defpush(self, x): self.stack.append(x) ifnot self.minstack or x <= self.minstack[-1]: #1 self.minstack.append(x) defpop(self): if self.minstack and self.minstack[-1] == self.top(): self.minstack.pop() self.stack.pop()
defpop(self): for i in range(len(self.queue) - 1): self.queue.append(self.queue.pop(0)) return self.queue.pop(0)
deftop(self): for i in range(len(self.queue) - 1): self.queue.append(self.queue.pop(0)) result = self.queue[0] self.queue.append(self.queue.pop(0)) # 恢复原样 return result
字典 dict 的遍历 遍历 key 值:for key in dict 遍历 value 值:for value in dict.values() 遍历字典项:for kv in dict.items() 遍历 key 和 value 值 : for key, value in dict.items()
deftwoSum(nums, target): dic = {} if len(nums) <= 1: return false for i in range(len(nums)): tmp = target - nums[i] if tmp in dic: return [dic[tmp], i] else: dic[nums[i]] = i
无重复字符的最长子串 Longest Substring Without Repeating Characters
defsingleNumber(nums): cnt = {} for num in nums: if num notin cnt: cnt[num] = 1 else: cnt[num] += 1 for num, count in cnt.items(): if count == 1: return num
deffindRepeatedDnaSequences(self, s): dic = {} res = [] for i in range(len(s)-9): key = s[i:i+10] if key notin dic: dic[key] = 1 else: if key notin res: res.append(key) return res
defisIsomorphic(self, s, t): dic = {} for i in range(len(s)): if s[i] in dic: if t[i] != dic[s[i]]: returnFalse else: if t[i] in dic.values(): returnFalse dic[s[i]] = t[i] returnTrue
classSolution(object): defisSameTree(self, p, q): if (not p and q) or (not q and p): returnFalse ifnot p andnot q: returnTrue return p.val == q.val and self.isSameTree(p.left, q.left) and self.isSameTree(p.right, q.right)
classSolution: defisSymmetric(self, root): ifnot root: returnTrue# 空树为对称树 return self.symmetric(root.left, root.right) defsymmetric(self, left, right): ifnot left andnot right: returnTrue if left and right and left.val == right.val: return self.symmetric(left.left, right.right) and self.symmetric(left.right, right.left) else: returnFalse
classSolution(object): defpreorderTraversal(self, root): result = [] stack = [] while root or stack: while root: result.append(root.val) stack.append(root) root = root.left if stack: node = stack.pop() root = node.right return result
classSolution(object): definorderTraversal(self, root): result = [] stack = [] while root or stack: while root: stack.append(root) root = root.left if stack: node = stack.pop() result.append(node.val) root = node.right return result
思路:层次遍历利用队列的先进先出特性,将先进入队列的元素 pop 出来。 题中需要按照层次来打印出遍历结果,可以用一个临时列表存储二叉树一层的所有节点。即用 queue 来存储当前层元素, tmp 存储下一层元素。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
classSolution(object): deflevelOrder(self, root): result = [] ifnot root: return result queue = [root] while queue: result.append([node.val for node in queue]) tmp = [] for node in queue: if node.left: tmp.append(node.left) if node.right: tmp.append(node.right) queue = tmp return result
defrightSideView(self, root): ifnot root: return [] res = [] queue = [root] while queue: res.append(queue[-1].val) tmp = [] for node in queue: if node.left: tmp.append(node.left) if node.right: tmp.append(node.right) queue = tmp return res
classSolution(object): deffindBottomLeftValue(self, root): queue = [root] result = root while queue: tmp = [] result = queue[0] for node in queue: if node.left: tmp.append(node.left) if node.right: tmp.append(node.right) queue = tmp return result.val
classSolution(object): defaverageOfLevels(self, root): result = [] queue = [root] while queue: tmp = [] sum = 0.0 for node in queue: sum += node.val if node.left: tmp.append(node.left) if node.right: tmp.append(node.right) result.append(sum/len(queue)) queue = tmp return result
思路: 之字形遍历二叉树,奇数行从左往右,偶数行从右往左,… 可以修改层次遍历的代码,通过判断 res 的长度,来判断当前行是奇数行还是偶数行,若是偶数行,则将结果翻转即可。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
defzigzagLevelOrder(self, root): res = [] ifnot root: return res queue = [root] while queue: nodes = [node.val for node in queue] if len(res) % 2 == 0: res.append(nodes) else: res.append(nodes[::-1]) tmp = [] for node in queue: if node.left: tmp.append(node.left) if node.right: tmp.append(node.right) queue = tmp return res
defgenerateTrees(self, n): """ :type n: int :rtype: List[TreeNode] # 返回一个根节点的list即可 """ if n == 0: return [] return self.dfs(1, n) defdfs(self, begin, end): if begin > end: return [None] res = [] for i in range(begin, end+1): left = self.dfs(begin, i-1) right = self.dfs(i+1, end) for l in left: for r in right: root = TreeNode(i) root.left = l root.right = r res.append(root) return res
classSolution(object): deflowestCommonAncestor(self, root, p, q): ifnot root or root == p or root == q: return root left = self.lowestCommonAncestor(root.left, p ,q) right = self.lowestCommonAncestor(root.right, p, q) if left and right: return root if left: return left return right
defnextPermutation(self, nums): n = len(nums) if n <= 1: return flag = 0 for i in range(n-2, -1, -1): if nums[i] < nums[i+1]: for j in range(n-1, i, -1): if nums[j] > nums[i]: nums[i], nums[j] = nums[j], nums[i] nums[i+1:] = sorted(nums[i+1:]) flag = 1 break break ifnot flag: nums.sort() # nums[:] = sorted(nums[:])
defmerge(self, intervals): """ :type intervals: List[Interval] :rtype: List[Interval] """ if len(intervals) <= 1: return intervals res = [] intervals = sorted(intervals, key=lambda x: (x.start, x.end)) left = intervals[0].start right = intervals[0].end for i in range(1, len(intervals)): if right >= intervals[i].start: right = max(right, intervals[i].end) else: interval = Interval(left, right) res.append(interval) left = intervals[i].start right = intervals[i].end interval = Interval(left, right) res.append(interval) return res
defmerge(self, nums1, m, nums2, n): while m > 0and n > 0: if nums1[m-1] >= nums2[n-1]: nums1[m+n-1] = nums1[m-1] m -= 1 else: nums1[m+n-1] = nums2[n-1] n -= 1 if n > 0: nums1[:n] = nums2[:n]
投机做法:
1 2 3
defmerge(nums1, m, nums2, n): nums1[m:] = nums2[:n] nums1.sort()
defgenerate(self, numRows): res = [] for i in range(numRows): if i <= 1: res.append([1]*(i+1)) else: row = [1] + [0] * (i-1) + [1] for j in range(1, i): row[j] = res[i-1][j-1] + res[i-1][j] res.append(row) return res
defgetRow(self, rowIndex): res = [] for i in range(rowIndex+1): if i <= 1: res = [1] * (i+1) else: tmp = [] for j in range(i-1): tmp.append(res[j] + res[j+1]) res = [1] + tmp + [1] return res
defcontainsNearbyDuplicate(self, nums, k): dic = {} for i in range(len(nums)): if nums[i] in dic: j = dic[nums[i]] if i - j <= k: returnTrue dic[nums[i]] = i returnFalse
摩尔投票法:快速的计算出一个数组中出现次数过半的数,应用同加异减的思想。设置一个计数器,在遍历数组的时候,如果是这个数,则计数器加 1,否则减 1,当计数器为 0 时,则重置 major 和 cnt。
1 2 3 4 5 6 7 8 9 10 11 12
defmajorityElement(self, nums): major = nums[0] cnt = 1 for i in range(1, len(nums)): if nums[i] == major: cnt += 1 elif nums[i] != major: cnt -= 1 if cnt == 0: major = nums[i] cnt = 1 return major
defproductExceptSelf(self, nums): n = len(nums) product = [1] * n tmp = 1 for i in range(n): product[i] = tmp tmp *= nums[i] tmp = 1 for i in range(n-1, -1, -1): product[i] *= tmp tmp *= nums[i] return product
defmoveZeroes(nums): """ :type nums: List[int] :rtype: void Do not return anything, modify nums in-place instead. """ i = 0 for x in nums: if x != 0: nums[i] = x i += 1 while i < len(nums): nums[i] = 0 i += 1
classSolution(object): defisValidSudoku(self, board): for i in range(9): row = board[i] col = [r[i] for r in board] ifnot self.valid(row) ornot self.valid(col): returnFalse for i in [0, 3, 6]: for j in [0, 3, 6]: nine = [board[row][col] for row in [i, i+1, i+2] for col in [j, j+1, j+2]] ifnot self.valid(nine): returnFalse returnTrue defvalid(self, nums): dic = {} for char in nums: if char.isdigit(): if char in dic: returnFalse else: dic[char] = 1 returnTrue
defrotate(self, matrix): n = len(matrix) for i in range(n): for j in range(i+1, n): matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j] for i in range(n): for j in range(n//2): matrix[i][j], matrix[i][n-j-1] = matrix[i][n-j-1], matrix[i][j]
defspiralOrder(self, matrix): """ :type matrix: List[List[int]] :rtype: List[int] """ res = [] ifnot matrix: return matrix left = 0 right = len(matrix[0]) - 1 up = 0 down = len(matrix) - 1 size = (right+1) * (down+1) while left <= right and up <= down: for i in range(left, right+1): if len(res)< size: res.append(matrix[up][i]) up += 1 for i in range(up, down+1): if len(res)< size: res.append(matrix[i][right]) right -= 1 for i in range(right, left-1, -1): if len(res)< size: res.append(matrix[down][i]) down -= 1 for i in range(down, up-1, -1): if len(res)< size: res.append(matrix[i][left]) left += 1 return res
defgenerateMatrix(self, n): """ :type n: int :rtype: List[List[int]] """ matrix = [[0for col in range(n)] for row in range(n)] left = 0 right = n-1 up = 0 down = n-1 num = 1 while left <= right and up <= down: for i in range(left, right+1): if num <= n*n: matrix[up][i] = num num += 1 up += 1 for i in range(up, down+1): if num <= n*n: matrix[i][right] = num num += 1 right -= 1 for i in range(right, left-1, -1): if num <= n*n: matrix[down][i] = num num += 1 down -= 1 for i in range(down, up-1, -1): if num <= n*n: matrix[i][left] = num num += 1 left += 1 return matrix
暴力法:两次遍历,第一次遍历存储需要置零的行和列,第二次遍历置零。此法时间复杂度为 O(n * m) , 空间复杂度为 O(n+m)。
1 2 3 4 5 6 7 8 9 10 11 12
defsetZeroes(self, matrix): rows = [] cols = [] for i in range(len(matrix)): for j in range(len(matrix[0])): if matrix[i][j] == 0: rows.append(i) cols.append(j) for i in range(len(matrix)): for j in range(len(matrix[0])): if i in rows or j in cols: matrix[i][j] = 0
defsetZeroes(self, matrix): m = len(matrix) n = len(matrix[0]) flag = 0 for i in range(m): if matrix[i][0] == 0: flag = 1# 说明第 0 列中是有 0 的 for j in range(1,n): if matrix[i][j] == 0: matrix[i][0] = 0 matrix[0][j] = 0
for i in range(m-1, -1, -1): for j in range(n-1, 0, -1): # 第 0 列额外判断 if matrix[i][0] == 0or matrix[0][j] == 0: matrix[i][j] = 0 if flag: matrix[i][0] = 0
有序矩阵的第k小元素 Kth Smallest Element in a Sorted Matrix
思路: 由于可能会改变链表表头,因此添加一个辅助节点 dummy。然后用两个指针,fast 先走 n 步,然后 slow 再和 fast 同步走,当 fast 走到终点时,slow 位于要删除的节点的前面。
1 2 3 4 5 6 7 8 9 10 11 12
defremoveNthFromEnd(self, head, n): dummy = ListNode(0) dummy.next = head fast = head slow = dummy # 此处需要注意,slow不能是head,因为head有可能要被删除。 for _ in range(n): fast = fast.next while fast: slow = slow.next fast = fast.next slow.next = slow.next.next return dummy.next
思路: 由于每次要交换相邻节点,因此可以两个节点作为一个单位进行处理。 用 cur 记录当前节点,pre 记录上一个节点,然后进行交换操作。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
defswapPairs(self, head): ifnot head ornot head.next: return head dummy = pre = ListNode(0) dummy.next = head.next cur = head while cur and cur.next: tmp = cur.next cur.next = tmp.next tmp.next = cur pre.next = tmp pre = cur cur = cur.next return dummy.next
defrotateRight(self, head, k): ifnot head ornot head.next or k == 0: return head node = head size = 0 while node: size += 1# 链表的长度 node = node.next k = k % size # 将后面 k 个数 rotate 到前面 if k == 0: return head slow, fast = head, head for _ in range(k): fast = fast.next while fast.next: fast = fast.next slow = slow.next fast.next = head head = slow.next slow.next = None return head
classSolution(object): defdeleteDuplicates(self, head): ifnot head ornot head.next: return head cur = head.next pre = head while cur: if pre.val == cur.val: cur = cur.next else: pre.next = cur pre = cur cur = pre.next pre.next = None return head
classSolution(object): defdeleteDuplicates(self, head): ifnot head ornot head.next: return head dummy = ListNode(0) dummy.next = head
pre = dummy cur = dummy.next while cur: is_repeated = False while cur.next and pre.next.val == cur.next.val: cur = cur.next is_repeated = True if is_repeated: pre.next = cur.next else: pre = pre.next cur = cur.next return dummy.next
classSolution(object): defreverseBetween(self, head, m, n): whilenot head ornot head.next or m == n: return head cur = head end = head for _ in range(m-1): end = cur cur = cur.next
pre = None rend = end if m == 1else cur for _ in range(n-m+1): tmp = cur.next cur.next = pre pre = cur cur = tmp if m != 1: end.next = pre rend.next = cur return head if m != 1else pre
classSolution(object): defhasCycle(self, head): slow = fast = head while fast and fast.next: slow = slow.next fast = fast.next.next if slow == fast: returnTrue returnFalse
defdetectCycle(self, head): ifnot head ornot head.next: returnNone slow = fast = head flag = 0 while fast and fast.next: slow = slow.next fast = fast.next.next if slow == fast: flag = 1 break# 必须要break,否则死循环 ifnot flag: # 不是环形就返回None,提高效率。 returnNone slow = head while slow != fast: slow = slow.next fast = fast.next return slow
思路:对于链表 A 和 B,相交于公共部分 C,设两个链表的公共部分长度为 c,那么 A 的长度为 a + c,B 的长度为 b + c,那么有 a + c + b = b + c +a。
当链表 A 访问到尾部时,则从链表 B 的头部开始访问 B; 当链表 B 访问到尾部时,则从链表 A 的头部开始访问 A。 这样可以控制访问 A 和 B 的指针同时访问到交点,若 A 和 B 没有交点,则两个指针同时为空,返回 None
1 2 3 4 5 6 7 8 9 10
classSolution(object): defgetIntersectionNode(self, headA, headB): p = headA q = headB ifnot p ornot q: returnNone while p != q: p = p.next if p else headB q = q.next if q else headA return p
classSolution(object): defisPalindrome(self, head): arr = [] while head: arr.append(head.val) head = head.next for i in range(len(arr)//2): if arr[i] != arr[len(arr)-1-i]: returnFalse returnTrue
classSolution(object): defisPalindrome(self, head): ifnot head ornot head.next: returnTrue fast = slow = head rhead = None while fast.next and fast.next.next: slow = slow.next fast = fast.next.next rhead = self.reverseList(slow.next) while rhead: if rhead.val != head.val: returnFalse rhead = rhead.next head = head.next returnTrue defreverseList(self, head): cur = head pre = None while cur: tmp = cur.next cur.next = pre pre = cur cur = tmp return pre
classSolution(object): defoddEvenList(self, head): ifnot head: return head even_head = head.next odd = head even = even_head while even and even.next: odd.next = odd.next.next odd = odd.next even.next = even.next.next even = even.next odd.next = even_head return head