Leetcode 14. 最长公共前缀
2019-07-19 14:53
363 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/LetJava/article/details/96477505
最后返回由左右边界确定的公共前缀即可。
题目
编写一个函数来查找字符串数组中的最长公共前缀。
如果不存在公共前缀,返回空字符串 “”。
示例 1:
输入: [“flower”,“flow”,“flight”]
输出: “fl”
示例 2:
输入: [“dog”,“racecar”,“car”]
输出: “”
解释: 输入不存在公共前缀。
说明:
- 所有输入只包含小写字母 a-z 。
解答
解法一:利用字典序
利用字符串排序时的字典序规则。
排序后,最小字符串和最大字符串的公共前缀即是所有字符串的公共前缀。
复杂度:O(m * nlogn) 的时间,O(1) 的空间
代码
class Solution { public String longestCommonPrefix(String[] strs) { if(strs == null || strs.length < 1) return ""; Arrays.sort(strs); String min = strs[0]; String max = strs[strs.length - 1]; StringBuilder stb = new StringBuilder(); for(int i = 0; i < min.length(); i++) { if(max.charAt(i) == min.charAt(i)) { stb.append(max.charAt(i)); } else { break; } } return stb.toString(); } }
结果
解法二:水平扫描
具体如下:
- 让公共前缀初始化为第一个字符串。
- 然后不断的向后迭代,不断地缩减公共前缀 prefix 的长度。
复杂度:O(m * n) 的时间,O(1) 的空间。
代码
class Solution { public String longestCommonPrefix(String[] strs) { if(strs == null || strs.length == 0) return ""; String prefix = strs[0]; for(int i = 1; i < strs.length; i ++) { String str = strs[i]; while(str.indexOf(prefix) != 0) { prefix = prefix.substring(0, Math.min(str.length(), prefix.length() - 1)); } } return prefix; } }
结果
解法三:垂直扫描
垂直扫描上述思路略有不同,垂直扫描比较的是每个字符串相同位置的字符是否相同。
从第一个位置开始迭代,一旦发现有任何一个字符串在当前位置的字符与其他的不同,那么此位置就是最大前缀的边界点。
复杂度:O(m * n) 的时间,O(1) 的空间。
代码
class Solution { public String longestCommonPrefix(String[] strs) { if(strs == null || strs.length == 0) return ""; StringBuilder res = new StringBuilder(); for(int i = 0; i < strs[0].length(); i ++) { char ch = strs[0].charAt(i); for(int j = 1; j < strs.length; j ++) { String str = strs[j]; if(i >= str.length() || str.charAt(i) != ch) { return res.toString(); } } res.append(ch); } return res.toString(); } }
结果
解法四:二分法
类似于解法二,不同的是公共前缀的确定使用了二分法,每次都对当前的前缀长度加倍或减半。
主要思路:
- 先找到最短的字符串长度,因为最大公共前缀的长度不会超过最短的字符串长度 minLen 。
- 采用二分法: 如果当前的前缀是所有字符串的公共前缀,那么就尝试将当前的前缀长度加倍。
- 否则,让当前的前缀长度减半。
复杂度:O(m * nlogn) 的时间,O(1) 的空间。
代码
class Solution { public String longestCommonPrefix(String[] strs) { if(strs == null || strs.length < 1) return ""; int minLen = strs[0].length(); for(int i = 1; i < strs.length; i ++) { minLen = Math.min(minLen, strs[i].length()); } int low = 1; int high = minLen; while(low <= high) { int mid = (low + high) >>> 1; if(isCommonPrefix(strs, mid)) { low = mid + 1; } else { high = mid - 1; } } return strs[0].substring(0, (low + high) >>> 1); } private boolean isCommonPrefix(String[] strs, int len) { String prefix = strs[0].substring(0, len); for(int i = 1; i < strs.length; i ++) { if(!strs[i].startsWith(prefix)) return false; } return true; } }
结果
解法五:分治法
采用归并排序的思想,不断融合字符串的公共前缀。
复杂度:O(m * n) 的时间,O(m * logn) 的空间。
代码
class Solution { public String longestCommonPrefix(String[] strs) { if(strs == null || strs.length == 0 4000 ) return ""; return merge(strs, 0, strs.length - 1); } private String merge(String[] strs, int start, int end) { if(start == end) return strs[start]; int mid = (start + end) >>> 1; String left = merge(strs, start, mid); String right = merge(strs, mid + 1, end); return mergePrefix(left, right); } private String mergePrefix(String s1, String s2) { if(s1.equals(s2)) return s1; int minLen = Math.min(s1.length(), s2.length()); for(int i = 0; i < minLen; i ++) { if(s1.charAt(i) != s2.charAt(i)) return s1.substring(0, i); } return s1.substring(0, minLen); } }
结果
扩展解法:Trie 字典树
使用 Trie 数据结构,将单词存储在一颗多叉树上。
对 Trie 不太了解的同学可以看一下:Leetcode 208. 实现 Trie (前缀树)
对于本题,需要注意所有字符串的公共前缀必须满足的条件:
- 当前结点的 next 数组有效长度必须为 1 。(不能有分叉)
- 当前结点不是某一个字符串的结束点。(当前结点不是单词的结束结点)
复杂度:O(m * n) 的时间,O(m * n) 的空间。
代码
class Solution { class Node { boolean isWord; int size; Node[] next = new Node[26]; } private Node root = new Node(); public String longestCommonPrefix(String[] strs) { if(strs == null || strs.length == 0) return ""; for(int i = 0; i < strs.length; i ++) { if(strs[i].length() == 0) return ""; addWord(strs[i]); } return getLongestPrefix(strs[0]); } private void addWord(String word) { Node p = root; for(int i = 0; i < word.length(); i ++) { char ch = word.charAt(i); if(p.next[ch -'a'] == null) { p.next[ch - 'a'] = new Node(); p.size ++; } p = p.next[ch - 'a']; } p.isWord = true; } private String getLongestPrefix(String word) { Node p = root; for(int i = 0; i < word.length(); i ++) { char ch = word.charAt(i); if(p.size != 1 || p.isWord) { return word.substring(0, i); } else { p = p.next[ch - 'a']; } } return word; } }
结果
相关文章推荐
- Leetcode(14) 最长公共前缀
- LeetCode-14-Longest Common Prefix(最长公共前缀)
- leetcode14. 最长公共前缀
- LeetCode 14. 最长公共前缀
- LeetCode_Q14_最长公共前缀
- 【leetcode每日一题】【2019-05-20】14. 最长公共前缀
- 力扣(LeetCode 14)最长公共前缀 python
- [算法Rust,Go,Python,JS实现)]LeetCode之14-最长公共前缀
- leetcode_14. 最长公共前缀(python)
- leetcode-14-求字符串数组最长公共前缀
- LeetCode题解(python)-14. 最长公共前缀
- Leetcode14. 最长公共前缀
- 【LeetCode】14. 最长公共前缀
- LeetCode——14 最长公共前缀
- LeetCode 14 Longest Common Prefix(最长公共前缀)
- LeetCode 14 Longest Common Prefix(最长公共前缀)(String)
- 【LeetCode】[14] 最长公共前缀
- LeetCode - 14. 最长公共前缀
- [C++]LeetCode 14: Longest Common Prefix(最长公共前缀)
- LeetCode 14 最长公共前缀(字符串)