leetcode刷题
开始刷leetcode,记录下整个过程,留着慢慢学习和优化。
1.两数之和(Two sum)
#coding:utf-8 # 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。 # 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。 # 示例: # 给定 nums = [2, 7, 11, 15], target = 9 # 因为 nums[0] + nums[1] = 2 + 7 = 9 # 所以返回 [0, 1] #暴力遍历法,空间复杂度O(1),时间O(n2),3976ms class Solution(object): def twoSum(self, nums, target): """ :type nums: List[int] :type target: int :rtype: List[int] """ if nums==[]: return [] for i in range(len(nums)): for j in range(i+1,len(nums)): if nums[i]+nums[j]==target: return [i,j] #哈希表法,空间O(n),时间O(n),28ms class Solution(object): def twoSum(self, nums, target): """ :type nums: List[int] :type target: int :rtype: List[int] """ if nums==[]: return [] map={} for i in range(len(nums)): component = target-nums[i] if component in map: j = map.get(component) if i!=j: return [i,j] map[nums[i]]=i
2.两数相加(Add Two Numbers)
#coding:utf-8 # 给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。 # 如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。 # 您可以假设除了数字 0 之外,这两个数都不会以 0 开头。 # 示例: # 输入:(2 -> 4 -> 3) + (5 -> 6 -> 4) # 输出:7 -> 0 -> 8 # 原因:342 + 465 = 807 # Definition for singly-linked list. class ListNode(object): def __init__(self, x): self.val = x self.next = None class Solution(object): def addTwoNumbers(self, l1, l2): """ :type l1: ListNode :type l2: ListNode :rtype: ListNode """ sumNode = ListNode(0) s = sumNode n1=l1 n2=l2 quotient=0 while (n1!=None or n2!=None) : x = n1.val if n1 else 0 y = n2.val if n2 else 0 quotient,remainder = divmod(quotient+x+y,10) #商向前进一位,余数为当前val值 s.next = ListNode(remainder) s = s.next if n1!=None: n1=n1.next if n2!=None: n2=n2.next if quotient>0: #注意最后的商向前进一位 (2-0-8, 3-2-5) s.next = ListNode(1) #return sumNode.next out=[] node = sumNode.next while node: out.append(node.val) node = node.next return out # l1 = ListNode(2) # l1.next=ListNode(4) # l1.next.next=ListNode(3) # l2 = ListNode(5) # l2.next=ListNode(6) # l2.next.next=ListNode(4) # s = Solution() # t=s.addTwoNumbers(l1,l2) # print t
3. 无重复字符的最长子串 (Longest substring without repeating character)
#coding:utf-8 # 给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。 # 示例 1: # 输入: "abcabcbb" # 输出: 3 # 解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。 # 示例 2: # 输入: "bbbbb" # 输出: 1 # 解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。 # 示例 3: # 输入: "pwwkew" # 输出: 3 # 解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。 # 请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。 #时间复杂度O(2n),耗时88ms (列表作为滑动窗口) class Solution(object): def lengthOfLongestSubstring(self, s): """ :type s: str :rtype: int """ substr=[] mark=0 i=0 while i < len(s): if s[i] in substr: index = substr.index(s[i]) for j in range(index+1): #将重复字母及以前的元素从列表中移除 substr.pop(0) substr.append(s[i]) if len(substr)>mark: mark=len(substr) #mark储存最长的子串的长度 i = i+1 return mark #时间复杂度O(n),耗时72s (优化滑动窗口) class Solution(object): def lengthOfLongestSubstring(self, s): """ :type s: str :rtype: int """ substr={} mark=0 index=0 i=0 while i < len(s): if s[i] in substr: index = max(index,substr[s[i]]+1) #index 记住滑动窗口的起始位置 substr[s[i]]=i mark=max(mark,i-index+1) i = i+1 return mark
4.寻找两个有序数组的中位数 Median of two sorted arrays
#寻找两个有序数组的中位数 # 给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。 # 请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。 # 你可以假设 nums1 和 nums2 不会同时为空。 # 示例 1: # nums1 = [1, 3] # nums2 = [2] # 则中位数是 2.0 # 示例 2: # nums1 = [1, 2] # nums2 = [3, 4] # 则中位数是 (2 + 3)/2 = 2.5 """ :type nums1: List[int] :type nums2: List[int] :rtype: float """ class Solution(object): def findMedianSortedArrays(self,nums1,nums2): s1,s2,m,n=nums1,nums2,len(nums1),len(nums2) if m>n: s1,s2,m,n=nums2,nums1,n,m #保证m<=n,即s1表示较短的数组,其长度为m imin,imax=0,m halflength=(m+n+1)/2 while imin<=imax: i=(imin+imax)/2 j=halflength-i if i<m and s2[j-1]>s1[i]: imin = i+1 elif i>0 and s1[i-1]>s2[j]: imax = i-1 else: if i==0: max_of_left=s2[j-1] elif j==0: #只有m=n时,会出现j=0 max_of_left = s1[i-1] else: max_of_left=max(s1[i-1],s2[j-1]) if (m+n)%2==1: #两个数组长度之和为奇数 return max_of_left if i==m: min_of_right=s2[j] elif j==n: #只有m=n时,会出现j=n min_of_right=s1[i] else: min_of_right=min(s1[i],s2[j]) return (max_of_left+min_of_right)/2.0 #python2.7 #参考方法二,时间复杂度为? # class Solution: # def findMedianSortedArrays(self, nums1, nums2]): # nums = sorted(nums1 + nums2) # mid = len(nums)/2 #python 3中,长度为奇数如5时,mid=2.5 # return (nums[round(mid - 0.3)] + nums[round(mid - 0.7)])/2 if __name__=="__main__": s1=[2,4,6,8,10] s2=[1,2,3,5,7,9,20] s = Solution() print(s.findMedianSortedArrays(s1,s2))
5.最长回文子串 (Longest palindrome substring)
#coding:utf-8 # 给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。 # 示例 1: # 输入: "babad" # 输出: "bab" # 注意: "aba" 也是一个有效答案。 # 示例 2: # 输入: "cbbd" # 输出: "bb" #时间复杂度为O(n2),耗时850ms class Solution(object): def longestPalindrome(self, s): """ :type s: str :rtype: str """ if not s: return "" start=0 end = 0 for i in range(len(s)): len1 = self.expandAroundCenter(s,i,i) #以i为中心点,向两端扩展,判断是否对称 len2 = self.expandAroundCenter(s,i,i+1) #以i,i+1为中心点,向两端扩展,判断是否对称 length = max(len1,len2) if length>(end-start): start = i-(length-1)/2 end = i+length/2 return s[start:end+1] def expandAroundCenter(self,s,m,n): left=m right=n while (left>=0 and right<len(s) and s[left]==s[right]): left-=1 right+=1 return right-left-1
6.Z字形变换(Zigzag Conversion)
#coding:utf-8 #Z字形状变换 """ 将一个给定字符串根据给定的行数,以从上往下、从左到右进行 Z 字形排列。 比如输入字符串为 "LEETCODEISHIRING" 行数为 3 时,排列如下: L C I R E T O E S I I G E D H N 之后,你的输出需要从左往右逐行读取,产生出一个新的字符串,比如:"LCIRETOESIIGEDHN"。 请你实现这个将字符串进行指定行数变换的函数: string convert(string s, int numRows); 示例 1: 输入: s = "LEETCODEISHIRING", numRows = 3 输出: "LCIRETOESIIGEDHN" 示例 2: 输入: s = "LEETCODEISHIRING", numRows = 4 输出: "LDREOEIIECIHNTSG" 解释: L D R E O E I I E C I H N T S G """ """ :type s: str :type numRows: int :rtype: str """ class Solution(object): def convert(self, s, numRows): offset = 2*numRows-2 length=len(s) if length<=numRows or numRows<=1: #防止length或offset为0时,range(0,length,offset)函数报错 return s from collections import defaultdict d = defaultdict(list) for i in range(0,length,offset): for j in range(numRows): if (i+j)<length: d[j].append(s[i+j]) for k in range(1,numRows-1): temp = i+offset-k if temp<length: d[k].append(s[temp]) result = "" for key in d: result = result+"".join(d[key]) return result if __name__=="__main__": s = Solution() print(s.convert("LEETCODEISHIRING",4)) print(s.convert("LEETCODEISHIRING",3))
7. 整数反转(reverse interger)
#coding:utf-8 #整数反转 # 给出一个 32 位的有符号整数,你需要将这个整数中每位上的数字进行反转。 # 示例 1: # 输入: 123 # 输出: 321 # 示例 2: # 输入: -123 # 输出: -321 # 示例 3: # 输入: 120 # 输出: 21 # 注意: # 假设我们的环境只能存储得下 32 位的有符号整数,则其数值范围为 [−231, 231 − 1]。请根据这个假设,如果反转后整数溢出那么就返回 0。 """ :type x: int :rtype: int """ class Solution(object): def reverse(self, x): sign=1 if x<0: sign=-1 import sys ret = 0 m = sys.maxint #sys.maxint=2147483647(2^32 -1), sys.maxint跟系统有关系,32位时为2147483647 x = abs(x) while x!=0: remainder=x%10 x = x/10 if ret>(m/10) or (sign>0 and ret==m/10 and remainder>7): return 0 if ret>(m/10) or (sign<0 and ret==m/10 and remainder>8): return 0 ret = ret*10+remainder return sign*ret if __name__=="__main__": s = Solution() print(s.reverse(-8463847412)) print(s.reverse(-2346128362234)) print(s.reverse(7463847412)) print(s.reverse(2346128362234))
8. 字符窜转整数 (string to integer)
#coding:utf-8 #字符窜转换整数(atoi) string to integer # 请你来实现一个 atoi 函数,使其能将字符串转换成整数。 # 首先,该函数会根据需要丢弃无用的开头空格字符,直到寻找到第一个非空格的字符为止。 # 当我们寻找到的第一个非空字符为正或者负号时,则将该符号与之后面尽可能多的连续数字组合起来,作为该整数的正负号;假如第一个非空字符是数字,则直接将其与之后连续的数字字符组合起来,形成整数。 # 该字符串除了有效的整数部分之后也可能会存在多余的字符,这些字符可以被忽略,它们对于函数不应该造成影响。 # 注意:假如该字符串中的第一个非空格字符不是一个有效整数字符、字符串为空或字符串仅包含空白字符时,则你的函数不需要进行转换。 # 在任何情况下,若函数不能进行有效的转换时,请返回 0。 # 说明: # 假设我们的环境只能存储 32 位大小的有符号整数,那么其数值范围为 [−231, 231 − 1]。如果数值超过这个范围,qing返回 INT_MAX (231 − 1) 或 INT_MIN (−231) 。 # 示例 1: # 输入: "42" # 输出: 42 # 示例 2: # 输入: " -42" # 输出: -42 # 解释: 第一个非空白字符为 '-', 它是一个负号。 # 我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。 # 示例 3: # 输入: "4193 with words" # 输出: 4193 # 解释: 转换截止于数字 '3' ,因为它的下一个字符不为数字。 # 示例 4: # 输入: "words and 987" # 输出: 0 # 解释: 第一个非空字符是 'w', 但它不是数字或正、负号。 # 因此无法执行有效的转换。 # 示例 5: # 输入: "-91283472332" # 输出: -2147483648 # 解释: 数字 "-91283472332" 超过 32 位有符号整数范围。 # 因此返回 INT_MIN (−231) 。 """ :type str: str :rtype: int """ class Solution(object): def myAtoi(self, str): astr = str.strip() if len(astr)==0: return 0 valid=['+','-','0','1','2','3','4','5','6','7','8','9'] if astr[0] not in valid: return 0 else: i=1 while i<len(astr): if astr[i] in valid[2:]: i = i+1 else: break ret = astr[:i].strip("+").lstrip("0") # "000000000" if len(ret)==0: return 0 if ret[0]=="-": ret = ret[0]+ret[1:].lstrip("0") i = len(ret) if len(ret)>11 or (len(ret)==11 and int(ret[1:i-1])>214748364) or (len(ret)==11 and int(ret[1:i-1])==214748364 and int(ret[i-1])>8): return -2147483648 elif len(ret)==1: #防止int("-")报错 return 0 else: return int(ret) else: i = len(ret) if len(ret)>10 or (len(ret)==10 and int(ret[0:i-1])>214748364) or (len(ret)==10 and int(ret[0:i-1])==214748364 and int(ret[i-1])>7): return 2147483647 else: return int(ret) if __name__=="__main__": s = Solution() # print(s.myAtoi(" -2147483648")) # print(s.myAtoi(" +2147483648")) print(s.myAtoi(" +1146905820n1")) print(s.myAtoi(" +1146905820n1"))
9. 回文数(palindrome number)
#coding:utf-8 #9 回文数(Palindrome number) # 判断一个整数是否是回文数。回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 # 示例 1: # 输入: 121 # 输出: true # 示例 2: # 输入: -121 # 输出: false # 解释: 从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。 # 示例 3: # 输入: 10 # 输出: false # 解释: 从右向左读, 为 01 。因此它不是一个回文数 """ :type x: int :rtype: bool """ #会出现反转后整数溢出? # class Solution(object): # def isPalindrome(self, x): # if x<0: # return False # temp = x # remainder = 0 # while temp>0: # remainder = remainder*10+temp%10 # temp = temp/10 # if remainder==x: # return True # else: # return False #只反转后面一本分 class Solution(object): def isPalindrome(self, x): if x<0 or (x%10==0 and x!=0): return False remainder = 0 while x>remainder: remainder = remainder*10+x%10 x = x/10 return x==remainder or x==remainder/10 #123321 和 12321两种情况 if __name__=="__main__": s = Solution() print(s.isPalindrome(121)) print(s.isPalindrome(-121)) print(s.isPalindrome(10))
30.串联所有单词的子串
给定一个字符串 s 和一些长度相同的单词 words。找出 s 中恰好可以由 words 中所有单词串联形成的子串的起始位置。
注意子串要与 words 中的单词完全匹配,中间不能有其他字符,但不需要考虑 words 中单词串联的顺序。
示例 1:
输入:
s = "barfoothefoobarman",
words = ["foo","bar"]
输出:[0,9]
解释:
从索引 0 和 9 开始的子串分别是 "barfoor" 和 "foobar" 。
输出的顺序不重要, [9,0] 也是有效答案。
示例 2:
输入:
s = "wordgoodgoodgoodbestword",
words = ["word","good","best","word"]
输出:[]
耗时:1040s
class Solution(object): def findSubstring(self, s, words): """ :type s: str :type words: List[str] :rtype: List[int] """ indices=[] if s and words: word_len=len(words[0]) word_num = len(words) length = word_len*word_num i=0 while i <=len(s)-length: flag=True if s[i:i+word_len] in words: j=i temp=[] while j<(i+length): if s[j:j+word_len] in words: temp.append(str(s[j:j+word_len])) j = j+word_len else: flag=False break #print temp if flag: for item in words: if item in temp: temp.remove(item) else: break if len(temp)==0: indices.append(i) i=i+1 return indices

浙公网安备 33010602011771号