3

我终于像我想要的那样做了。谢谢大家的帮助,我想强调这不是家庭作业。

public static void main(String[] args) {
    String input = "Java is a programming language";
            StringTokenizer st = new StringTokenizer(input);
    System.out.print(longestWord(input));

}

public static String longestWord(StringTokenizer st) {
    if (!st.hasMoreTokens()) {
        return "";

    } else {
        String token = st.nextToken(); 
        String longestInTheRest = longestWord(st);
        if (token.length() > longestInTheRest.length()) { 

            return token;

        } else {
            return longestInTheRest;
        }
4

7 回答 7

3

以下内容不太正确:

else if (token.length() > result.length()) {

当上述语句执行时,result总是" ".

该函数应该做的是返回较大的:(1)长度token;(2) 递归调用返回的单词的长度。

您可能还会考虑这两个s.substring()调用是否完全符合您的要求,或者是否可能存在问题。打印出来tokenrest(或在调试器中检查它们)可能很有用。

由于这看起来像家庭作业,我会在这里停下来。

于 2012-01-15T12:48:33.593 回答
1

另一种解决方案,以更实用的风格编写 - 请注意,我没有在每次调用递归方法时分配新字符串(只有split开头的操作分配新字符串)。我还接受了 Robert 的建议,即首先将原始问题转换为对数组的递归,它使事情变得更简单:

public static String longestWord(String s) {
    return longestWord(s.split("\\s+"), 0, 0);
}

public static String longestWord(String[] words, int currentIdx, int longestIdx) {
    if (currentIdx == words.length)
        return words[longestIdx];
    return longestWord(words, currentIdx + 1,
        words[currentIdx].length() > words[longestIdx].length() ? currentIdx : longestIdx);
}

上述解决方案中的技巧是我的递归在字符串数组的索引上前进,而不是在字符串本身上。这就是我避免在每次调用时创建新字符串的原因。不需要substring, copyOfRange,或类似的操作arraycopynew String()从而产生更优雅的解决方案。

编辑:

我稍微简化了上面的代码,以便于理解。关于split方法,它是标准的字符串操作,请查看文档

public static String longestWord(String s) {        
    return longestWord(s.split(" "), 0, 0);
}

public static String longestWord(String[] words, int currentIdx, int longestIdx) {
    if (currentIdx == words.length)
        return words[longestIdx];
    int idx;  // temporarily stores the index of the current longest word
    if (words[currentIdx].length() > words[longestIdx].length())
        idx = currentIdx;
    else
        idx = longestIdx;
    return longestWord(words, currentIdx + 1, idx);
}
于 2012-01-15T14:48:00.127 回答
1

您正在将当前单词与结果进行比较,但结果是一个始终设置为的局部变量" "(顺便说一句,它不是空字符串,而是一个包含空格的字符串)。

您应该将当前结果作为参数传递给该方法,并以空字符串作为结果开始。

您还有一个错误,因为您没有修剪标记,因此将前导空格视为单词的一部分。

于 2012-01-15T12:50:44.867 回答
0

您需要测试是否有剩余空间。

就像是

int index = s.indexOf(' ');
if (index < 0) return s;
于 2012-01-15T12:52:14.213 回答
0

为了递归工作,你需要传递一个当前状态,当前最长的单词来比较。

如果看起来像家庭作业,所以我不包括答案——如果不是,请告诉我。

于 2012-01-15T12:48:07.660 回答
0
    result = token;
    return longestWord(rest);

这是错误的部分。result 保存令牌,但随后退出方法,再次输入并将结果设置为“”。将另一个参数 String currentLongest 添加到方法签名中,这样它就不会丢失。

于 2012-01-15T12:49:02.543 回答
0

我会采取稍微不同的方法来解决这个问题:

首先,我会将字符串转换为更适合递归方法的数组。

public static String longestWord(String string) {
    return longestWord(string.split(" "), "");
}

然后我们可以考虑递归的方法。如果我们递归地传入一个较小的数组,我们知道我们最终会传入一个空数组——这是我们的基本情况,我们已经枚举了所有元素,所以只返回作为参数传入的最长的数组。在递归的情况下,我们检查(现在更小的)数组的第一个元素是否比当前最长的元素长,并递归调用传入两者中较长的一个。

private static String longestWord(String[] strings, String currentLongest) {
    if (strings == null || strings.length == 0) {
        return currentLongest;
    }
    String[] newStrings = Arrays.copyOfRange(strings, 1, strings.length);
    String longest = strings[0].length() < currentLongest.length() ? currentLongest : strings[0];
    return longestWord(newStrings, longest);
}

注意:这也可以通过在数组中使用索引来实现,而不是复制它。然而,在实践中,这是一种太过分的优化——它使阅读变得更加困难,并且不太可能使任何人受益。

于 2012-01-15T13:48:50.950 回答