最长公共前缀
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
示例 1:
输入:strs = ["flower","flow","flight"]
输出:"fl"
示例 2:
输入:strs = ["dog","racecar","car"]
输出:""
解释:输入不存在公共前缀。
提示:
1 <= strs.length <= 200
0 <= strs[i].length <= 200
strs[i] 仅由小写英文字母组成
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-common-prefix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
思路及解析:
这道题花费了我将近三个小时,也是本人比较菜的原因
在一开始的时候选择了的思路:
以第一个为基础,不断地截取第一个元素,
str = strs[0].substring(0,subLength); 然后继续字符串数组内的元素进行比较, 依次比较每一个strs[i].stratWith(str),都是以str开头的就开始第二轮遍历 第一轮遍历结束subLength++ 直到找到不相同的字符开始停止遍历、退出循环如代码所示:
// int i=1; // boolean flag = true; // //首先需要遍历strs中的元素 // //获取第一个元素当中的第一个字符 // str = ""+strs[0].charAt(0); //// System.out.println("str: "+str); // //定义第一个元素的下标 // int curStr = 0; // int count = 0; // while(i<strs.length&&curStr<=strs[0].length()) { // // // if(!strs[i].startsWith(str)) { //// System.out.println("出现不同了"); //// System.out.println("当前curStr:"+curStr+", 当前count: "+count+",当前遍历strs[i]: "+strs[i]); // flag=false; // break; // } //// if(curStr==0) { // if(curStr+1<=strs[0].length()) { // str = strs[0].substring(0, curStr+1); // } // //// }else { //// str = strs[0].substring(0, curStr); //// } // // curStr++; // //// System.out.println("当前第"+(count)+"次: "+str+""); // i++; // if(curStr<=strs[0].length()&&i>=strs.length) { // System.out.println("当前i:"+i); // i=1; // if(curStr<strs[0].length()){ //// System.out.println("当前str"); // curStr--; // } // // } // count++; // } // if(!flag&&count==0) { // // str=""; // } // else { // System.out.println("curStr:"+curStr); // if(curStr>1) { // str = strs[0].substring(0, curStr-1); // }else { // str = strs[0].substring(0, curStr); // } // // // } //// System.out.println(str); return str;
这种思路导致的结果在于对第一个元素的长度不确定,在我看来要考虑非常多的数组越界问题,思路较为混乱,结果失败了(当然看了别人的题解后发现以第一个也是很简单的)
后来在朋友的一番点醒下,我选择了另外一条遍历的方法
于是乎我采用了另外一种思路
- 首先遍历循环找出最短的那一个字符串、并设它为参照对象,提取当前字符串的首字母值str = curStr.subString(0,1) 和当前字符串的长度 curStr.length (循环次数)
- 遍历当前字符串的长度 此时截取的长度为subLength = 1、定义一个flag=true变量是否应该退出外循环
- 截取了当前字符串的长度开始循环与每一个字符串数组内的字符串进行比较
- 当出现了不一样的时候退出循环 、flag=false(出现了不一样已经没有必要循环遍历了) --- 如果strslength小于strs.length的时候说明第一次循环不通过、定义firstPass=false
- 一样的时候strsLength++ -->当前strslength是用来判断是否第一次循环,当不满足第一次循环的时候应该返回空窜
- 截取了当前字符串的长度开始循环与每一个字符串数组内的字符串进行比较
2. 如果flag==true subLength++ 如果flag==false 结束外循环
3. 当一直遍历,该最短字符串就是就是最大的公共窜的时候也应该退出循环 subLength>curStr.length
4.str = curStr.substring(0,subLength); 继续循环
3. 判断是否第一次循环都不过,返回空窜
4. 判断是否只有一个元素,返回当前元素
5.判断是否含有空窜,返回空窜
6.返回str
代码如下:
class Solution { public String longestCommonPrefix(String[] strs) { //如果含有空窜,返回空窜 for (String string : strs) { if("".equals(string)) { return ""; } } //如果当前只有一个元素,返回当前元素 if(strs.length==1) { return strs[0]; } String str = ""; //找出最短的字符串,并将它设为参照 //定义一个长度 int strLength = strs[0].length(); //定义index第几个元素 int strIndex = 0; //当前字符串 String curStr = strs[0]; //找到最短的字符串 for (String string : strs) { if(strLength>string.length()) { strLength = string.length(); //当前字符串赋给curStr curStr = string; } } System.out.println("strLength: "+strLength+", curStr: "+curStr); //遍历每一个元素查看是否相同 //定义一个截取长度 int subLength = 1; str = curStr.substring(0,subLength); boolean firstPass = true; int strsLength = 0; while(subLength<=curStr.length()) { boolean flag = true; for (String string : strs) { //如果相同,截取长度+1 if(!string.startsWith(str)) { System.out.println("当前sttring: "+string+", str: "+str); flag = false; if(strsLength<strs.length) { firstPass = false; } break; } strsLength++; } if(flag) { subLength++; } if(!flag) { break; } System.out.println("str: "+str+", subLength: "+subLength+", flag: "+flag); if(subLength>curStr.length()) { break; } str = curStr.substring(0,subLength); } System.out.println("当前str: "+str+", subLength: "+subLength+", "); //由于在一开始subLength=1 所以一直是提前的方式进行判断,在未达到数组越界前出来的话多1,需要减去 if(subLength<=curStr.length()) { str = curStr.substring(0,subLength-1); } if(!firstPass) { str=""; } return str; } }
测试结果: