刷Leetcode算法的第一天

序言

今天是刷LT的一天,好好干饭,好好努力,好好加油哦!

  1. 第一题

题目描述:
找到几个字符串中最长公共前缀。

例子如下:

Input: ["flower","flow","flight"]
Output: "fl"
Input: ["dog","racecar","car"]
Output: ""

方法一
解析思路:
这里需要使用的的是zip函数和set函数,先理解这两个函数的用法再做这道题。

(1) zip() vs zip(*)

zip()函数作用于可迭代的对象,将对象对应的元素组成一个个元组
然后返回这些元组的列表, 例子如下:

a = [1, 2, 3]
b = ["a", "b", "c"]

list(zip(a, b))  #用list列出来
输出为:[(1, 'a'), (2, 'b'), (3, 'c')]

zip(*)函数则相反,起到解压的作用,
例子如下:

example = ["flower", "flow", "flqwe"]
list(zip(*example))
输出为:[('f', 'f', 'f'), ('l', 'l', 'l'), ('o', 'o', 'q'), ('w', 'w', 'w')]

(2)set()函数

set() 函数创建一个无序不重复元素集,可用于删除重复值。例子如下

a = set('abcdd')
b = set('cdeff')
a
b
输出为:
{
    
    'a', 'b', 'c', 'd'}
{
    
    'c', 'd', 'e', 'f'}
a & b #交集 
输出为 {
    
    'c', 'd'}
a | b #并集 
输出为 {
    
    'a', 'b', 'c', 'd', 'e', 'f'}

回到之前的题目,需要返回列表中的几个字符中共同前缀。

Input: ["flower","flow","flight"]
Output: "fl"

首先,用zip(*)把列表的几个字符解压出来,把input解压出来,变成[(‘f’, ‘f’, ‘f’), (‘l’, ‘l’, ‘l’), (‘o’, ‘o’, ‘q’), (‘w’, ‘w’, ‘w’)], 然后用set函数去掉重复值,变成[(‘f’), (‘l’), ( ‘o’, ‘q’), (‘w’)],最后用一个if函数,只取其中set后长度为1的字符。Python如下:

def longestCommonPrefix(strs) -> str:
    opt = ''
    for i in zip (*strs):     #zip (*strs) 即是解压组合出来
        if len(set(i))==1:    #针对set后长度为1的字符
            opt += i[0]       #录入字符
        else:
            break
    return opt

方法二:
把列表的第一个字符串作为标准,跟剩余的其他字符串比较。而两个字符串的比较使用二分法来比较,最后的时间复杂度为O(N*log(N))。跟第一个方法的时间复杂度相比好很多。

使用一个例子来理解两个字符串的二分法是:
str = {leets, leetcode, leetc, leed}
首先,leets 从中间拆开,5//2 = 2 即leets 分为 lee 和 ts
然后,检查lee 是否 in {leetcode, leetc, leed} 一致通过
再然后,把t加入lee 为leet,再次检查leet 是否 in {leetcode, leetc, leed} 并没有一致通过
所以直接返回 lee为最长公共前缀。用这个方法执行起来更快。

首先理解find函数用法,可以检测字符串中是否包含子字符串
find()函数语法 :string.find(str, beg=0, end=len(string))

  1. str : 指定检索的字符串
  2. beg :开始索引,默认为0
  3. end :结束索引,默认为字符串的长度

如果指定 beg(开始) 和 end(结束) 范围,则检查是否包含在指定范围内
如果包含子字符串返回开始的索引值,否则返回-1
例子:

str1 = "AppleandDoctor"
str2 = "and"
print(str1.find(str2))     #没有任何指定范围,默认整个字符串范围
print(str1.find(str2, 1))  #指定从位置为1的开始检索
print(str1.find(str2, 10)) #指定从位置为10的开始检索
输出
5
5
-1

所以定义PassorNot函数 检测字符是否全部通过

def PassorNot(strs,mid):
  s = strs[0][0:mid]
  #检测剩余的其他字符串
  for i in range(1,len(strs)):
    #如果出现了不通过的情况,则马上return false
    if strs[i].find(s)!=0:
      return False
  #如果都通过,即剩余的字符串都包含s,则return True
  return True

现在可以定义整个函数

def longestCommonPrefix(strs):
  '''
  :strs: List type 包含多个字符串的列表
  返回最长的公共前缀
  '''
  #取列表中的第一个字符串作为标准比较
  low, high = 1,len(strs[0]) 
  while low <= high:
    mid = (low + high)//2
    if PassorNot(strs,mid):
      low = mid + 1
    else:
      high = mid - 1

  return strs[0][0:(low+high)//2]
  1. 题目二

题目描述:
给定一个 haystack 字符串和一个 needle 字符串,在 haystack 字符串中找出 needle 字符串出现的第一个位置 (从0开始)。如果不存在,则返回 -1。

例子如下:

输入: haystack = "hello", needle = "ll"
输出: 2
输入: haystack = "aaaaa", needle = "bba"
输出: -1

解析思路:
直接根据条件来,用多个if 来筛选。

def strStr(haystack,needle):
    lh = len(haystack)         #haystack的长度
    ln = len(needle)           #needle的长度
    if ln == 0:                #当needle为空集return0
        return 0 
    if lh == 0 or lh < ln:     #当不符合条件无法查找 return -1
        return -1
    i = 0
    while(i<=lh-ln):           
        if haystack[i] == needle[0]:    
        #当出现和needle第一个字母相同的字符时,测试后面的是否一致。   
            if haystack[i:i+ln] == needle:
            #记住[i:i+ln]字符提取是取前不取后,即i+ln的字符是没有取到的。
                return i
            else:
                i+=1
        else:
            i+=1
    return -1 

猜你喜欢

转载自blog.csdn.net/Jiana_Feng/article/details/114651030