我知道子字符串的工作原理,但是我试图在下面的代码中了解它的工作原理。目的是在字符串数组中找到最长的公共前缀。字符串输入为{flower,flow,fleece}。看起来子串每次都只花整个单词,当它不为0时,每次,因为length-1的0将给出整个单词。
public String longestCommonPrefix(String[] strs) {
if (strs.length == 0) return "";
String prefix = strs[0];
for (int i = 1; i < strs.length; i++)
while (strs[i].indexOf(prefix) != 0) {
prefix = prefix.substring(0, prefix.length() - 1);
if (prefix.isEmpty()) return "";
}
return prefix;
}
输出是fl。我只是想了解原因。
答案 0 :(得分:1)
长度为1的0将给出整个单词
不,它返回除最后一个字符以外的单词。
发件人:https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#substring(int,%20int)
public String substring(int beginIndex,int endIndex)
返回一个 作为此字符串的子字符串的新字符串。
子字符串 从指定的beginIndex开始,并扩展到位于的字符 index endIndex-1.
因此,代码要做的是用此行修剪每次迭代中的最后一个字符:
prefix = prefix.substring(0, prefix.length() - 1);
直到找到通用前缀。
答案 1 :(得分:1)
substring()中的endIndex是排他的。因此,代码要做的是从前缀变量中删除最后一个字符。
String hello = "hello";
System.out.println(hello.substring(0,hello.length));
// hello
System.out.println(hello.substring(0,hello.length - 1));
// hell
答案 2 :(得分:0)
虽然这不是您直接要问的问题,但值得一提的是,使用indexOf
和substring
并不是解决此问题的好方法。
strs[i].indexOf(prefix) != 0
是检查字符串是否以某些内容开头的低效方法。这是因为,如果发现字符串不是以prefix
开头,它将继续搜索其他位置的出现-并不会出现在该位置。
更有效的检查是!strs[i].startsWith(prefix)
:一旦发现字符串不是以前缀开头,它就会停止。
然后,使用substring
将字符从字符串末尾切掉也是无效的:每次将一个字符切掉,都会创建一个新的字符串,然后再次检查;但是在找到匹配的前缀之前,您可能必须先砍掉很多个单个字符。
您可以通过使用strs[i].regionMatches(0, prefix, 0, someLength)
来避免这种“创建对象”的问题,其中someLength
是一个以prefix.length()
开头的int,然后递减直到{{1} }返回true。但这仍然效率不高,因为您一次将其递减一次。
以另一种方式进行操作会更容易:以regionMatches
从零开始,然后递增直到出现以下两种情况:
someLength
的长度:prefix
someLength >= prefix.length()
的长度:strs[i]
someLength >= strs[i].length()
这基本上是prefix.charAt(someLength) != strs[i].charAt(someLength)
的工作,但是通过“自己”完成,您可以找出字符串不同的位置。
然后,使用startsWith
一次性将其切碎。或根本不切碎:您可以简单地存储公共前缀的长度,并在末尾执行一次子字符串。
代码类似于:
prefix = prefix.substring(0, someLength);