题目描述:
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""
。
示例 1:
输入: ["flower","flow","flight"]
输出: "fl"
示例 2:
输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z
。
这道题看题目描述和测试用例,会发现不是难题,就是一个字符串数组,求数组中的每个元素是否有公共的前缀,而且这个前缀必须的是最长。
但其实这道题很有深度,有好多种解法,什么二分查找,什么分治法等等。但我用的就是最直白的方法,两个for循环,理解起来也好理解,其他方法,我还在研究,本博客会不断补充,先将我的想法,思路和大家分享一下。
第一,要求最长的公共前缀,我想得现有一个字符串数组
第二,从数组中的第一个元素开始比较,将第一个元素的每一个字符和第二个元素,第三个。。。第i个元素的每一个字符进行比较,如果相同就建立一个字符串变量将相同的字符加起来,组成一个字符串(可能有点绕口,例如,【"flow","flower","flo"】,将flow中的每一个字符和其余的元素比较,f与第二第三相同,付给变量,l和第二第三元素的字符相同付给变量,等等最后,输出的变量就是flo),最后通过判断,输出
注:这个用到了变量存储相同字符,有好多种思路,
一用字符串str+=相同字符,
二,用stringbulider来append增加字符。
三,这个不是用来存储相同字符的方式,这种方式反其道而行之,用到了substring方法,就是字符串截取方法,当判断没有元素相同时,就输出第一个字符(因为是将第一个字符和其他元素字符比较)从下标为0,到没有相同元素的下标之间的字符就是相同字符,能比存储字符串简单一点,存储字符串比这个能好理解点。好了,说了这么多绕口的话,我们来看代码。因为容易理解。
代码如下:
public static void main(String[] args){
String []strs = {"flower","ulow","plight"};
最长公共前缀 zz = new 最长公共前缀 ();
System.out.println(zz.longestCommonPrefix ( strs ));
}
public String longestCommonPrefix(String[] strs) {
if (strs == null || strs.length == 0) return "没有";
for (int i = 0; i < strs[0].length() ; i++){
char c = strs[0].charAt(i);
for (int j = 1; j < strs.length; j ++) {
// 两种情况第一种,前缀等于数组元素的长度,flowower---flow(前缀的长度最大就是数组中长度最小的那个元素。)
// 第二种 从第一个字符开始,不相等时,就证明找到了,不相等字符之前的字符都是相等的。
if (i == strs[j].length() || strs[j].charAt(i) != c){
return (strs[0].substring(0, i)) ;
}
}
}
return null;
}
}
这个使用到了substring,也好理解,找到不相同的那个字符对应的下标,输出0-这个不相同字符下标的字符串就是要求的最长公共前缀
还有一种用stringbuilder的,效果一样,判断也一样,更好理解,相同就添加,不相同就输出,
代码如下:
用subtrings方法,要么用StringBuilder来作为每个字符的连接,当相等时,将相等字符,
添加到StringBUilde中,不相等,或者前缀长度等于小于i时,证明已经找到最大前缀了,输出sb。
//j == strs.length - 1意思是,如果第一个元素的字符与后面元素的字符相等时,
那么最后那一个元素的字符也相等于第一个元素的字符。就如同flot,flo,floa.f与后面两个相同,
如果一相等就保存的话,那么,就会重复,fflloo,但如果相同时,且j是最后一个元素下标时
(总元素个数减去第一个元素),那么这样添加就不会重复了,
f直等到一直重复到最后一个元素,然后就增加一次,这样不管数组中有多少个元素,这样的话就只保存相同的一次。
StringBuilder sb = new StringBuilder();
if (strs[j].length()==i ||strs[j].charAt(i) != c) {
return sb.toString();
}
if (strs[j].charAt(i) == c && j == strs.length - 1){
sb.append ( c );
代码中的注释就不用细看了,代码没多少东西,这种方法比较容易想到,简单粗暴。时间复杂度O(n),n为所有字符的数量。
但是没有其他方法好,而且不那么高大上,本人能力有限,只能想到这种,等学会答案中那几种方法了,会补充到后面。
执行结果:
程序用时:
第二种方法,比第一种简便更好理解,执行速度更快。这种方法让数组中的第一个元素成为前缀,然后循环字符串数组,判断数组中的每一个元素是否以声明的那个前缀一样,一样就不动,不一样就将声明的那个前缀从0-长度减一,循环知道找到每一个元素都开头的那个前缀。用到了字符串startswith方法和substring方法。
这种方法简便执行速度快,,代码更让加简便,用到了startsWith这个方法,
判断数组中的每一个元素是否以prefix开头,不是的话,让prefix-1,
在判断是否与数组中的元素相同.
public String longestCommonPrefix(String[] strs) {
String prefix=strs[0];
for (int i = 0;i<strs.length;i++){
while (!strs[i].startsWith ( prefix )){
prefix = prefix.substring ( 0,prefix.length ()-1 );
if (prefix.isEmpty()) return "";
}
}
return prefix;
}
执行用时:
总结:这道题看似简单,实际有很多需要想的地方,本人能力有限,想法不够只能想到这种方法,看到答案中许多优质的解答一时间觉得自己想问题太浅显了。其他方法还在慢慢消化,本博客会慢慢补充。
2019-1-19记录