LeetCode第14题
/*
Write a function to find the longest common prefix string amongst an array of strings
If there is no common prefix, return an empty string ""
Example 1:
Input: ["flower","flow","flight"]
Output: "f1"
Example 2:
Input: ["dog", "racecar","car"]
Output: ""
Explanation: There is no common prefix among the input strings.
Note: All given inputs are in lowercase letters a-z
*/
import java.util.*;
public class LongestCommonPrefix{
public static void main(String[] args){
LongestCommonPrefix lcp = new LongestCommonPrefix();
String[] strs = {"123","1234849","1234745381"};
String result = lcp.longestCommonPrefix05(strs);
System.out.println(result);
//Arrays.asList 输入的必须是对象
// Integer[] numbers = { 8, 2, 7, 1, 4, 9, 5};
// System.out.println((int)Collections.min(Arrays.asList(numbers)));
// System.out.println(Arrays.asList(8, 2, 7, 1, 4, 9, 5));
// System.out.println(Arrays.asList("Larry", "Moe", "Curly"));
}
/*
0,1,2,3,4,5,6分裂
0,1,2,3 4,5,6//分裂
0,1 2,3 4,5 6//分裂
0 1 2 3 4 5 6//只剩一个,没有办法分了,将自己返回(分裂,合并)
01 23 45 6//对返回的数取公共值
0123 456//再次对返回的数取公共值
0123456//再次对返回的数取公共值
递归总的来说,是一个V字路径,最低点就是停止条件
*/
public String longestCommonPrefix05(String[] strs) {
if(strs == null || strs.length == 0) return "";
return longestCommonPrefix(strs, 0 , strs.length - 1);
}
public String longestCommonPrefix(String[] strs,int Left,int Right){
// 停止条件,只输入一个元素,即Left == Right
// 最底层的递归处理
if (Left == Right)
// 等价于返回公共前缀
return strs[Left];
// 写代码的时候,可以先写下面的,最后考虑上面的停止情况
int mid = (Left + Right)/2;
// 有点二叉树的感觉,返回值从只有一个元素的时候开始返回
String LeftPrefix = longestCommonPrefix(strs,Left,mid);
String RightPrefix = longestCommonPrefix(strs,mid+1,Right);
// 对获得的返回值取公共前缀,先划分的后获取公共前缀
// 逻辑上一层递归是一个可执行的块,只要对最底层的递归做特殊处理
int i=0;
// 这里不能使用随机的长度循环,因为循环内部没有做溢出判断的类似语句
for (;i < Math.min(LeftPrefix.length(),RightPrefix.length());i++){
if (LeftPrefix.charAt(i) != RightPrefix.charAt(i)) break;
}
// 等价于返回公共前缀
return LeftPrefix.substring(0,i);
}
// 水平比较
public String longestCommonPrefix04(String[] strs) {
if(strs == null || strs.length == 0) return "";
//前面已经保证strs有元素
String curMinPrefix = strs[0];
for(int i = 1;i<strs.length;i++){
// 返回值int
int minLen = Math.min(curMinPrefix.length(),strs[i].length());
int preLen = 0;
for(int j=0;j<minLen;j++){
if (curMinPrefix.charAt(j) != strs[i].charAt(j)) break;
preLen++;
}
// 只輸入一個參數,表示是的是起始索引;两个输入是左闭右开
curMinPrefix = curMinPrefix.substring(0,preLen);
}
return curMinPrefix;
}
// 优化
public String longestCommonPrefix03(String[] strs) {
// 输入检验,要做
if (strs == null || strs.length == 0) return "";
String pre = "";
// 可以选取任何一个字符串作为循环限制,因为strs[0].length() >= minLen
for (int i = 0;i < strs[0].length();i++){
char temp = strs[0].charAt(i);
for (String str:strs){
// 达到一个字符串的行尾,或指定位置字符不完全匹配
//循环内部没有做溢出判断的类似语句
if(i == str.length() || str.charAt(i) != temp) return pre;
}
pre += temp;
}
return pre;
}
// 优化
public String longestCommonPrefix02(String[] strs) {
// 输入检验,要做
if (strs == null || strs.length == 0) return "";
String pre = "";
// 可以选取任何一个字符串作为循环限制,因为strs[0].length() >= minLen
for (int i = 0;i < strs[0].length();i++){
char temp = strs[0].charAt(i);
boolean flag = false;
for (String str:strs){
// 达到一个字符串的行尾,或指定位置字符不完全匹配
//循环内部没有做溢出判断的类似语句
if(i == str.length() || str.charAt(i) != temp) flag = true;
}
if (flag) break;
pre += temp;
}
return pre;
}
public String longestCommonPrefix01(String[] strs) {
// 输入检验,要做
if (strs == null || strs.length == 0) return "";
// List的子类有ArrayList(数组),LinkedList(双向链表)
List<Integer> lenList = new ArrayList<Integer>();
for (String str:strs){
lenList.add(str.length());
}
// Collections类里面有好多好用的方法
// lenList里面没有元素,则会报 java.util.NoSuchElementException 异常
int min = (int)Collections.min(lenList);
String pre = "";
for (int i = 0;i < min;i++){
char temp = strs[0].charAt(i);
boolean flag = false;
for (String str:strs){
if(str.charAt(i) != temp) flag = true;
}
// break只能跳出最近的一个循环
if (flag) break;
pre += temp;
}
return pre;
}
}