LeetCode Notes_#14 Longest Common Prefix

LeetCode Notes_#14 Longest Common Prefix

Contents

Problem

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: "fl"

Example 2:

Input: ["dog","racecar","car"]
Output: ""
Explanation: There is no common prefix among the input strings.

Solution

思路

寻找最长的公共前缀,我的想法是直接从第一个字母开始遍历,设置一个flag代表是否有共同的前缀。

#try:截取一个字符串的一部分
a='string'
a[0:2]
'st'
  1. #遇到一个大小写问题,意识到动态语言的缺点了... 
  2. Input=["flower","flow","flight"] 
  3. InputLen=[] 
  4. MinLen=0 
  5. flag=1 
  6. TmpList=[]#用于存储每个字符串的前缀 
  7. for i in range(len(Input)): 
  8. InputLen.append(len(Input[i])) 
  9. MinLen=min(InputLen) 
  10.  
  11. for j in range(1,MinLen): 
  12. # print(flag) 
  13. TmpList=[] 
  14. if flag:#前面的前缀相同了,我才继续往后去尝试 
  15. for k in range(len(Input)):#遍历每个单词 
  16. TmpList.append(Input[k][0:j])#依次取每个单词的前面j个字符,加入列表 
  17. print(TmpList) 
  18. if len(set(TmpList))!=1: 
  19. flag=0#这时刚好开始出现不同,那么前j-1个相同 
  20. print (Input[0][0:j-1]) 
  21.  
['f', 'f', 'f']
['fl', 'fl', 'fl']
['flo', 'flo', 'fli']
fl
#一些corner case,emmmm
[]
[""]
["",""]
["a","aa"]
["c","c"]
[""][0]#这种情况就不可以用二重下标了
''
'a'[0]
'a'
'a'[0:1]
'a'

解答

  1. class Solution(object): 
  2. def longestCommonPrefix(self, strs): 
  3. """ 
  4. :type strs: List[str] 
  5. :rtype: str 
  6. """ 
  7. if strs==[]: 
  8. return '' 
  9. if '' in strs: 
  10. return '' 
  11. if len(strs)==1: 
  12. return strs[0]  
  13. if len(set(strs))==1: 
  14. return strs[0] 
  15.  
  16. InputLen=[] 
  17. MinLen=0 
  18. flag=1 
  19. TmpList=[]#用于存储每个字符串的前缀 
  20. for i in range(len(strs)): 
  21. InputLen.append(len(strs[i])) 
  22. MinLen=min(InputLen) 
  23. # print MinLen 
  24. # print range(1) 
  25.  
  26. for j in range(MinLen): 
  27. # print(flag) 
  28. TmpList=[] 
  29. if flag:#前面的前缀相同了,我才继续往后去尝试 
  30. for k in range(len(strs)):#遍历每个单词 
  31. TmpList.append(strs[k][0:j+1])#依次取每个单词的前面j个字符,加入列表 
  32. # print(TmpList) 
  33. # print j,k,TmpList 
  34. # print len(set(TmpList)) 
  35. if len(set(TmpList))!=1: 
  36. flag=0#这时刚好开始出现不同,那么前j-1个相同 
  37. # print j 
  38. if j>=1: 
  39. return strs[0][0:j]  
  40. else: 
  41. return '' 
  42. elif (len(set(TmpList))==1 and j==MinLen-1): 
  43. return TmpList[0] 

28ms,faster than 57.76%
这些corner case有点烦人...这代码有点辣鸡,很多的for还有if else...

高票答案

  1. class Solution: 
  2. # @return a string 
  3. def longestCommonPrefix(self, strs): 
  4. if not strs: 
  5. return "" 
  6.  
  7. for i, letter_group in enumerate(zip(*strs)): 
  8. if len(set(letter_group)) > 1: 
  9. return strs[0][:i] 
  10. else: 
  11. return min(strs) 

看看人家这个代码多优雅...用了一些python中比较高级的用法。
所以所谓精通一门语言,就是要会使用这门语言里边特有的一些用法去缩短代码,提高效率,提高可读性。
而不是说每一门语言我都只会用最基本的循环,if...else...解决问题,那样就没有了深入学习一门语言的意义。

  • enumerate()
    Python 内置的 enumerate 函数可以把一个 list 变成索引-元素对,这样就
    可以在 for 循环中同时迭代索引和元素本身
for i, value in enumerate(['A', 'B', 'C']): 
    print(i, value) 
0 A
1 B
2 C
  • zip()
    zip() 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的对象,这样做的好处是节约了不少的内存。

我们可以使用 list() 转换来输出列表。

如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同,利用 * 号操作符,可以将元组解压为列表。

strs=["asd","sdfa"]
list(zip(*strs))
[('a', 's'), ('s', 'd'), ('d', 'f')]

Java

更好的思路是纵向比较,即外层循环是元素下标,内层循环是strs数组的下标。比较strs数组当中每个字符串相同位置是字符是否相同,遇到不同的,说明在此之前的子字符串就是最长的公共前缀。

class Solution {
    public String longestCommonPrefix(String[] strs) {
        if(strs == null || strs.length == 0) return "";
        int arrayLength = strs.length;
        int firstStrLength = strs[0].length();
        for(int i = 0;i < firstStrLength;i++){
            char c = strs[0].charAt(i);
            for(int j = 0;j < arrayLength;j++){
                if(i == strs[j].length() || strs[j].charAt(i) != c){
                    return strs[0].substring(0, i);
                }
            }
        }
        return strs[0];
    }
}
posted @ 2018-10-19 11:54  Howfar's  阅读(193)  评论(0编辑  收藏  举报