编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 ""。
示例 1:
输入: ["flower","flow","flight"]
输出: "fl"
示例 2:
输入: ["dog","racecar","car"]
输出: ""
解释: 输入不存在公共前缀。
说明:
所有输入只包含小写字母 a-z 。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-common-prefix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
字符串匹配这块是我的弱项。
水平扫描
我们每次的关注点应该是后一位。这个方法是真的奇特,我是想不出这么怪异的方式。
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; }
水平扫描2
之前的是对字符串进行块级别扫描,现在是对字符级别
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++) { if (i == strs[j].length() || strs[j].charAt(i) != c) return strs[0].substring(0, i); } } return strs[0]; }
这个问题再分析一下,就是一组数据,我们找出其中的“公共量”,不过多的思考,是否可以将其分成两组,让两个人同时找,找完了再合在一块找?这就是分治的思路。
其实我们前几个方法,都没用上算法的思维,有点暴力,虽然看起来也是巧妙的,但是毫无疑问,那也是易错且复杂的思路,做算法题就是找简单的方法,用上正常的看待问题的思路,我们这种分治思路就是日常生活中很常见的思路,理解起来简单且逻辑清晰。
public String longestCommonPrefix(String[] strs) { if (strs == null || strs.length == 0) return ""; return longestCommonPrefix(strs, 0 , strs.length - 1); } private String longestCommonPrefix(String[] strs, int l, int r) { if (l == r) { return strs[l]; } else { int mid = r + (l - r) / 2; String lcpLeft = longestCommonPrefix(strs, l , mid); String lcpRight = longestCommonPrefix(strs, mid + 1,r); return commonPrefix(lcpLeft, lcpRight); } } String commonPrefix(String left,String right) { int min = Math.min(left.length(), right.length()); for (int i = 0; i < min; i++) { if ( left.charAt(i) != right.charAt(i) ) return left.substring(0, i); } return left.substring(0, min); }
二分查找方式
二分查找的效率之处在于他们快速去除一半的不可能区间。
public String longestCommonPrefix(String[] strs) { if (strs == null || strs.length == 0) return ""; int minLen = Integer.MAX_VALUE; for (String str : strs) minLen = Math.min(minLen, str.length()); int low = 1; int high = minLen; while (low <= high) { int middle = (low + high) / 2; if (isCommonPrefix(strs, middle)) low = middle + 1; else high = middle - 1; } return strs[0].substring(0, (low + high) / 2); } private boolean isCommonPrefix(String[] strs, int len){ String str1 = strs[0].substring(0,len); for (int i = 1; i < strs.length; i++) if (!strs[i].startsWith(str1)) return false; return true; }
双指针方式
public static String longgestCommonPrefix(String[] strs) { String result = ""; if (strs.length == 0 || strs == null) { return ""; } else if (strs.length == 1) { return strs[0]; } for (int i = 0; i < strs[0].length(); i++) { for (int j = 1; j < strs.length; j++) { if (i == strs[j].length() || strs[0].charAt(i) != strs[j].charAt(i)) { return result; } } result += strs[0].charAt(i); } return result; }