for idx inrange(2,len(nums)): res = max(yesterday,two_day_ago + nums[idx]) # 准备下一天的计算:昨天变成前天,今天变成昨天 two_day_ago = yesterday yesterday = res return res
其实可以没有前天这个变量的:
1 2 3 4 5 6 7
classSolution(object): defrob(self, nums): # rob1表示这一家偷了的最大收益,rob2表示这一家不偷的最大收益 rob1, rob2 = 0,0 for num in nums: rob1, rob2 = rob2 + num, max(rob1, rob2) returnmax(rob1, rob2)
也可以这么写:
1 2 3 4 5 6 7 8
classSolution(object): defrob(self, nums): # last代表昨天的最大利益,now表示今天的最大利益 last = now = 0 for i in nums: # now = max(last + i, now):今天偷还是不偷 last, now = now, max(last + i, now) return now
classSolution(object): defisHappy(self, n): cache = [] while n != 1: tmp = 0 for each instr(n): tmp += int(each)**2 n = tmp ifnot n in cache: cache.append(n) else: returnFalse returnTrue
就算是使用存缓,上面代码的6-8行的效率不高,应该如下使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution(object): defisHappy(self, n): if n == 1: returnTrue numlist = [] whileTrue: temp = 0 # 代替上面代码的6-8行 while n != 0: n,remain = divmod(n,10) temp += remain**2 if temp == 1: returnTrue if temp in numlist: returnFalse numlist.append(temp) n = temp
classSolution(object): defisHappy(self, n): unhappy = [4,16,37,58,89,145,42,20] happy = [1,10,100,1000] while n notin unhappy and n notin happy: total = 0 while n: n,remain = divmod(n,10) total += remain**2 n = total return n in happy
classSolution(object): defisPrimes(self,n): for num inrange(2,n//2+1): if n % num == 0: returnFalse returnTrue defcountPrimes(self, n): res = 0 for each inrange(2,n): if self.isPrimes(each): res += 1 return res
classSolution(object): defcountPrimes(self, n): if n <= 1: return0 nums = [None] * n nums[0] = False nums[1] = False for i inrange(n): if nums[i] == None: nums[i] = True for j inrange(i + i, n, i): nums[j] = False returnsum(nums)
for i inrange(len(s)): if s[i] notin dictionary_s: dictionary_s[s[i]] = t[i] elif s[i] in dictionary_s: if dictionary_s[s[i]] != t[i]: returnFalse if t[i] notin dictionary_t: dictionary_t[t[i]] = s[i] elif t[i] in dictionary_t: if dictionary_t[t[i]] != s[i]: returnFalse returnTrue
# 头插法. # 思路:将原链的头节点p设置为最后一个节点,然后head节点不断头插入p中,最后返回head classSolution(object): defreverseList(self, head): p = head if p isNone: return p # s节点用于遍历整个原链表 s = head.next # p的节点设置为空,变成尾节点 # 因为使用头插法,p变成初始节点 p.next = None while s: # head为头插的节点(头节点) head = s s = s.next
for i inrange(nums_len): if nums[i] in nums_dict: if i - nums_dict[nums[i]] <= k: returnTrue # 因为是从左到右扫描,所以每次都要更新字典 nums_dict[nums[i]] = i returnFalse
上面代码可以简化如下:
1 2 3 4 5 6 7 8
classSolution: defcontainsNearbyDuplicate(self, nums: List[int], k: int) -> bool: d={} for index,value inenumerate(nums): if value in d and index-d[value]<=k: returnTrue d[value]=index returnFalse
classSolution(object): defisPalin(self,alist): iflen(alist) == 0: returnTrue left = 0 right = len(alist) - 1 while left < right: if alist[left] != alist[right]: returnFalse left += 1 right -= 1 returnTrue defisPalindrome(self, head): alist = [] while head: alist.append(head.val) head = head.next return self.isPalin(alist)
classSolution(object): defreversed(self,head): ifnot head ornot head.next: return head pre = head.next head.next = None while pre: tmp = pre.next pre.next = head pre = tmp return head
defisPalindrome(self, head): dummy = head revHead = self.reversed(dummy) while head: if head.val != revHead.val: returnFalse head = head.next revHead = revHead.next returnTrue
classSolution(object): defreversed(self,head): ifnot head ornot head.next: return head pre = head.next head.next = None while pre: tmp = pre.next pre.next = head head = pre pre = tmp return head
defisPalindrome(self, head): ifnot head ornot head.next: returnTrue
slow = fast = head while fast and fast.next: slow = slow.next fast = fast.next.next print(slow.val) slow = self.reversed(slow) while slow: print(head.val,slow.val) if head.val != slow.val: returnFalse head = head.next slow = slow.next returnTrue
可以简化如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
classSolution: defisPalindrome(self, head): fast = slow = head # 找到中点 while fast and fast.next: fast = fast.next.next slow = slow.next # 反转链表,可参考leetcode206 node = None while slow: slow.next, node, slow = node, slow, slow.next # 双指针 while node: if node.val != head.val: returnFalse node = node.next head = head.next returnTrue
给定一个包含 0, 1, 2, ..., n 中 n 个数的序列,找出 0 .. n 中没有出现在序列中的那个数。
示例 1:
1 2
输入: [3,0,1] 输出: 2
示例 2:
1 2
输入: [9,6,4,2,3,5,7,0,1] 输出: 8
说明: 你的算法应具有线性时间复杂度。你能否仅使用额外常数空间来实现?
我的代码:
1 2 3 4 5 6 7 8 9 10
classSolution(object): defmissingNumber(self, nums): a = (len(nums)+1) / 2 * len(nums) tot = 0 for each in nums: tot += each # 如果缺最大数 if (len(nums)-1) / 2 * len(nums) - tot == len(nums): returnlen(nums) returnint(a-tot)
# The isBadVersion API is already defined for you. # @param version, an integer # @return a bool # def isBadVersion(version): classSolution: deffirstBadVersion(self, n): left = 1 right = n mid = int(left+(right-left)/2) while left <= right: if isBadVersion(mid): right = mid-1 else: left = mid+1 mid = int(left+(right-left)/2) return left
代码二如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
classSolution: deffirstBadVersion(self, n): # 头元素 low = 1 # 伪元素 high = n # 没有等号,等号成立的时候就退出循环 while low < high: mid = (low + high) //2 if isBadVersion(mid): # 高不加 high = mid else: # 低加一 low = mid + 1 # 此时low==high,所以可以二选一 return low
新时代的二分法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
classSolution: deffirstBadVersion(self, n): left = 1 # 利用左闭右开的特性,所以右端点加1, # 好处是当while loop终止时,right、mid、left三者取值相同 # 不用思考需要返回哪一个,返回哪一个都是正确的 right = n+1 while(left<right): # 注意这里的mid取值 mid = left + (right-left)//2 if(isBadVersion(mid)==False): left = mid + 1 else: right = mid return right
classSolution: defmoveZeroes(self, nums: List[int]) -> None: for each in nums[::-1]: if each == 0: nums.remove(each) nums.append(0)
但是这是删除后添加,而不是移动,而且上面的代码效率较低.正确的代码如下:
1 2 3 4 5 6 7 8 9 10 11
classSolution: defmoveZeroes(self, nums): k = 0 # 此次遍历的目的:将不为0的元素复制到前面,记录复制了多少个元素 for i in nums: if i != 0: nums[k] = i k += 1 # 既然有k个不为零的元素,并且这些元素都移动到了前面,那么后面元素都是0 for i inrange(k,len(nums)): nums[i] = 0
# 交换非零元素和零元素 classSolution: defmoveZeroes(self, nums): # k记录非零元素应该换到第几个位置 k = 0 for i, num inenumerate(nums): if num != 0: nums[i], nums[k] = nums[k], nums[i] k += 1
classSolution: defreverseString(self, s: List[str]) -> None: left = 0 right = len(s) -1 while left < right: s[left],s[right] = s[right],s[left] left += 1 right -= 1
当然你也可以这么写:
1 2 3 4 5
classSolution: defreverseString(self, s: List[str]) -> None: a = len(s) - 1 for i inrange(len(s)//2): s[i],s[a-i]=s[a-i],s[i]
classSolution: defintersection(self, nums1, nums2): a = {} for i in nums1: if i in a: a[i] += 1 else: a[i] = 0 r = [each for each in nums2 if each in a] returnlist(set(r))
inter = set(nums1) & set(nums2) l = [] for i in inter: l += [i] * min(nums1.count(i), nums2.count(i)) return l
或者使用dict:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution: defintersect(self,nums1, nums2): """使用hash""" d1 = {} d2 = {} for each in nums1: d1[each] = d1.get(each,0) + 1 for each in nums2: d2[each] = d2.get(each,0) + 1
inners = [] # 同时遍历两个字典 for key in (d1.keys() iflen(d1)<len(d2) else d2.keys()): if d1.get(key) != Noneand d2.get(key) != None: inners.extend([key]*min(d1.get(key),d2.get(key))) return inners
经验:
==同时遍历两个字典使用if d1.get(key) and d2.get(key):==
注意for key in (d1.keys() if len(d1)<len(d2) else d2.keys())的用法
当然也可以使用最普通的方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: defintersect(self, nums1: List[int], nums2: List[int]) -> List[int]: d={} res=[] for i in nums1: if i in d: d[i]+=1 else: d[i]=1 for i in nums2: if i in d and d[i]>0: res.append(i) d[i]-=1 return res
# The guess API is already defined for you. # @param num, your guess # @return -1 if my number is lower, 1 if my number is higher, otherwise return 0 # def guess(num): classSolution(object): defguessNumber(self, n): left = 1 right = n + 1 while left < right: mid = left + (right - left) // 2 if guess(mid) == 1: left = mid + 1 elif guess(mid) == -1: right = mid else: return mid return left
classSolution(object): defcanConstruct(self, ransomNote, magazine): d = {} for i in magazine: d[i] = d.get(i, 0) + 1 for i in ransomNote: d[i] = d.get(i, 0) - 1
classSolution(object): deffirstUniqChar(self, s): count_dict = {} for each in s: count_dict[each] = count_dict.get(each,0) + 1 y = [key for key,value in count_dict.items() if value == 1] for idx inrange(len(s)): if s[idx] in y: return idx return -1
第7行新开辟了空间,不太好:
1 2 3 4 5 6 7 8 9 10 11
classSolution(object): deffirstUniqChar(self, s): hash_map = dict() for char in s: hash_map[char] = hash_map.get(char,0) + 1 for i inrange(len(s)): char = s[i] # 不开辟空间,直接使用 if char in hash_map and hash_map[char] == 1: return i return -1
classSolution(object): deffindTheDifference(self, s, t): for each inset(t): if s.count(each) != t.count(each): return each
或者使用dict:
1 2 3 4 5 6 7 8 9 10 11 12
classSolution(object): deffindTheDifference(self, s, t): dict_s = {} dict_t = {} for each in s: dict_s[each] = dict_s.get(each,0) + 1 for each in t: dict_t[each] = dict_t.get(each,0) + 1
for each in dict_t: if dict_t.get(each) != dict_s.get(each): return each
真正的做法,应该使用位运算:==数字与自身异或结果为0==
1 2 3 4 5 6
classSolution: deffindTheDifference(self, s, t): ret = 0 for c in s + t: ret ^= ord(c) returnchr(ret)
# 第一步确定n是在几位数里,第二步是确定在几位数的第几位数字的第几位 classSolution(object): deffindNthDigit(self, n): # 第一步 # 位数 digit = 1 while n > digit*9*10**(digit-1): n -= digit*9*10**(digit-1) digit += 1
# 第二步 # 得到几位数的第几位数字 a = int((n-1)/digit) # 得到几位数的第几位数字的第几位 b = int((n-1)%digit) # 得到第几位数字是多少 num = 10**(digit-1)+a # 数字转字符再转列表把第几位数的第几位切出来 res = list(str(num))[b:b+1] # 列表转字符再转数字 returnint(''.join(res))
或者:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
classSolution: deffindNthDigit(self, n): if n < 10: return n # 多少位数 i = 1 while n > 9 * 10 **(i - 1) * i: n -= 9 * 10 **(i - 1) * i i += 1 if n % i == 0: returnint(str(10 ** (i - 1) + n // i - 1)[-1]) else: returnint(str(10 ** (i - 1) + n // i)[n%i-1])
或者:
1 2 3 4 5 6 7 8 9 10 11 12
classSolution(object): deffindNthDigit(self, n): # 多少位数 w = 1 # 某位数有多少个数字(如w=2时k=9*10=90) k = 9 while n > k * w: n -= k * w k *= 10 w += 1 tmp = 10 ** (w - 1) + (n - 1) / w returnint(str(tmp)[(n - 1) % w])
classSolution(object): deftoHex(self, num): hashmap = '0123456789abcdef' if num > 0: res = '' while num: num,remain = divmod(num,16) res = hashmap[remain] + res return res elif num < 0: ... else: return'0'
if num < 0: # 求补码 begin=1# 初始标记位 add = 0# 进位标志 num = abs(num) while num != 0: x = num % 16 if begin: # 首位计算 if x==0: add=1 else: x = 16-x # 取补 begin = 0 else: if x == 0and add==1: x=x else: x = 15-x+add # 取反 add = 0
# 使用位运算,每4位,对应1位16进制数字。 # 使用0xf(00...01111b)获取num的低4位。 # >>算数位移,其中正数右移左边补0,负数右移左边补1。! classSolution(object): deftoHex(self, num): result = '' alpha = '0123456789abcdef' if num == 0: return'0' while num != 0andlen(result) < 8: result += alpha[num & 0xf] num = num >> 4 return result[::-1]
# 如果一个字符出现偶数次,那么它必定对于构造回文串有帮助, # 如果一个字符出现奇数次,那么它的(奇数次 - 1)也可以用于构造回文串 # 如果一个数出现一次,那么它可以用于放在中间。 classSolution: deflongestPalindrome(self, s: str) -> int: d = {} for each in s: d[each] = d.get(each,0) + 1
res = 0 has_alone = False for count in d.values(): if count % 2 == 1: res += (count - 1) has_alone = True else: res += count return res + 1if has_alone else res
classSolution: deffizzBuzz(self, n: int) -> List[str]: res = [] for each inrange(1,n+1): if each % 15 == 0: res.append('FizzBuzz') elif each % 3 == 0: res.append('Fizz') elif each % 5 == 0: res.append('Buzz') else: res.append(str(each)) return res
可以合并这些代码:
1 2 3 4 5 6
classSolution: deffizzBuzz(self, n): res = [] for i inrange(1,n+1): res.append('Fizz'[i%3*len('Fizz')::]+'Buzz'[i%5*len('Buzz')::] orstr(i)) return res
classSolution: defthirdMax(self, nums: List[int]) -> int: first,second,third= float('-inf'),float('-inf'),float('-inf') for num in nums: if num > first: first,second,third = num,first,second elif second < num < first: second,third = num,second elif third < num < second: third = num return third if third != float('-inf') else first
classSolution: defaddStrings(self, num1, num2): # 首先反转 num1_r = num1[::-1] num2_r = num2[::-1] carry, ret, i = 0, '', 0 while i < len(num1_r) or i < len(num2_r): a = 0if i >= len(num1_r) elseint(num1_r[i]) b = 0if i >= len(num2_r) elseint(num2_r[i]) ret += str((a+b+carry)%10) carry = (a+b +carry) // 10 i += 1 if carry: ret += '1' return ret[::-1]