├── .gitignore ├── 1. 滑动窗口 ├── 121. Best Time to Buy and Sell Stock.py ├── 239. Sliding Window Maximum.py ├── 3. Longest Substring Without Repeating Characters.py ├── 53. Maximum Subarray.py └── 剑指 Offer 57 - II. 和为s的连续正数序列.py ├── 10. 双堆模式 ├── 155. Min Stack.py ├── 295. Find Median from Data Stream.py ├── 480. Sliding Window Median.py └── 剑指 Offer 09.py ├── 11. 2分变种 ├── 153. Find Minimum in Rotated Sorted Array.py ├── 154. Find Minimum in Rotated Sorted Array II.py ├── 162. Find Peak Element.py ├── 33. Search in Rotated Sorted Array.py ├── 34. Find First and Last Position of Element in Sorted Array.py ├── 35. Search Insert Position.py ├── 540. Single Element in a Sorted Array.py └── 剑指 Offer 16. 数值的整数次方.py ├── 12. 前K大的数模式HEAP ├── 215. Kth Largest Element in an Array.py ├── 347. Top K Frequent Elements.py └── 373. Find K Pairs with Smallest Sums.py ├── 13. K路归并 ├── 21. Merge Two Sorted Lists.py └── 23. Merge k Sorted Lists.py ├── 14. DP 动态规划 ├── 10. Regular Expression Matching.py ├── 1143. Longest Common Subsequence.py ├── 120. Triangle.py ├── 121. Best Time to Buy and Sell Stock.py ├── 122. Best Time to Buy and Sell Stock II.py ├── 123. Best Time to Buy and Sell Stock III.py ├── 139. Word Break.py ├── 152. Maximum Product Subarray.py ├── 188. Best Time to Buy and Sell Stock IV.py ├── 198. House Robber.py ├── 213. House Robber II.py ├── 300. Longest Increasing Subsequence.py ├── 309. Best Time to Buy and Sell Stock with Cooldown.py ├── 322. Coin Change.py ├── 416. Partition Equal Subset Sum.py ├── 44. Wildcard Matching.py ├── 5. Longest Palindromic Substring.py ├── 516. Longest Palindromic Subsequence.py ├── 518. Coin Change 2.py ├── 53. Maximum Subarray.py ├── 714. Best Time to Buy and Sell Stock with Transaction Fee.py ├── 72. Edit Distance.py ├── 887. Super Egg Drop.py ├── 91. Decode Ways.py ├── 剑指 Offer 10- I. 斐波那契数列.py ├── 剑指 Offer 10- II. 青蛙跳台阶问题.py ├── 剑指 Offer 14- I. 剪绳子.py ├── 剑指 Offer 46. 把数字翻译成字符串.py ├── 剑指 Offer 47. 礼物的最大价值.py ├── 剑指 Offer 49. 丑数.py ├── 剑指 Offer 60. n个骰子的点数.py ├── 变态跳台阶.py └── 矩形覆盖.py ├── 15. 排序算法 ├── Bubblesort.py ├── Heapsort.py ├── Insertion Sort.py ├── Linear Sorting.cpp ├── Mergesort.py ├── Quicksort.py ├── Selection Sort.py └── Shell's Sort.py ├── 16. 树和链表结合 ├── 109. Convert Sorted List to Binary Search Tree.py ├── 114. Flatten Binary Tree to Linked List.py └── 剑指 Offer 36. 二叉搜索树与双向链表.py ├── 17. 树的重新构建 ├── 1008. Construct Binary Search Tree from Preorder Traversal.py ├── 105. Construct Binary Tree from Preorder and Inorder Traversal.py ├── 106. Construct Binary Tree from Inorder and Postorder Traversal.py ├── 606. Construct String from Binary Tree.py └── 889. Construct Binary Tree from Preorder and Postorder Traversal.py ├── 18. 位运算 ├── 136. Single Number.py ├── 190. Reverse Bits.py ├── 540. Single Element in a Sorted Array.py ├── 剑指 Offer 15. 二进制中1的个数.py ├── 剑指 Offer 56 - I. 数组中数字出现的次数.py └── 剑指 Offer 56 - II. 数组中数字出现的次数 II.py ├── 19. 字符串 ├── 8. String to Integer (atoi).py ├── 剑指 Offer 20. 表示数值的字符串.py ├── 剑指 Offer 58 - I. 翻转单词顺序.py └── 剑指 Offer 58 - II. 左旋转字符串.py ├── 2. 双指针 ├── 1. Two Sum.py ├── 11. Container With Most Water.py ├── 16. 3Sum Closest.py ├── 18. 4Sum.py ├── 26. Remove Duplicates from Sorted Array.py ├── 27. Remove Element.py ├── 283. Move Zeroes.py ├── 42. Trapping Rain Water.py ├── 75. Sort Colors.py ├── 86. Partition List.py ├── 977. Squares of a Sorted Array.py ├── Two Sum II - Input array is sorted.py ├── 剑指 Offer 04. 二维数组中的查找.py └── 剑指 Offer 21. 调整数组顺序使奇数位于偶数前面.py ├── 20. stack └── 剑指 Offer 31. 栈的压入、弹出序列.py ├── 21. math ├── 172. Factorial Trailing Zeroes.py └── 470. Implement Rand10() Using Rand7().java ├── 22. array └── 剑指 Offer 66. 构建乘积数组.py ├── 23. 二叉搜索树 ├── 二叉树的下一个结点.py ├── 剑指 Offer 68 - I. 二叉搜索树的最近公共祖先.py └── 剑指 Offer 68 - II. 二叉树的最近公共祖先.py ├── 3. 快慢指针-链表题目 ├── JZ56删除链表中重复的结点.py ├── 141. Linked List Cycle.py ├── 142. Linked List Cycle II.py ├── 234. Palindrome Linked List.py ├── 61. Rotate List.py ├── 剑指 Offer 18. 删除链表的节点.py ├── 剑指 Offer 22. 链表中倒数第k个节点.py ├── 剑指 Offer 35. 复杂链表的复制.py └── 剑指 Offer 52. 两个链表的第一个公共节点.py ├── 4. 原地链表翻转 ├── 206. Reverse Linked List.py ├── 234. Palindrome Linked List.py ├── 25. Reverse Nodes in k-Group.py └── 92. Reverse Linked List II.py ├── 5. 区间合并 ├── 56. Merge Intervals.py ├── 57. Insert Interval.py └── 986. Interval List Intersections.py ├── 6. 无序限定范围的数组元素查找O(N) ├── 41. First Missing Positive.py ├── 448. Find All Numbers Disappeared in an Array.py └── 剑指 Offer 03. 数组中重复的数字.py ├── 7. BFS ├── 102. Binary Tree Level Order Traversal.py ├── 103. Binary Tree Zigzag Level Order Traversal.py ├── 127. Word Ladder.py ├── 207. Course Schedule.py └── 297. Serialize and Deserialize Binary Tree.py ├── 8. 树的DFS ├── 100. Same Tree.py ├── 101. Symmetric Tree.py ├── 104. Maximum Depth of Binary Tree.py ├── 110. Balanced Binary Tree.py ├── 111. Minimum Depth of Binary Tree.py ├── 112. Path Sum.py ├── 113. Path Sum II.py ├── 437. Path Sum III.py ├── 剑指 Offer 26. 树的子结构.py ├── 剑指 Offer 33. 二叉搜索树的后序遍历序列.py └── 剑指 Offer 54. 二叉搜索树的第k大节点.py ├── 9. DFS-递归-回溯法 ├── 131. Palindrome Partitioning.py ├── 17. Letter Combinations of a Phone Number.py ├── 39. Combination Sum.py ├── 40. Combination Sum II.py ├── 46. Permutations.py ├── 47. Permutations II.py ├── 78. Subsets.py ├── 79. Word Search.py ├── 90. Subsets II.py └── 剑指 Offer 13. 机器人的运动范围.py └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Initially taken from Github's Python gitignore file 2 | 3 | # Byte-compiled / optimized / DLL files 4 | __pycache__/ 5 | *.py[cod] 6 | *$py.class 7 | 8 | # C extensions 9 | *.so 10 | 11 | # Distribution / packaging 12 | .Python 13 | build/ 14 | develop-eggs/ 15 | dist/ 16 | downloads/ 17 | eggs/ 18 | .eggs/ 19 | lib/ 20 | lib64/ 21 | parts/ 22 | sdist/ 23 | var/ 24 | wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | 53 | # Translations 54 | *.mo 55 | *.pot 56 | 57 | # Django stuff: 58 | *.log 59 | local_settings.py 60 | db.sqlite3 61 | 62 | # Flask stuff: 63 | instance/ 64 | .webassets-cache 65 | 66 | # Scrapy stuff: 67 | .scrapy 68 | 69 | # Sphinx documentation 70 | docs/_build/ 71 | 72 | # PyBuilder 73 | target/ 74 | 75 | # Jupyter Notebook 76 | .ipynb_checkpoints 77 | 78 | # IPython 79 | profile_default/ 80 | ipython_config.py 81 | 82 | # pyenv 83 | .python-version 84 | 85 | # celery beat schedule file 86 | celerybeat-schedule 87 | 88 | # SageMath parsed files 89 | *.sage.py 90 | 91 | # Environments 92 | .env 93 | .venv 94 | env/ 95 | venv/ 96 | ENV/ 97 | env.bak/ 98 | venv.bak/ 99 | 100 | # Spyder project settings 101 | .spyderproject 102 | .spyproject 103 | 104 | # Rope project settings 105 | .ropeproject 106 | 107 | # mkdocs documentation 108 | /site 109 | 110 | # mypy 111 | .mypy_cache/ 112 | .dmypy.json 113 | dmypy.json 114 | 115 | # Pyre type checker 116 | .pyre/ 117 | .idea/ 118 | toy*.py 119 | .DS_Store 120 | toy*.py 121 | post/ 122 | data/ 123 | .vscode -------------------------------------------------------------------------------- /1. 滑动窗口/121. Best Time to Buy and Sell Stock.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxProfit(self, prices: List[int]) -> int: 3 | if not prices: 4 | return 0 5 | min_price_so_far = prices[0] 6 | res = 0 7 | for i in range(1, len(prices)): 8 | min_price_so_far = min(prices[i], min_price_so_far) 9 | res = max(res, prices[i]-min_price_so_far) 10 | return res 11 | -------------------------------------------------------------------------------- /1. 滑动窗口/239. Sliding Window Maximum.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | 4 | class Solution: 5 | def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: 6 | n = len(nums) 7 | sw = deque() 8 | for i in range(k): 9 | while sw and nums[i] > nums[sw[-1]]: 10 | sw.pop() 11 | sw.append(i) 12 | ans = [] 13 | for i in range(k, n): 14 | ans.append(nums[sw[0]]) 15 | 16 | while sw and sw[0] <= i-k: 17 | sw.popleft() 18 | while sw and nums[i] > nums[sw[-1]]: 19 | sw.pop() 20 | sw.append(i) 21 | 22 | ans.append(nums[sw[0]]) 23 | return ans 24 | -------------------------------------------------------------------------------- /1. 滑动窗口/3. Longest Substring Without Repeating Characters.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def lengthOfLongestSubstring(self, s): 3 | """ 4 | :type s: str 5 | :rtype: int 6 | """ 7 | if len(s) == 0 or not s: 8 | return 0 9 | res = 1 10 | start = 0 11 | ch_map = {} 12 | for i in range(len(s)): 13 | offer = s[i] 14 | if offer not in ch_map: 15 | ch_map[offer] = i 16 | else: 17 | if ch_map[offer] < start: # not in the current seq 18 | ch_map[offer] = i 19 | else: 20 | start = ch_map[offer]+1 21 | ch_map[offer] = i 22 | res = max(i-start+1, res) 23 | return res 24 | -------------------------------------------------------------------------------- /1. 滑动窗口/53. Maximum Subarray.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxSubArray(self, nums: List[int]) -> int: 3 | if not nums: 4 | return 0 5 | res = nums[0] 6 | res_so_far = nums[0] 7 | for i in range(1, len(nums)): 8 | res_so_far = max(nums[i], nums[i]+res_so_far) 9 | res = max(res, res_so_far) 10 | return res 11 | -------------------------------------------------------------------------------- /1. 滑动窗口/剑指 Offer 57 - II. 和为s的连续正数序列.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def FindContinuousSequence(self, tsum): 4 | # write code here 5 | end = (tsum+1)//2 6 | res = [] 7 | for j in range(2, end+1): 8 | consume = True 9 | for i in range(1, j): 10 | if consume: 11 | tmp = ((i+j)*(j-i+1))/2 12 | if tmp == tsum: 13 | res.append(list(range(i, j+1))) 14 | elif tmp > tsum: 15 | continue 16 | else: 17 | consume = False 18 | else: 19 | break 20 | return res 21 | -------------------------------------------------------------------------------- /10. 双堆模式/155. Min Stack.py: -------------------------------------------------------------------------------- 1 | import math 2 | class MinStack: 3 | def __init__(self): 4 | self.stack = [] 5 | self.min_stack = [] 6 | 7 | def push(self, node): 8 | # write code here 9 | self.stack.append(node) 10 | if not self.min_stack or self.min_stack[-1] >= node: 11 | self.min_stack.append(node) 12 | 13 | def pop(self): 14 | # write code here 15 | node = self.stack.pop() 16 | if node == self.min_stack[-1]: 17 | self.min_stack.pop() 18 | return node 19 | def top(self): 20 | # write code here 21 | return self.stack[-1] 22 | def getMin(self): 23 | # write code here 24 | return self.min_stack[-1] 25 | 26 | 27 | # Your MinStack object will be instantiated and called as such: 28 | # obj = MinStack() 29 | # obj.push(x) 30 | # obj.pop() 31 | # param_3 = obj.top() 32 | # param_4 = obj.getMin() -------------------------------------------------------------------------------- /10. 双堆模式/295. Find Median from Data Stream.py: -------------------------------------------------------------------------------- 1 | import heapq 2 | class MedianFinder: 3 | 4 | def __init__(self): 5 | """ 6 | initialize your data structure here. 7 | """ 8 | self.minheap = [] 9 | self.maxheap = [] 10 | 11 | def addNum(self, num: int) -> None: 12 | if not self.maxheap : 13 | heapq.heappush(self.maxheap, -num) 14 | return 15 | if num < - self.maxheap[0]: 16 | heapq.heappush(self.maxheap, -num) 17 | if len(self.maxheap) > len(self.minheap)+1 : 18 | val = - heapq.heappop(self.maxheap) 19 | heapq.heappush(self.minheap, val) 20 | else: 21 | heapq.heappush(self.minheap, num) 22 | if len(self.minheap) > len(self.maxheap)+1 : 23 | val = heapq.heappop(self.minheap) 24 | heapq.heappush(self.maxheap, -val) 25 | 26 | 27 | def findMedian(self) -> float: 28 | if len(self.minheap) > len(self.maxheap): 29 | return self.minheap[0] 30 | elif len(self.minheap) < len(self.maxheap): 31 | return - self.maxheap[0] 32 | else: 33 | return (- self.maxheap[0] + self.minheap[0]) /2 34 | 35 | 36 | # Your MedianFinder object will be instantiated and called as such: 37 | # obj = MedianFinder() 38 | # obj.addNum(num) 39 | # param_2 = obj.findMedian() -------------------------------------------------------------------------------- /10. 双堆模式/480. Sliding Window Median.py: -------------------------------------------------------------------------------- 1 | """ 2 | # BCR 3 | Runtime: O(n) 4 | Spacetime: O(1) 5 | 6 | # Brute force soultion 7 | Create z subsets of nums, where z is len(nums) / k 8 | Sort z 9 | calcuate median 10 | Runtime: O(n * k * log k) -- calling merge sort on each subset in z 11 | Spacetime: O(z), -- where z is len(nums) / k 12 | 13 | # Two heap apporach 14 | create a max heap and min heap to effecintly model the middle of the array so its easy to calculat the median. 15 | use a sliding window of size k, to iterate through nums and populate the heaps 16 | calcuate the median when heaps equal size k 17 | slide the window, remove the value that is no longer included, add the new value 18 | repeat 19 | 20 | Runtime: O( n * k ) 21 | Spacetime: O(k) 22 | 23 | """ 24 | import heapq 25 | from heapq import * 26 | 27 | class Solution: 28 | 29 | @staticmethod 30 | def calculate_median(max_heap: List[int], min_heap: List[int]) -> float: 31 | if len(max_heap) == len(min_heap): 32 | return (-max_heap[0] + min_heap[0]) / 2.0 33 | return min_heap[0] 34 | 35 | @staticmethod 36 | def add_to_heaps(max_heap: List[int], min_heap: List[int], num) -> None: 37 | heappush(max_heap, -heappushpop(min_heap, num)) 38 | 39 | if len(max_heap) > len(min_heap): 40 | heappush(min_heap, -heappop(max_heap)) 41 | 42 | @staticmethod 43 | def remove_from_heap(heap: List[int], num) -> None: 44 | index = heap.index(num) 45 | # delete in O(1) 46 | # replace the value we want to remove with the last value 47 | heap[index] = heap[-1] 48 | del heap[-1] 49 | 50 | # Restore heap property thoughout the tree 51 | if index < len(heap): 52 | heapq._siftup(heap, index) 53 | heapq._siftdown(heap, 0, index) 54 | 55 | def remove_from_heaps(self, max_heap: List[int], min_heap: List[int], num) -> None: 56 | if min_heap[0] <= num: 57 | self.remove_from_heap(min_heap, num) 58 | return 59 | self.remove_from_heap(max_heap, -num) 60 | 61 | def medianSlidingWindow(self, nums: List[int], k: int) -> List[float]: 62 | max_heap: List[int] = [] 63 | min_heap: List[int] = [] 64 | result: List[int] = [] 65 | size_of_k = k - 1 66 | 67 | for i in range(size_of_k): 68 | self.add_to_heaps(max_heap, min_heap, nums[i]) 69 | 70 | for i in range(size_of_k, len(nums)): 71 | self.add_to_heaps(max_heap, min_heap, nums[i]) 72 | median = self.calculate_median(max_heap, min_heap) 73 | result.append(median) 74 | self.remove_from_heaps(max_heap, min_heap, nums[i - size_of_k ]) 75 | 76 | return result -------------------------------------------------------------------------------- /10. 双堆模式/剑指 Offer 09.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def __init__(self): 4 | self.stack1 = [] 5 | self.stack2 = [] 6 | def push(self, node): 7 | # write code here 8 | self.stack1.append(node) 9 | def pop(self): 10 | # return xx 11 | if self.stack2: 12 | return self.stack2.pop() 13 | if self.stack1: 14 | while self.stack1: 15 | self.stack2.append(self.stack1.pop()) 16 | return self.stack2.pop() 17 | -------------------------------------------------------------------------------- /11. 2分变种/153. Find Minimum in Rotated Sorted Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findMin(self, nums: List[int]) -> int: 3 | if not nums: 4 | return 5 | if len(nums) == 1: 6 | return nums[0] 7 | 8 | start = 0 9 | end = len(nums)-1 10 | while start < end-1: 11 | mid = start + (end-start)//2 12 | if nums[mid] < nums[end]: 13 | end = mid 14 | else: 15 | start = mid 16 | return min(nums[start], nums[end]) 17 | -------------------------------------------------------------------------------- /11. 2分变种/154. Find Minimum in Rotated Sorted Array II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findMin(self, nums: List[int]) -> int: 3 | if not nums: 4 | return 5 | if len(nums) == 1: 6 | return nums[0] 7 | 8 | start = 0 9 | end = len(nums)-1 10 | while start + 1 < end: 11 | while start < len(nums)-1 and nums[start] == nums[start+1]: 12 | start += 1 13 | while end > 0 and nums[end] == nums[end-1]: 14 | end -= 1 15 | mid = start + (end-start)//2 16 | if nums[mid] < nums[end]: 17 | end = mid 18 | else: 19 | start = mid 20 | return min(nums[start], nums[end]) 21 | -------------------------------------------------------------------------------- /11. 2分变种/162. Find Peak Element.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findPeakElement(self, nums: List[int]) -> int: 3 | if not nums: 4 | return 0 5 | start = 0 6 | end = len(nums)-1 7 | 8 | # 21 9 | while start < end-1: 10 | mid = start + (end-start)//2 11 | if nums[mid] > nums[mid+1]: 12 | end = mid 13 | else: 14 | start = mid 15 | if nums[start] > nums[end]: 16 | return start 17 | else: 18 | return end 19 | -------------------------------------------------------------------------------- /11. 2分变种/33. Search in Rotated Sorted Array.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def search(self, nums, target): 3 | """ 4 | :type nums: List[int] 5 | :type target: int 6 | :rtype: int 7 | """ 8 | if not nums or len(nums) == 0: 9 | return -1 10 | start = 0 11 | end = len(nums)-1 12 | while start+1 < end: 13 | mid = start + (end-start)//2 14 | if nums[mid] == target: 15 | return mid 16 | if nums[start] < nums[mid]: 17 | if nums[start] <= target < nums[mid]: 18 | end = mid 19 | else: 20 | start = mid 21 | else: 22 | if nums[mid] <= target <= nums[end]: 23 | start = mid 24 | else: 25 | end = mid 26 | if nums[start] == target: 27 | return start 28 | if nums[end] == target: 29 | return end 30 | return -1 31 | -------------------------------------------------------------------------------- /11. 2分变种/34. Find First and Last Position of Element in Sorted Array.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def searchRange(self, nums, target): 3 | """ 4 | :type nums: List[int] 5 | :type target: int 6 | :rtype: List[int] 7 | """ 8 | if not nums or len(nums) == 0: 9 | return [-1, -1] 10 | start, end = 0, len(nums)-1 11 | begin, stop = -1, -1 12 | while start + 1 < end: 13 | mdl = start + (end-start)//2 14 | if nums[mdl] < target: 15 | start = mdl 16 | else: 17 | end = mdl 18 | if nums[end] == target: 19 | begin = end 20 | if nums[start] == target: 21 | begin = start 22 | start, end = 0, len(nums)-1 23 | while start + 1 < end: 24 | mdl = start + (end-start)//2 25 | if nums[mdl] <= target: 26 | start = mdl 27 | else: 28 | end = mdl 29 | if nums[start] == target: 30 | stop = start 31 | if nums[end] == target: 32 | stop = end 33 | return [begin, stop] 34 | -------------------------------------------------------------------------------- /11. 2分变种/35. Search Insert Position.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def searchInsert(self, nums, target): 3 | """ 4 | :type nums: List[int] 5 | :type target: int 6 | :rtype: int 7 | """ 8 | if not nums or len(nums) == 0: 9 | return 0 10 | start = 0 11 | end = len(nums)-1 12 | while start+1 < end: 13 | mdl = start + (end - start)//2 14 | if nums[mdl] < target: 15 | start = mdl 16 | else: 17 | end = mdl 18 | 19 | if nums[start] == target: 20 | return start 21 | if nums[end] == target: 22 | return end 23 | if target < nums[start]: 24 | return start 25 | if target < nums[end]: 26 | return end 27 | return end+1 28 | -------------------------------------------------------------------------------- /11. 2分变种/540. Single Element in a Sorted Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def singleNonDuplicate(self, nums: List[int]) -> int: 3 | res = 0 4 | for num in nums: 5 | res ^= num 6 | return res 7 | 8 | # method 2 9 | class Solution: 10 | def singleNonDuplicate(self, nums: List[int]) -> int: 11 | if len(nums) == 1: 12 | return nums[0] 13 | start = 0 14 | end = len(nums)-1 15 | while start +1 < end: 16 | mid = start + (end-start)//2 17 | if mid % 2 == 0: # mid is even 18 | if nums[mid] == nums[mid+1]: 19 | start = mid 20 | else: 21 | end = mid 22 | else: 23 | if nums[mid] == nums[mid-1]: 24 | start = mid 25 | else: 26 | end = mid 27 | # print(nums[start], nums[end]) 28 | if start % 2 == 0: 29 | if nums[start] != nums[start+1]: 30 | return nums[start] 31 | else: 32 | return nums[end] 33 | else: 34 | if nums[start] != nums[start-1]: 35 | return nums[start] 36 | else: 37 | return nums[end] -------------------------------------------------------------------------------- /11. 2分变种/剑指 Offer 16. 数值的整数次方.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def myPow(self, x: float, n: int) -> float: 3 | tmp = 1 4 | if n < 0: 5 | x = 1 / x 6 | n *= -1 7 | while n: 8 | if n & 1: 9 | tmp *= x 10 | x *= x 11 | n >>= 1 12 | return tmp 13 | -------------------------------------------------------------------------------- /12. 前K大的数模式HEAP/215. Kth Largest Element in an Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findKthLargest(self, nums: List[int], k: int) -> int: 3 | if not nums or len(nums) < k: 4 | return 5 | if len(nums)==1: 6 | return nums[0] 7 | # method 1 8 | # import heapq 9 | # minq = [] 10 | # for num in nums: 11 | # if len(minq) < k: 12 | # heapq.heappush(minq, num) 13 | # else: 14 | # topk = minq[0] 15 | # if num > topk: 16 | # heapq.heappop(minq) 17 | # heapq.heappush(minq, num) 18 | # return minq[0] 19 | 20 | # partition 21 | target_k = len(nums) - k 22 | start = 0 23 | end = len(nums)-1 24 | 25 | while start <= end: 26 | idx_k = self.partition(nums, start, end) 27 | if idx_k == target_k: 28 | return nums[idx_k] 29 | elif idx_k < target_k: 30 | start = idx_k+1 31 | else: 32 | end = idx_k-1 33 | 34 | def partition(self, nums, start, end): 35 | pivot = nums[end] 36 | slow = fast = start 37 | 38 | while fast < end: 39 | if nums[fast] <= pivot: 40 | nums[fast], nums[slow] = nums[slow], nums[fast] 41 | slow += 1 42 | fast += 1 43 | nums[slow], nums[end] = nums[end], nums[slow] 44 | return slow 45 | -------------------------------------------------------------------------------- /12. 前K大的数模式HEAP/347. Top K Frequent Elements.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def topKFrequent(self, nums: List[int], k: int) -> List[int]: 3 | counter = {} 4 | for num in nums: 5 | counter[num] = counter.get(num, 0) + 1 6 | top_k = k 7 | # counter = [(k,v) for k,v in counter.items()] 8 | # counter = sorted(counter, key= lambda x: -x[1]) 9 | # return [c[0] for c in counter[:(k)]] 10 | import heapq 11 | minheap = [] 12 | for i, (k, v) in enumerate(counter.items()): 13 | if i < top_k: 14 | heapq.heappush(minheap, (v, k)) 15 | else: 16 | _v, _k = minheap[0] 17 | if v > _v: 18 | heapq.heappop(minheap) 19 | heapq.heappush(minheap, (v, k)) 20 | # print(minheap) 21 | return [k for v, k in minheap] 22 | -------------------------------------------------------------------------------- /12. 前K大的数模式HEAP/373. Find K Pairs with Smallest Sums.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def kSmallestPairs(self, nums1: List[int], nums2: List[int], k: int) -> List[List[int]]: 3 | if not nums1 or not nums2: 4 | return [] 5 | maxheap = [] 6 | import heapq 7 | i = 0 8 | for num1 in nums1: 9 | for num2 in nums2: 10 | if i < k: 11 | heapq.heappush(maxheap, (-(num1+num2), [num1, num2])) 12 | i += 1 13 | else: 14 | k_min, [n1, n2] = maxheap[0] 15 | print(-k_min) 16 | if num1+num2 < -k_min: 17 | heapq.heappop(maxheap) 18 | heapq.heappush(maxheap, (-(num1+num2), [num1, num2])) 19 | 20 | return [v for k, v in maxheap] 21 | -------------------------------------------------------------------------------- /13. K路归并/21. Merge Two Sorted Lists.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode(object): 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | class Solution(object): 8 | def mergeTwoLists(self, l1, l2): 9 | """ 10 | :type l1: ListNode 11 | :type l2: ListNode 12 | :rtype: ListNode 13 | """ 14 | if not l1: 15 | return l2 16 | if not l2: 17 | return l1 18 | dummy = ListNode(-1) 19 | cur = dummy 20 | while l1 and l2: 21 | if l1.val < l2.val: 22 | cur.next = l1 23 | l1 = l1.next 24 | else: 25 | cur.next = l2 26 | l2 = l2.next 27 | cur = cur.next 28 | if l1: 29 | cur.next = l1 30 | if l2: 31 | cur.next = l2 32 | return dummy.next 33 | -------------------------------------------------------------------------------- /13. K路归并/23. Merge k Sorted Lists.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | class Solution: 8 | def mergeKLists(self, lists: List[ListNode]) -> ListNode: 9 | import heapq 10 | minq = [] 11 | i = 0 12 | for _list in lists: 13 | if _list: 14 | heapq.heappush(minq, (_list.val, i, _list)) 15 | i += 1 16 | dummy = ListNode(-1) 17 | cur = dummy 18 | while minq: 19 | val, _, node = heapq.heappop(minq) 20 | if node.next: 21 | heapq.heappush(minq, (node.next.val, i, node.next)) 22 | i += 1 23 | cur.next = node 24 | cur = cur.next 25 | return dummy.next 26 | -------------------------------------------------------------------------------- /14. DP 动态规划/10. Regular Expression Matching.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isMatch(self, s: str, p: str) -> bool: 3 | dp = [[False]*(len(s)+1) for i in range(len(p)+1)] 4 | for i in range(len(p)+1): 5 | for j in range(len(s)+1): 6 | if i == 0: 7 | if j == 0: 8 | dp[i][j] = True 9 | continue 10 | if j == 0: 11 | if i >= 2 and p[i-1] == "*": 12 | dp[i][j] = dp[i-2][j] 13 | continue 14 | if p[i-1] == s[j-1] or p[i-1] == '.': 15 | dp[i][j] = dp[i-1][j-1] 16 | if p[i-1] == '*': 17 | dp[i][j] = dp[i-2][j] 18 | if s[j-1] == p[i-2] or p[i-2] == '.': 19 | dp[i][j] = dp[i][j] or dp[i][j-1] 20 | return dp[-1][-1] 21 | -------------------------------------------------------------------------------- /14. DP 动态规划/1143. Longest Common Subsequence.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def longestCommonSubsequence(self, text1: str, text2: str) -> int: 3 | dp = [[0]*(len(text2)+1) for i in range(len(text1)+1)] 4 | for i in range(1, len(text1)+1): 5 | for j in range(1, len(text2)+1): 6 | if text1[i-1] == text2[j-1]: 7 | dp[i][j] = dp[i-1][j-1]+1 8 | else: 9 | dp[i][j] = max(dp[i-1][j], dp[i][j-1]) 10 | return dp[-1][-1] 11 | -------------------------------------------------------------------------------- /14. DP 动态规划/120. Triangle.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def minimumTotal(self, triangle: List[List[int]]) -> int: 3 | if not triangle: 4 | return 0 5 | for i in range(len(triangle)-2, -1, -1): 6 | tri = triangle[i] 7 | for j in range(len(tri)): 8 | tri[j] = tri[j]+min(triangle[i+1][j], triangle[i+1][j+1]) 9 | # print(triangle) 10 | return triangle[0][0] 11 | -------------------------------------------------------------------------------- /14. DP 动态规划/121. Best Time to Buy and Sell Stock.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxProfit(self, prices: List[int]) -> int: 3 | if not prices: 4 | return 0 5 | min_price_so_far = prices[0] 6 | res = 0 7 | for i in range(1, len(prices)): 8 | min_price_so_far = min(prices[i], min_price_so_far) 9 | res = max(res, prices[i]-min_price_so_far) 10 | 11 | return res 12 | -------------------------------------------------------------------------------- /14. DP 动态规划/122. Best Time to Buy and Sell Stock II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxProfit(self, prices: List[int]) -> int: 3 | res = 0 4 | if not prices: 5 | return 0 6 | for i in range(1, len(prices)): 7 | res += max(prices[i] - prices[i-1], 0) 8 | return res 9 | -------------------------------------------------------------------------------- /14. DP 动态规划/123. Best Time to Buy and Sell Stock III.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxProfit(self, prices: List[int]) -> int: 3 | if not prices or len(prices) == 1: 4 | return 0 5 | p1 = [0]*len(prices) 6 | p2 = [0]*len(prices) 7 | min_so_far = prices[0] 8 | max_profit = 0 9 | for i in range(len(prices)): 10 | p1[i] = max(max_profit, prices[i] - min_so_far) 11 | 12 | if prices[i] < min_so_far: 13 | min_so_far = prices[i] 14 | if p1[i] > max_profit: 15 | max_profit = p1[i] 16 | 17 | max_profit = 0 18 | max_so_far = prices[-1] 19 | for j in range(len(prices)-1, -1, -1): 20 | p2[j] = max(max_profit, max_so_far - prices[j]) 21 | if p2[j] > max_profit: 22 | max_profit = p2[j] 23 | if max_so_far < prices[j]: 24 | max_so_far = prices[j] 25 | 26 | res = 0 27 | for i in range(len(prices)): 28 | res = max(res, p1[i]+p2[i]) 29 | return res 30 | -------------------------------------------------------------------------------- /14. DP 动态规划/139. Word Break.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def wordBreak(self, s: str, wordDict: List[str]) -> bool: 3 | dp = [False]*(len(s)+1) 4 | dp[0] = True 5 | for i in range(len(s)): 6 | for j in range(i+1): 7 | if s[j:i+1] in wordDict: 8 | if dp[j]: 9 | dp[i+1] = True 10 | break 11 | return dp[-1] 12 | -------------------------------------------------------------------------------- /14. DP 动态规划/152. Maximum Product Subarray.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxProduct(self, nums: List[int]) -> int: 3 | if not nums: 4 | return 0 5 | res = nums[0] 6 | maxP_till_now = nums[0] 7 | minP_till_now = nums[0] 8 | for i in range(1, len(nums)): 9 | _maxP_till_now = max( 10 | nums[i], nums[i]*maxP_till_now, nums[i]*minP_till_now) 11 | minP_till_now = min( 12 | nums[i], nums[i]*minP_till_now, nums[i]*maxP_till_now) 13 | maxP_till_now = _maxP_till_now 14 | res = max(res, maxP_till_now) 15 | print(minP_till_now, maxP_till_now) 16 | return res 17 | -------------------------------------------------------------------------------- /14. DP 动态规划/188. Best Time to Buy and Sell Stock IV.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxProfit(self, k: int, prices: List[int]) -> int: 3 | n = len(prices) 4 | 5 | # solve special cases 6 | if not prices or k==0: 7 | return 0 8 | 9 | if 2*k > n: 10 | res = 0 11 | for i, j in zip(prices[1:], prices[:-1]): 12 | res += max(0, i - j) 13 | return res 14 | 15 | # dp[i][used_k][ishold] = balance 16 | # ishold: 0 nothold, 1 hold 17 | dp = [[[-math.inf]*2 for _ in range(k+1)] for _ in range(n)] 18 | 19 | # set starting value 20 | dp[0][0][0] = 0 21 | dp[0][1][1] = -prices[0] 22 | 23 | # fill the array 24 | for i in range(1, n): 25 | for j in range(k+1): 26 | # transition equation 27 | dp[i][j][0] = max(dp[i-1][j][0], dp[i-1][j][1]+prices[i]) 28 | # you can't hold stock without any transaction 29 | if j > 0: 30 | dp[i][j][1] = max(dp[i-1][j][1], dp[i-1][j-1][0]-prices[i]) 31 | 32 | res = max(dp[n-1][j][0] for j in range(k+1)) 33 | return res -------------------------------------------------------------------------------- /14. DP 动态规划/198. House Robber.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def rob(self, nums) -> int: 3 | if not nums: 4 | return 0 5 | if len(nums) <= 2: 6 | return max(nums) 7 | pprev = nums[0] 8 | prev = max(nums[0], nums[1]) 9 | res = prev 10 | for i in range(2, len(nums)): 11 | cur = max(prev, nums[i]+pprev) 12 | res = max(cur, res) 13 | pprev = prev 14 | prev = cur 15 | return res 16 | -------------------------------------------------------------------------------- /14. DP 动态规划/213. House Robber II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def rob(self, nums: List[int]) -> int: 3 | if not nums: 4 | return 0 5 | if len(nums) == 1: 6 | return nums[0] 7 | if len(nums) == 3 or len(nums) == 2: 8 | return max(nums) 9 | 10 | pprev = nums[0] 11 | prev = max(nums[0], nums[1]) 12 | 13 | for i in range(2, len(nums)-1): 14 | cur = max(pprev+nums[i], prev) 15 | pprev = prev 16 | prev = cur 17 | max1 = cur 18 | 19 | pprev = nums[1] 20 | prev = max(nums[1], nums[2]) 21 | for i in range(3, len(nums)): 22 | cur2 = max(pprev + nums[i], prev) 23 | pprev = prev 24 | prev = cur2 25 | max2 = cur2 26 | return max(max1, max2) 27 | -------------------------------------------------------------------------------- /14. DP 动态规划/300. Longest Increasing Subsequence.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def lengthOfLIS(self, nums: List[int]) -> int: 3 | if not nums: 4 | return 0 5 | if len(nums) == 1: 6 | return 1 7 | dp = [1]*len(nums) 8 | dp[0] = 1 9 | res = 1 10 | for i in range(1, len(nums)): 11 | for j in range(i): 12 | if nums[i] > nums[j]: 13 | dp[i] = max(dp[i], dp[j] + 1) 14 | res = max(res, dp[i]) 15 | return res 16 | 17 | 18 | class Solution: 19 | def lengthOfLIS(self, nums: List[int]) -> int: 20 | if len(nums) < 2: 21 | return len(nums) 22 | 23 | stack = [nums[0]] 24 | for i in nums[1:]: 25 | if stack[-1] < i: 26 | stack.append(i) 27 | else: 28 | pos = bisect.bisect_left( 29 | stack, i, 0, len(stack)) # Binary seacrh 30 | stack[pos] = i 31 | return len(stack) 32 | -------------------------------------------------------------------------------- /14. DP 动态规划/309. Best Time to Buy and Sell Stock with Cooldown.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | 3 | def maxProfit(self, prices): 4 | """ 5 | :type prices: List[int] 6 | :rtype: int 7 | """ 8 | if not prices or len(prices) < 2: 9 | return 0 10 | n = len(prices) 11 | buy, sell = [0] * n, [0] * n 12 | buy[0] = -prices[0] 13 | buy[1] = max(-prices[0], -prices[1]) 14 | sell[1] = max(0, prices[1] - prices[0]) 15 | for i in xrange(2, n): 16 | buy[i] = max(sell[i - 2] - prices[i], buy[i - 1]) 17 | sell[i] = max(buy[i - 1] + prices[i], sell[i - 1]) 18 | 19 | return sell[n - 1] 20 | -------------------------------------------------------------------------------- /14. DP 动态规划/322. Coin Change.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def coinChange(self, coins: List[int], amount: int) -> int: 3 | dp = [float('Inf')] * (amount+1) 4 | dp[0] = 0 5 | 6 | for coin in coins: 7 | for j in range(coin, amount+1): 8 | dp[j] = min(dp[j], dp[j-coin]+1) 9 | return dp[amount] if dp[amount] != float('Inf') else -1 10 | -------------------------------------------------------------------------------- /14. DP 动态规划/416. Partition Equal Subset Sum.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def canPartition(self, nums: List[int]) -> bool: 3 | if not nums or len(nums) < 2: 4 | return False 5 | target = sum(nums) 6 | if target % 2 != 0: 7 | return False 8 | target = target // 2 9 | 10 | dp = [[False]*(target+1) for i in range(len(nums)+1)] 11 | for i in range(len(nums)+1): 12 | dp[i][0] = True 13 | for i in range(1, len(nums)+1): 14 | for j in range(1, target+1): 15 | if j >= nums[i-1]: 16 | dp[i][j] = dp[i-1][j] or dp[i-1][j-nums[i-1]] 17 | else: 18 | dp[i][j] = dp[i-1][j] 19 | if dp[i][target]: 20 | return True 21 | # print(dp) 22 | return dp[i][target] 23 | -------------------------------------------------------------------------------- /14. DP 动态规划/44. Wildcard Matching.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isMatch(self, s: str, p: str) -> bool: 3 | dp = [[False]*(len(s)+1) for i in range(len(p)+1)] 4 | dp[0][0] = True 5 | for i in range(1, len(p)+1): 6 | if p[i-1] == '*': 7 | dp[i][0] = dp[i-1][0] 8 | for i in range(1, len(p)+1): 9 | for j in range(1, len(s)+1): 10 | if p[i-1] == s[j-1] or p[i-1] == '?': 11 | dp[i][j] = dp[i-1][j-1] 12 | else: 13 | if p[i-1] == '*': 14 | dp[i][j] = dp[i][j-1] 15 | dp[i][j] = dp[i][j] or dp[i-1][j] 16 | return dp[-1][-1] 17 | -------------------------------------------------------------------------------- /14. DP 动态规划/5. Longest Palindromic Substring.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def longestPalindrome(self, s: str) -> str: 3 | if not s: 4 | return "" 5 | if len(s) <= 1: 6 | return s 7 | dp = [[False]*len(s) for i in range(len(s))] 8 | res = s[0] 9 | 10 | for i in range(len(s)-1, -1, -1): 11 | for j in range(i, len(s)): 12 | if i == j: 13 | dp[i][j] = True 14 | elif s[i] == s[j]: 15 | if dp[i+1][j-1] or j-i == 1: 16 | dp[i][j] = True 17 | if j-i + 1 > len(res): 18 | res = s[i:j+1] 19 | # print(dp) 20 | return res 21 | -------------------------------------------------------------------------------- /14. DP 动态规划/516. Longest Palindromic Subsequence.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def longestPalindromeSubseq(self, s: str) -> int: 3 | dp = [[0]*len(s) for i in range(len(s))] 4 | for i in range(len(s)-1, -1, -1): 5 | for j in range(i, len(s)): 6 | if i == j: 7 | dp[i][j] = 1 8 | elif s[i] == s[j]: 9 | dp[i][j] = dp[i+1][j-1]+2 10 | else: 11 | dp[i][j] = max( 12 | dp[i+1][j], dp[i][j-1] 13 | ) 14 | # print(dp) 15 | return dp[0][-1] 16 | -------------------------------------------------------------------------------- /14. DP 动态规划/518. Coin Change 2.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def change(self, amount: int, coins: List[int]) -> int: 3 | dp = [0]*(amount+1) 4 | dp[0] = 1 5 | for coin in coins: 6 | for j in range(coin, amount+1): 7 | dp[j] +=dp[j-coin] 8 | return dp[amount] -------------------------------------------------------------------------------- /14. DP 动态规划/53. Maximum Subarray.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxSubArray(self, nums: List[int]) -> int: 3 | if not nums: 4 | return 0 5 | res = nums[0] 6 | res_so_far = nums[0] 7 | for i in range(1, len(nums)): 8 | res_so_far = max(nums[i], nums[i]+res_so_far) 9 | res = max(res, res_so_far) 10 | return res 11 | -------------------------------------------------------------------------------- /14. DP 动态规划/714. Best Time to Buy and Sell Stock with Transaction Fee.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxProfit(self, prices: List[int], fee: int) -> int: 3 | if not prices: 4 | return 0 5 | if len(prices) == 1: 6 | return 0 7 | max_no_share = 0 8 | max_hold_share = 0 9 | for i in range(1, len(prices)): 10 | max_no_share, max_hold_share = max(max_no_share, max_hold_share+prices[i]-prices[i-1]-fee), max( 11 | max_no_share, max_hold_share + prices[i]-prices[i-1]) 12 | return max_no_share -------------------------------------------------------------------------------- /14. DP 动态规划/72. Edit Distance.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def minDistance(self, word1: str, word2: str) -> int: 3 | dp = [[0]*(len(word2)+1) for i in range(len(word1)+1)] 4 | for i in range(len(word1)+1): 5 | for j in range(len(word2)+1): 6 | if i == 0: 7 | dp[0][j] = j 8 | continue 9 | if j == 0: 10 | dp[i][0] = i 11 | continue 12 | if word1[i-1] == word2[j-1]: 13 | dp[i][j] = dp[i-1][j-1] 14 | else: 15 | dp[i][j] = min(dp[i-1][j], dp[i][j-1], dp[i-1][j-1])+1 16 | return dp[-1][-1] 17 | -------------------------------------------------------------------------------- /14. DP 动态规划/887. Super Egg Drop.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def superEggDrop(self, K, N): 3 | 4 | # Right now, dp[i] represents dp(1, i) 5 | dp = range(N+1) 6 | 7 | for k in xrange(2, K+1): 8 | # Now, we will develop dp2[i] = dp(k, i) 9 | dp2 = [0] 10 | x = 1 11 | for n in xrange(1, N+1): 12 | # Let's find dp2[n] = dp(k, n) 13 | # Increase our optimal x while we can make our answer better. 14 | # Notice max(dp[x-1], dp2[n-x]) > max(dp[x], dp2[n-x-1]) 15 | # is simply max(T1(x-1), T2(x-1)) > max(T1(x), T2(x)). 16 | while x < n and max(dp[x-1], dp2[n-x]) > \ 17 | max(dp[x], dp2[n-x-1]): 18 | x += 1 19 | 20 | # The final answer happens at this x. 21 | dp2.append(1 + max(dp[x-1], dp2[n-x])) 22 | 23 | dp = dp2 24 | 25 | return dp[-1] -------------------------------------------------------------------------------- /14. DP 动态规划/91. Decode Ways.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def numDecodings(self, s: str) -> int: 3 | dp = [1]*len(s) 4 | for i, char in enumerate(s): 5 | if int(char) > 0 and int(char) <= 9: 6 | if i > 0 and int(s[i-1:i+1]) >= 11 and int(s[i-1:i+1]) <= 26: 7 | dp[i] = dp[i-1]+dp[i-2] 8 | else: 9 | dp[i] = dp[i-1] 10 | elif int(char) == 0: 11 | if i >= 1 and (int(s[i-1:i+1]) == 10 or int(s[i-1:i+1]) == 20): 12 | if i == 1: 13 | dp[i] = 1 14 | else: 15 | dp[i] = dp[i-2] 16 | else: 17 | return '0' 18 | else: 19 | return '0' 20 | return dp[-1] 21 | -------------------------------------------------------------------------------- /14. DP 动态规划/剑指 Offer 10- I. 斐波那契数列.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def Fibonacci(self, n): 4 | # write code here 5 | if n == 0: 6 | return 0 7 | if n == 1: 8 | return 1 9 | ppv = 0 10 | pv = 1 11 | for i in range(2, n+1): 12 | res = ppv + pv 13 | ppv = pv 14 | pv = res 15 | return res 16 | -------------------------------------------------------------------------------- /14. DP 动态规划/剑指 Offer 10- II. 青蛙跳台阶问题.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def jumpFloor(self, n): 4 | # write code here 5 | if n == 1: 6 | return 1 7 | if n == 2: 8 | return 2 9 | prev = 2 10 | pprev = 1 11 | for i in range(3, n+1): 12 | res = prev+pprev 13 | pprev = prev 14 | prev = res 15 | return res 16 | -------------------------------------------------------------------------------- /14. DP 动态规划/剑指 Offer 14- I. 剪绳子.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def cutRope(self, n): 4 | # write code here 5 | if n == 2: 6 | return 1 7 | if n == 3: 8 | return 2 9 | dp = [1]*(n+1) 10 | dp[3] = 2 11 | for j in range(3, n+1): 12 | for i in range(j+1): 13 | dp[j] = max(dp[j], dp[j-i]*i) 14 | return dp[-1] 15 | -------------------------------------------------------------------------------- /14. DP 动态规划/剑指 Offer 46. 把数字翻译成字符串.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def translateNum(self, num: int) -> int: 3 | str_num = str(num) 4 | n = len(str_num) 5 | dp = [1 for _ in range(n + 1)] 6 | for i in range(2, n + 1): 7 | if str_num[i - 2] == '1' or \ 8 | (str_num[i - 2] == '2' and str_num[i - 1] < '6'): 9 | dp[i] = dp[i - 2] + dp[i - 1] 10 | else: 11 | dp[i] = dp[i - 1] 12 | return dp[n] 13 | 14 | 作者:z1m 15 | 链接:https://leetcode-cn.com/problems/ba-shu-zi-fan-yi-cheng-zi-fu-chuan-lcof/solution/dong-tai-gui-hua-dp-by-z1m/ 16 | 来源:力扣(LeetCode) 17 | 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 -------------------------------------------------------------------------------- /14. DP 动态规划/剑指 Offer 47. 礼物的最大价值.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def maxValue(self, grid: List[List[int]]) -> int: 3 | for i in range(len(grid)): 4 | for j in range(len(grid[0])): 5 | if i == 0 and j == 0: continue 6 | if i == 0: grid[i][j] += grid[i][j - 1] 7 | elif j == 0: grid[i][j] += grid[i - 1][j] 8 | else: grid[i][j] += max(grid[i][j - 1], grid[i - 1][j]) 9 | return grid[-1][-1] 10 | 11 | 作者:jyd 12 | 链接:https://leetcode-cn.com/problems/li-wu-de-zui-da-jie-zhi-lcof/solution/mian-shi-ti-47-li-wu-de-zui-da-jie-zhi-dong-tai-gu/ 13 | 来源:力扣(LeetCode) 14 | 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 -------------------------------------------------------------------------------- /14. DP 动态规划/剑指 Offer 49. 丑数.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def GetUglyNumber_Solution(self, index): 4 | # write code here 5 | if index <= 0: 6 | return 0 7 | dp = [1]*index 8 | a, b, c = 0, 0, 0 9 | for i in range(1, index): 10 | da = dp[a]*2 11 | db = dp[b]*3 12 | dc = dp[c]*5 13 | num = min(da, db, dc) 14 | if num == da: 15 | a += 1 16 | if num == db: 17 | b += 1 18 | if num == dc: 19 | c += 1 20 | dp[i] = num 21 | return dp[-1] 22 | -------------------------------------------------------------------------------- /14. DP 动态规划/剑指 Offer 60. n个骰子的点数.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def twoSum(self, n: int) -> List[float]: 3 | 4 | dp = [ [0 for _ in range(6*n+1)] for _ in range(n+1)] 5 | for i in range(1,7): 6 | dp[1][i] = 1 7 | 8 | for i in range(2,n+1): 9 | for j in range(i,i*6+1): 10 | for k in range(1,7): 11 | if j >= k+1: 12 | dp[i][j] +=dp[i-1][j-k] 13 | res = [] 14 | for i in range(n,n*6+1): 15 | res.append(dp[n][i]*1.0/6**n) 16 | return res 17 | 18 | 作者:up2m 19 | 链接:https://leetcode-cn.com/problems/nge-tou-zi-de-dian-shu-lcof/solution/rong-yi-li-jie-de-pythondong-tai-gui-hua-fang-fa-b/ 20 | 来源:力扣(LeetCode) 21 | 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 -------------------------------------------------------------------------------- /14. DP 动态规划/变态跳台阶.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def jumpFloorII(self, n): 4 | if n == 1: 5 | return 1 6 | if n == 2: 7 | return 2 8 | dp = [1] * n 9 | dp[0] = 1 10 | dp[1] = 2 11 | for i in range(2, n): 12 | for k in range(i): 13 | dp[i] += dp[k] 14 | 15 | # print(dp) 16 | return dp[-1] 17 | -------------------------------------------------------------------------------- /14. DP 动态规划/矩形覆盖.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def rectCover(self, number): 4 | # write code here 5 | if number <= 1: 6 | return number 7 | elif number == 2: 8 | return 2 9 | pv = 2 10 | ppv = 1 11 | for i in range(number-2): 12 | res = pv+ppv 13 | ppv = pv 14 | pv = res 15 | return res 16 | -------------------------------------------------------------------------------- /15. 排序算法/Bubblesort.py: -------------------------------------------------------------------------------- 1 | def bubbleSort(arr): 2 | n = len(arr) 3 | 4 | # Traverse through all array elements 5 | for i in range(n-1): 6 | # range(n) also work but outer loop will repeat one time more than needed. 7 | 8 | # Last i elements are already in place 9 | for j in range(0, n-i-1): 10 | 11 | # traverse the array from 0 to n-i-1 12 | # Swap if the element found is greater 13 | # than the next element 14 | if arr[j] > arr[j+1] : 15 | arr[j], arr[j+1] = arr[j+1], arr[j] 16 | 17 | # Driver code to test above 18 | arr = [64, 34, 25, 12, 22, 11, 90] 19 | 20 | bubbleSort(arr) 21 | 22 | print ("Sorted array is:") 23 | for i in range(len(arr)): 24 | print ("%d" %arr[i]), -------------------------------------------------------------------------------- /15. 排序算法/Heapsort.py: -------------------------------------------------------------------------------- 1 | # Python program for implementation of heap Sort 2 | 3 | # To heapify subtree rooted at index i. 4 | # n is size of heap 5 | def heapify(arr, n, i): 6 | largest = i # Initialize largest as root 7 | l = 2 * i + 1 # left = 2*i + 1 8 | r = 2 * i + 2 # right = 2*i + 2 9 | 10 | # See if left child of root exists and is 11 | # greater than root 12 | if l < n and arr[i] < arr[l]: 13 | largest = l 14 | 15 | # See if right child of root exists and is 16 | # greater than root 17 | if r < n and arr[largest] < arr[r]: 18 | largest = r 19 | 20 | # Change root, if needed 21 | if largest != i: 22 | arr[i],arr[largest] = arr[largest],arr[i] # swap 23 | 24 | # Heapify the root. 25 | heapify(arr, n, largest) 26 | 27 | # The main function to sort an array of given size 28 | def heapSort(arr): 29 | n = len(arr) 30 | 31 | # Build a maxheap. 32 | # Since last parent will be at ((n//2)-1) we can start at that location. 33 | for i in range(n // 2 - 1, -1, -1): 34 | heapify(arr, n, i) 35 | 36 | # One by one extract elements 37 | for i in range(n-1, 0, -1): 38 | arr[i], arr[0] = arr[0], arr[i] # swap 39 | heapify(arr, i, 0) 40 | 41 | # Driver code to test above 42 | arr = [ 12, 11, 13, 5, 6, 7] 43 | heapSort(arr) 44 | n = len(arr) 45 | print ("Sorted array is") 46 | for i in range(n): 47 | print ("%d" %arr[i]), 48 | # This code is contributed by Mohit Kumra -------------------------------------------------------------------------------- /15. 排序算法/Insertion Sort.py: -------------------------------------------------------------------------------- 1 | def insert_sott(arr): 2 | if not arr or len(arr)==1: 3 | return arr 4 | 5 | for i in range(1, len(arr)): 6 | min_idx = i 7 | min_val = arr[i] 8 | j = i - 1 9 | while j >= 0 and arr[j] > min_val: 10 | arr[j+1] = arr[j] 11 | min_idx = j 12 | j -= 1 13 | arr[min_idx] = min_val 14 | return arr 15 | 16 | print(insert_sott([3,2,1,2,3,4])) -------------------------------------------------------------------------------- /15. 排序算法/Linear Sorting.cpp: -------------------------------------------------------------------------------- 1 | % # Counting Sort 2 | % # the counting sort algorithm sort interger from a know range $k$ and it is a stable sort 3 | void countingsort(int* array,int size, int k){ 4 | int num[k+1]={0}; 5 | int tmp[size]; 6 | // for(int i = 0; i <= k; i++){num[i] = 0;} 7 | for(int i = 0; i < size; i++){ 8 | num[array[i]] ++; 9 | } 10 | for(int i = 1; i <= k; i++){ 11 | num[i] += num[i-1]; 12 | } 13 | for(int i= size-1; i >= 0; i--){ 14 | int index = num[array[i]]; 15 | tmp[index] = array[i]; 16 | num[array[i]]--; 17 | } 18 | for(int i = 0; i < size; i++){ 19 | array[i] = tmp[i]; 20 | } 21 | } -------------------------------------------------------------------------------- /15. 排序算法/Mergesort.py: -------------------------------------------------------------------------------- 1 | def merge_sort(arr): 2 | if not arr or len(arr) == 1: 3 | return arr 4 | mergeSort(arr, s=0, e=len(arr)-1) 5 | return arr 6 | 7 | def mergeSort(arr, s, e): 8 | if s >= e: 9 | return 10 | m = s + (e-s)//2 11 | mergeSort(arr, s, m) 12 | mergeSort(arr, m+1, e) 13 | merge(arr, s, m, e) 14 | 15 | def merge(arr, s, m, e): 16 | i = s 17 | j = m+1 18 | 19 | new_arr = [] 20 | while i <= m and j <= e: 21 | if arr[i] < arr[j]: 22 | new_arr.append(arr[i]) 23 | i += 1 24 | else: 25 | new_arr.append(arr[j]) 26 | j+=1 27 | while i <= m: 28 | new_arr.append(arr[i]) 29 | i+=1 30 | while j <= e: 31 | new_arr.append(arr[j]) 32 | j += 1 33 | for i in range(len(new_arr)): 34 | arr[s+i] = new_arr[i] 35 | 36 | print(merge_sort([11,2,3,4,5])) -------------------------------------------------------------------------------- /15. 排序算法/Quicksort.py: -------------------------------------------------------------------------------- 1 | def quick_sort(arr): 2 | if not arr or len(arr) == 1: 3 | return arr 4 | quickSort(arr, s=0, e=len(arr)-1) 5 | return arr 6 | 7 | def quickSort(arr, s, e): 8 | if s >= e: 9 | return 10 | else: 11 | m = partition(arr, s, e) 12 | quickSort(arr, s, m-1) 13 | quickSort(arr, m+1, e) 14 | 15 | def partition(arr, s, e): 16 | if s >= e: 17 | return s 18 | pivot = arr[e] 19 | i = s 20 | for j in range(s, e): 21 | if arr[j] <= pivot: 22 | arr[j], arr[i] = arr[i], arr[j] 23 | i += 1 24 | arr[e], arr[i] = arr[i], arr[e] 25 | return i 26 | m = partition([4,1,2,3,4,-16], 0, 5) 27 | 28 | print(quick_sort([4,1,2,3,4,-16])) -------------------------------------------------------------------------------- /15. 排序算法/Selection Sort.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dongxiaohuang/leetcode_solutions/c868a61f145387dbce18244774a87395744ef5bf/15. 排序算法/Selection Sort.py -------------------------------------------------------------------------------- /15. 排序算法/Shell's Sort.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dongxiaohuang/leetcode_solutions/c868a61f145387dbce18244774a87395744ef5bf/15. 排序算法/Shell's Sort.py -------------------------------------------------------------------------------- /16. 树和链表结合/109. Convert Sorted List to Binary Search Tree.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, val=0, next=None): 4 | # self.val = val 5 | # self.next = next 6 | # Definition for a binary tree node. 7 | # class TreeNode: 8 | # def __init__(self, val=0, left=None, right=None): 9 | # self.val = val 10 | # self.left = left 11 | # self.right = right 12 | class Solution: 13 | def sortedListToBST(self, head: ListNode) -> TreeNode: 14 | if not head: 15 | return None 16 | if not head.next: 17 | return TreeNode(head.val) 18 | prev_slow = ListNode(-1) 19 | prev_slow.next = head 20 | slow = fast = head 21 | while fast and fast.next: 22 | prev_slow = prev_slow.next 23 | slow = slow.next 24 | fast = fast.next.next 25 | root = ListNode(slow.val) 26 | root.right = self.sortedListToBST(slow.next) 27 | prev_slow.next = None 28 | root.left = self.sortedListToBST(head) 29 | return root -------------------------------------------------------------------------------- /16. 树和链表结合/114. Flatten Binary Tree to Linked List.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def __init__(self): 9 | self.prev = None 10 | 11 | def flatten(self, root): 12 | if not root: 13 | return None 14 | self.flatten(root.right) 15 | self.flatten(root.left) 16 | 17 | root.right = self.prev 18 | root.left = None 19 | self.prev = root -------------------------------------------------------------------------------- /16. 树和链表结合/剑指 Offer 36. 二叉搜索树与双向链表.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | class Solution: 8 | def Convert(self, root): 9 | # write code here 10 | if not root: 11 | return None 12 | if not root.left and not root.right: 13 | return root 14 | left = root.left 15 | self.Convert(root.left) 16 | 17 | if left: 18 | while left.right: 19 | left = left.right 20 | root.left, left.right = left, root 21 | self.Convert(root.right) 22 | right = root.right 23 | if right: 24 | while right.left: 25 | right = right.left 26 | right.left, root.right = root, right 27 | while root.left: 28 | root = root.left 29 | return root -------------------------------------------------------------------------------- /17. 树的重新构建/1008. Construct Binary Search Tree from Preorder Traversal.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def bstFromPreorder(self, preorder: List[int]) -> TreeNode: 3 | if not preorder: 4 | return None 5 | root = TreeNode(preorder[0]) 6 | i = 1 7 | while i < len(preorder) and preorder[i] < root.val: 8 | i += 1 9 | root.left = self.bstFromPreorder(preorder[1:i]) 10 | root.right = self.bstFromPreorder(preorder[i:]) 11 | return root 12 | -------------------------------------------------------------------------------- /17. 树的重新构建/105. Construct Binary Tree from Preorder and Inorder Traversal.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, val=0, left=None, right=None): 4 | # self.val = val 5 | # self.left = left 6 | # self.right = right 7 | class Solution: 8 | def buildTree(self, preorder, inorder): 9 | if not preorder or not inorder: 10 | return None 11 | 12 | rootValue = preorder[0] 13 | root = TreeNode(rootValue) 14 | inorderIndex = inorder.index(rootValue) 15 | 16 | root.left = self.buildTree( 17 | preorder[1:inorderIndex+1], inorder[:inorderIndex]) 18 | root.right = self.buildTree( 19 | preorder[inorderIndex+1:], inorder[inorderIndex+1:]) 20 | 21 | return root 22 | # preorder = [3,9,20,15,7] 23 | # inorder = [9,3,15,20,7] 24 | # buildTree( preorder, inorder) 25 | -------------------------------------------------------------------------------- /17. 树的重新构建/106. Construct Binary Tree from Inorder and Postorder Traversal.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | # @param inorder, a list of integers 10 | # @param postorder, a list of integers 11 | # @return a tree node 12 | # 12:00 13 | def buildTree(self, inorder, postorder): 14 | if not inorder or not postorder: 15 | return None 16 | 17 | root = TreeNode(postorder.pop()) 18 | inorderIndex = inorder.index(root.val) 19 | 20 | root.right = self.buildTree(inorder[inorderIndex+1:], postorder) 21 | root.left = self.buildTree(inorder[:inorderIndex], postorder) 22 | 23 | return root -------------------------------------------------------------------------------- /17. 树的重新构建/606. Construct String from Binary Tree.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def tree2str(self, t): 3 | """ 4 | :type t: TreeNode 5 | :rtype: str 6 | """ 7 | if not t: 8 | return "" 9 | if t.left is None and t.right is None: 10 | return "{}".format(t.val) 11 | elif t.right is None: 12 | return "{}({})".format(t.val, self.tree2str(t.left)) 13 | elif t.left is None: 14 | return "{}()({})".format(t.val, self.tree2str(t.right)) 15 | else: 16 | return "{}({})({})".format(t.val, self.tree2str(t.left), self.tree2str(t.right)) -------------------------------------------------------------------------------- /17. 树的重新构建/889. Construct Binary Tree from Preorder and Postorder Traversal.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def constructFromPrePost(self, pre: List[int], post: List[int]) -> TreeNode: 3 | if not pre or not post: 4 | return None 5 | root = TreeNode(pre[0]) 6 | if len(pre) == 1: 7 | return root 8 | ind = post.index(pre[1]) 9 | root.left = self.constructFromPrePost(pre[1:ind+2], post[:ind+1]) 10 | root.right = self.constructFromPrePost(pre[ind+2:], post[ind+1:-1]) 11 | return root 12 | -------------------------------------------------------------------------------- /18. 位运算/136. Single Number.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def singleNumber(self, nums: List[int]) -> int: 3 | res = 0 4 | for num in nums: 5 | res ^= num 6 | return res 7 | -------------------------------------------------------------------------------- /18. 位运算/190. Reverse Bits.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def reverseBits(self, n: int) -> int: 3 | res = 0 4 | power = 31 5 | while n: 6 | res += (n % 2) << power 7 | n = n >> 1 8 | power -= 1 9 | return res 10 | -------------------------------------------------------------------------------- /18. 位运算/540. Single Element in a Sorted Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def singleNonDuplicate(self, nums: List[int]) -> int: 3 | res = 0 4 | for num in nums: 5 | res ^= num 6 | return res 7 | 8 | # method 2 9 | class Solution: 10 | def singleNonDuplicate(self, nums: List[int]) -> int: 11 | if len(nums) == 1: 12 | return nums[0] 13 | start = 0 14 | end = len(nums)-1 15 | while start +1 < end: 16 | mid = start + (end-start)//2 17 | if mid % 2 == 0: # mid is even 18 | if nums[mid] == nums[mid+1]: 19 | start = mid 20 | else: 21 | end = mid 22 | else: 23 | if nums[mid] == nums[mid-1]: 24 | start = mid 25 | else: 26 | end = mid 27 | # print(nums[start], nums[end]) 28 | if start % 2 == 0: 29 | if nums[start] != nums[start+1]: 30 | return nums[start] 31 | else: 32 | return nums[end] 33 | else: 34 | if nums[start] != nums[start-1]: 35 | return nums[start] 36 | else: 37 | return nums[end] -------------------------------------------------------------------------------- /18. 位运算/剑指 Offer 15. 二进制中1的个数.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def NumberOf1(self, n): 3 | # write code here 4 | count = 0 5 | while n != 0: 6 | count += 1 7 | n = n & (n-1) 8 | print(n) 9 | return count 10 | -------------------------------------------------------------------------------- /18. 位运算/剑指 Offer 56 - I. 数组中数字出现的次数.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def singleNumbers(self, nums: List[int]) -> List[int]: 3 | ret = functools.reduce(lambda x, y: x ^ y, nums) 4 | div = 1 5 | while div & ret == 0: 6 | div <<= 1 7 | a, b = 0, 0 8 | for n in nums: 9 | if n & div: 10 | a ^= n 11 | else: 12 | b ^= n 13 | return [a, b] 14 | 15 | 作者:LeetCode-Solution 16 | 链接:https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/solution/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-by-leetcode/ 17 | 来源:力扣(LeetCode) 18 | 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 -------------------------------------------------------------------------------- /18. 位运算/剑指 Offer 56 - II. 数组中数字出现的次数 II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def singleNumber(self, nums: List[int]) -> int: 3 | ones, twos = 0, 0 4 | for num in nums: 5 | ones = ones ^ num & ~twos 6 | twos = twos ^ num & ~ones 7 | return ones 8 | 9 | 作者:jyd 10 | 链接:https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-ii-lcof/solution/mian-shi-ti-56-ii-shu-zu-zhong-shu-zi-chu-xian-d-4/ 11 | 来源:力扣(LeetCode) 12 | 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 -------------------------------------------------------------------------------- /19. 字符串/8. String to Integer (atoi).py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def myAtoi(self, str: str) -> int: 3 | if str == '': return 0 4 | 5 | res = 0 6 | start = 0 7 | while start < len(str) and str[start] == ' ': 8 | start += 1 9 | sign = 1 10 | for idx, char in enumerate(str[start:]): 11 | if idx == 0 and char == '-': 12 | sign = -1 13 | elif idx == 0 and char == '+': 14 | continue 15 | else: 16 | if char >= '0' and char <= '9': 17 | res = res*10 + int(char) 18 | else: 19 | break 20 | tmp_res = sign * res 21 | if tmp_res > pow(2, 31)-1: 22 | return pow(2, 31)-1 23 | if tmp_res < -pow(2, 31): 24 | return -pow(2, 31) 25 | return tmp_res -------------------------------------------------------------------------------- /19. 字符串/剑指 Offer 20. 表示数值的字符串.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def __init__(self): 4 | self.sign = False 5 | self.hasE = False 6 | self.has_dcm = False 7 | def isNumeric(self, s): 8 | for i in range(len(s)): 9 | char = s[i] 10 | if char == 'e' or char == 'E': 11 | if self.hasE: 12 | return False 13 | if i == len(s)-1: 14 | return False 15 | self.hasE = True 16 | elif char == '+' or char == '-': 17 | # only can be after e 18 | if not self.sign: 19 | if i == 0: 20 | continue 21 | else: 22 | if s[i-1] not in ['e', 'E']: 23 | return False 24 | sign = True 25 | elif char == '.': 26 | if self.has_dcm: 27 | return False 28 | if self.hasE: 29 | return False 30 | self.has_dcm = True 31 | elif char < '0' or char > '9': 32 | return False 33 | 34 | return True -------------------------------------------------------------------------------- /19. 字符串/剑指 Offer 58 - I. 翻转单词顺序.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def ReverseSentence(self, s): 3 | # write code here 4 | s = list(s) 5 | self.revert(s, 0, len(s)-1) 6 | start = 0 7 | end = 0 8 | while start < len(s): 9 | if s[start] == ' ': 10 | start += 1 11 | end += 1 12 | elif end == len(s) or s[end] == ' ': 13 | self.revert(s, start, end-1) 14 | start = end 15 | else: 16 | end += 1 17 | 18 | return ''.join(s) 19 | 20 | def revert(self, s, start, end): 21 | while start < end: 22 | s[start], s[end] = s[end], s[start] 23 | start += 1 24 | end -= 1 25 | -------------------------------------------------------------------------------- /19. 字符串/剑指 Offer 58 - II. 左旋转字符串.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def LeftRotateString(self, s, n): 4 | # write code here 5 | if not s: 6 | return "" 7 | n = n % len(s) 8 | if not n: 9 | return s 10 | s = list(s) 11 | self.reverse(s, 0, len(s)-1) 12 | self.reverse(s, 0, len(s)-1-n) 13 | self.reverse(s, len(s)-n, len(s)-1) 14 | return ''.join(s) 15 | 16 | def reverse(self, s, start, end): 17 | while start < end: 18 | s[start], s[end] = s[end], s[start] 19 | start += 1 20 | end -= 1 21 | -------------------------------------------------------------------------------- /2. 双指针/1. Two Sum.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def twoSum(self, nums: List[int], target: int) -> List[int]: 3 | val_idx = {} 4 | for i in range(len(nums)): 5 | if (target-nums[i]) in val_idx: 6 | return [val_idx[target-nums[i]], i] 7 | val_idx[nums[i]] = i 8 | -------------------------------------------------------------------------------- /2. 双指针/11. Container With Most Water.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def maxArea(self, height): 3 | """ 4 | :type height: List[int] 5 | :rtype: int 6 | """ 7 | max_area = 0 8 | left = 0 9 | right = len(height)-1 10 | while left< right: 11 | max_area = max(max_area, (right-left)*min(height[right], height[left])) 12 | if height[left] < height[right]: 13 | left += 1 14 | else: 15 | right -= 1 16 | return max_area -------------------------------------------------------------------------------- /2. 双指针/16. 3Sum Closest.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def threeSumClosest(self, nums: List[int], target: int) -> int: 3 | nums.sort() 4 | closest = target - sum(nums[:3]) 5 | for i in range(len(nums)): 6 | aim = target-nums[i] 7 | start = i+1 8 | end = len(nums)-1 9 | while start < end: 10 | diff = aim - nums[start] - nums[end] 11 | if diff == 0: 12 | return target 13 | closest = diff if abs(diff) < abs(closest) else closest 14 | if diff < 0: 15 | end -= 1 16 | else: 17 | start += 1 18 | return target - closest 19 | -------------------------------------------------------------------------------- /2. 双指针/18. 4Sum.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def fourSum(self, nums: List[int], target: int) -> List[List[int]]: 3 | if not nums or len(nums) < 4: 4 | return [] 5 | nums.sort() 6 | res = [] 7 | for i in range(len(nums)-3): 8 | if i > 0 and nums[i] == nums[i-1]: 9 | continue 10 | if nums[i] * 4 > target: 11 | break 12 | for j in range(i+1, len(nums)-2): 13 | s = j+1 14 | e = len(nums)-1 15 | if j > i+1 and nums[j] == nums[j-1]: 16 | continue 17 | if nums[i]+nums[j]*3 > target: 18 | break 19 | while s < e: 20 | current_sum = nums[i] + nums[j] + nums[s] + nums[e] 21 | if current_sum == target: 22 | res.append([nums[i], nums[j], nums[s], nums[e]]) 23 | while s < e and nums[s+1] == nums[s]: 24 | s += 1 25 | while s < e and nums[e-1] == nums[e]: 26 | e -= 1 27 | s += 1 28 | e -= 1 29 | elif current_sum < target: 30 | s += 1 31 | else: 32 | e -= 1 33 | return res 34 | -------------------------------------------------------------------------------- /2. 双指针/26. Remove Duplicates from Sorted Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def removeDuplicates(self, nums: List[int]) -> int: 3 | if not nums: 4 | return 0 5 | if len(nums) == 1: 6 | return 1 7 | i = 0 8 | for j in range(1, len(nums)): 9 | if nums[j] != nums[i]: 10 | i += 1 11 | nums[i] = nums[j] 12 | 13 | return i+1 14 | -------------------------------------------------------------------------------- /2. 双指针/27. Remove Element.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def removeElement(self, nums: List[int], val: int) -> int: 3 | i = 0 4 | for j in range(len(nums)): 5 | if (nums[j] != val): 6 | nums[i], nums[j] = nums[j], nums[i] 7 | i += 1 8 | return i -------------------------------------------------------------------------------- /2. 双指针/283. Move Zeroes.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def moveZeroes(self, nums: List[int]) -> None: 3 | # """ 4 | # Do not return anything, modify nums in-place instead. 5 | # """ 6 | start = 0 7 | cur = 0 8 | for cur in range(len(nums)): 9 | if nums[cur] != 0: 10 | nums[cur], nums[start] = nums[start], nums[cur] 11 | start += 1 12 | -------------------------------------------------------------------------------- /2. 双指针/42. Trapping Rain Water.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def trap(self, height: List[int]) -> int: 3 | leftmost = 0 4 | rightmost = 0 5 | right = len(height)-1 6 | left = 0 7 | res = 0 8 | while left < right: 9 | leftmost = max(leftmost, height[left]) 10 | rightmost = max(rightmost, height[right]) 11 | if leftmost < rightmost: 12 | res += leftmost - height[left] 13 | left += 1 14 | else: 15 | res += rightmost - height[right] 16 | right -= 1 17 | return res -------------------------------------------------------------------------------- /2. 双指针/75. Sort Colors.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def sortColors(self, nums) -> None: 3 | """ 4 | Do not return anything, modify nums in-place instead. 5 | """ 6 | 7 | zero_idx = 0 8 | two_idx = len(nums)-1 9 | idx= 0 10 | while idx <= two_idx: 11 | if nums[idx] == 0: 12 | nums[zero_idx], nums[idx] = nums[idx], nums[zero_idx] 13 | zero_idx += 1 14 | idx += 1 15 | elif nums[idx] == 1: 16 | idx += 1 17 | elif nums[idx] == 2: 18 | nums[two_idx], nums[idx] = nums[idx], nums[two_idx] 19 | two_idx -= 1 -------------------------------------------------------------------------------- /2. 双指针/86. Partition List.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def partition(self, head, x): 3 | before = before_head = ListNode(-1) 4 | after = after_head = ListNode(-1) 5 | 6 | while head: 7 | if head.val < x: 8 | before.next = head 9 | before = before.next 10 | else: 11 | after.next = head 12 | after = after.next 13 | head = head.next 14 | before.next = after_head.next 15 | after.next = None 16 | return before_head.next 17 | -------------------------------------------------------------------------------- /2. 双指针/977. Squares of a Sorted Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def sortedSquares(self, A: List[int]) -> List[int]: 3 | start_pos = 0 4 | while start_pos < len(A) and A[start_pos] < 0: 5 | start_pos += 1 6 | max_neg = start_pos - 1 7 | res = [] 8 | while start_pos < len(A) and max_neg >= 0: 9 | if A[start_pos]**2 < A[max_neg]**2: 10 | res.append(A[start_pos]**2) 11 | start_pos += 1 12 | else: 13 | res.append(A[max_neg]**2) 14 | max_neg -= 1 15 | 16 | while start_pos < len(A): 17 | res.append(A[start_pos]**2) 18 | start_pos += 1 19 | 20 | while max_neg >= 0: 21 | res.append(A[max_neg]**2) 22 | max_neg -= 1 23 | 24 | return res 25 | -------------------------------------------------------------------------------- /2. 双指针/Two Sum II - Input array is sorted.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def twoSum(self, numbers: List[int], target: int) -> List[int]: 3 | 4 | start = 0 5 | end = len(numbers)-1 6 | while start < end: 7 | _sum = numbers[start] + numbers[end] 8 | if _sum == target: 9 | res = [start+1, end+1] 10 | start += 1 11 | end -= 1 12 | elif _sum < target: 13 | start += 1 14 | else: 15 | end -= 1 16 | return res 17 | -------------------------------------------------------------------------------- /2. 双指针/剑指 Offer 04. 二维数组中的查找.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | # array 二维列表 4 | def Find(self, target, array): 5 | row = 0 6 | col = len(array[0])-1 7 | while row < len(array) and col >= 0: 8 | if array[row][col] == target: 9 | return True 10 | 11 | elif array[row][col] > target: 12 | col -= 1 13 | else: 14 | row += 1 15 | return False 16 | -------------------------------------------------------------------------------- /2. 双指针/剑指 Offer 21. 调整数组顺序使奇数位于偶数前面.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def reOrderArray(self, array): 3 | # write code here 4 | if not array or len(array) == 1: 5 | return array 6 | i = 0 7 | for j in range(len(array)): 8 | if array[j] % 2 != 0: 9 | k = j 10 | while k > i: 11 | array[k], array[k-1] = array[k-1], array[k] 12 | k -= 1 13 | i += 1 14 | return array -------------------------------------------------------------------------------- /20. stack/剑指 Offer 31. 栈的压入、弹出序列.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def IsPopOrder(self, pushV, popV): 4 | # write code here 5 | if not pushV and not popV: 6 | return True 7 | if len(pushV) != len(popV): 8 | return False 9 | stack = [] 10 | for val in pushV: 11 | stack.append(val) 12 | while stack and stack[-1] == popV[0]: 13 | stack.pop() 14 | popV.pop(0) 15 | if stack: 16 | return False 17 | return True -------------------------------------------------------------------------------- /21. math/172. Factorial Trailing Zeroes.py: -------------------------------------------------------------------------------- 1 | class Solution(object): 2 | def trailingZeroes(self, n): 3 | zeroCnt = 0 4 | while n > 0: 5 | n = n/5; zeroCnt += n 6 | 7 | return zeroCnt -------------------------------------------------------------------------------- /21. math/470. Implement Rand10() Using Rand7().java: -------------------------------------------------------------------------------- 1 | // https://leetcode-cn.com/problems/implement-rand10-using-rand7/solution/xiang-xi-si-lu-ji-you-hua-si-lu-fen-xi-zhu-xing-ji/ 2 | /** 3 | * The rand7() API is already defined in the parent class SolBase. 4 | * public int rand7(); 5 | * @return a random integer in the range 1 to 7 6 | */ 7 | class Solution extends SolBase { 8 | public int rand10() { 9 | while (true){ 10 | int num = (rand7() - 1) * 7 + rand7(); 11 | // 如果在40以内,那就直接返回 12 | if(num <= 40) return 1 + num % 10; 13 | // 说明刚才生成的在41-49之间,利用随机数再操作一遍 14 | num = (num - 40 - 1) * 7 + rand7(); 15 | if(num <= 60) return 1 + num % 10; 16 | // 说明刚才生成的在61-63之间,利用随机数再操作一遍 17 | num = (num - 60 - 1) * 7 + rand7(); 18 | if(num <= 20) return 1 + num % 10; 19 | 20 | } 21 | } 22 | } 23 | 24 | 作者:jerry_nju 25 | 链接:https://leetcode-cn.com/problems/implement-rand10-using-rand7/solution/xiang-xi-si-lu-ji-you-hua-si-lu-fen-xi-zhu-xing-ji/ 26 | 来源:力扣(LeetCode) 27 | 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 -------------------------------------------------------------------------------- /22. array/剑指 Offer 66. 构建乘积数组.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def multiply(self, a): 4 | # write code here 5 | b = [1]*len(a) 6 | for i in range(1, len(a)): 7 | b[i] = b[i-1]*a[i-1] 8 | 9 | tmp = 1 10 | for j in range(len(a)-2, -1, -1): 11 | tmp = tmp*a[j+1] 12 | b[j] = b[j]*tmp 13 | 14 | return b 15 | -------------------------------------------------------------------------------- /23. 二叉搜索树/二叉树的下一个结点.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # class TreeLinkNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | # self.next = None 8 | class Solution: 9 | def GetNext(self, root): 10 | # write code here 11 | if not root: 12 | return None 13 | if root.right: 14 | res = root.right 15 | while res and res.left: 16 | res = res.left 17 | return res 18 | if root.next: 19 | parent = root 20 | while parent.next and parent.next.left != parent: 21 | parent = parent.next 22 | #if parent.next and parent.next.left == parent: 23 | return parent.next 24 | 25 | return None -------------------------------------------------------------------------------- /23. 二叉搜索树/剑指 Offer 68 - I. 二叉搜索树的最近公共祖先.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': 3 | while root: 4 | if root.val < p.val and root.val < q.val: # p,q 都在 root 的右子树中 5 | root = root.right # 遍历至右子节点 6 | elif root.val > p.val and root.val > q.val: # p,q 都在 root 的左子树中 7 | root = root.left # 遍历至左子节点 8 | else: break 9 | return root 10 | 11 | 作者:jyd 12 | 链接:https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-zui-jin-gong-gong-zu-xian-lcof/solution/mian-shi-ti-68-i-er-cha-sou-suo-shu-de-zui-jin-g-7/ 13 | 来源:力扣(LeetCode) 14 | 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 -------------------------------------------------------------------------------- /23. 二叉搜索树/剑指 Offer 68 - II. 二叉树的最近公共祖先.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def lowestCommonAncestor(self, root: TreeNode, p: TreeNode, q: TreeNode) -> TreeNode: 3 | if not root or root == p or root == q: return root 4 | left = self.lowestCommonAncestor(root.left, p, q) 5 | right = self.lowestCommonAncestor(root.right, p, q) 6 | if not left: return right 7 | if not right: return left 8 | return root 9 | 10 | 作者:jyd 11 | 链接:https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/solution/mian-shi-ti-68-ii-er-cha-shu-de-zui-jin-gong-gon-7/ 12 | 来源:力扣(LeetCode) 13 | 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 -------------------------------------------------------------------------------- /3. 快慢指针-链表题目/ JZ56删除链表中重复的结点.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def deleteDuplication(self, head): 3 | 4 | # write code here 5 | if not head or not head.next: 6 | return head 7 | dummy = ListNode(head.val-1) 8 | prev = dummy 9 | dummy.next = head 10 | cur = head 11 | while cur: 12 | if cur and cur.next and cur.val == cur.next.val: 13 | while cur and cur.next and cur.val == cur.next.val: 14 | cur = cur.next 15 | cur = cur.next 16 | prev.next = cur 17 | else: 18 | prev = cur 19 | cur = cur.next 20 | return dummy.next 21 | -------------------------------------------------------------------------------- /3. 快慢指针-链表题目/141. Linked List Cycle.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def hasCycle(self, head: ListNode) -> bool: 3 | fast = slow = head 4 | 5 | while fast and fast.next: 6 | fast = fast.next.next 7 | slow = slow.next 8 | if fast == slow: 9 | return True 10 | 11 | return False -------------------------------------------------------------------------------- /3. 快慢指针-链表题目/142. Linked List Cycle II.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | class Solution: 8 | def detectCycle(self, head: ListNode) -> ListNode: 9 | if not head: 10 | return None 11 | slow = fast = head 12 | while fast and fast.next: 13 | fast = fast.next.next 14 | slow = slow.next 15 | if fast == slow: 16 | fast = head 17 | while fast != slow: 18 | slow = slow.next 19 | fast = fast.next 20 | return fast 21 | return None 22 | -------------------------------------------------------------------------------- /3. 快慢指针-链表题目/234. Palindrome Linked List.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isPalindrome(self, head: ListNode) -> bool: 3 | dummy_rev = ListNode(-1) 4 | slow = fast = head 5 | while fast and fast.next: 6 | fast = fast.next.next 7 | rev_next = dummy_rev.next 8 | dummy_rev.next = slow 9 | slow = slow.next 10 | dummy_rev.next.next = rev_next 11 | if fast: 12 | slow = slow.next 13 | 14 | rev = dummy_rev.next 15 | while slow: 16 | if slow.val != rev.val: 17 | return False 18 | slow = slow.next 19 | rev = rev.next 20 | return True 21 | -------------------------------------------------------------------------------- /3. 快慢指针-链表题目/61. Rotate List.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, val=0, next=None): 4 | # self.val = val 5 | # self.next = next 6 | class Solution: 7 | def rotateRight(self, head: ListNode, k: int) -> ListNode: 8 | if not head or not k or not head.next: 9 | return head 10 | length = 0 11 | cur = head 12 | while cur: 13 | length += 1 14 | cur = cur.next 15 | k = k % length 16 | if k == 0: 17 | return head 18 | fast = head 19 | for i in range(k): 20 | prev_fast = fast 21 | fast = fast.next 22 | slow = head 23 | while fast.next: 24 | fast = fast.next 25 | slow = slow.next 26 | 27 | dummy = ListNode(-1) 28 | dummy.next = slow.next 29 | fast.next = head 30 | slow.next = None 31 | return dummy.next 32 | -------------------------------------------------------------------------------- /3. 快慢指针-链表题目/剑指 Offer 18. 删除链表的节点.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def deleteNode(self, head: ListNode, val: int) -> ListNode: 3 | if head.val == val: return head.next 4 | pre, cur = head, head.next 5 | while cur and cur.val != val: 6 | pre, cur = cur, cur.next 7 | if cur: pre.next = cur.next 8 | return head -------------------------------------------------------------------------------- /3. 快慢指针-链表题目/剑指 Offer 22. 链表中倒数第k个节点.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # class ListNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | class Solution: 8 | def FindKthToTail(self, head, k): 9 | # write code here 10 | slow = head 11 | fast = head 12 | if not head: 13 | return head 14 | for i in range(k): 15 | if fast: 16 | fast = fast.next 17 | else: 18 | return None 19 | while fast: 20 | fast = fast.next 21 | slow = slow.next 22 | return slow 23 | -------------------------------------------------------------------------------- /3. 快慢指针-链表题目/剑指 Offer 35. 复杂链表的复制.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # 返回 RandomListNode 3 | def Clone(self, head): 4 | # write code here 5 | if not head: 6 | return head 7 | dummy = RandomListNode(-1) 8 | old2new = {} 9 | cur = head 10 | new_cur = dummy 11 | while cur: 12 | new_node = RandomListNode(cur.label) 13 | old2new[cur] = new_node 14 | new_node.random = cur.random 15 | new_cur.next = new_node 16 | new_cur = new_cur.next 17 | cur = cur.next 18 | cur = dummy.next 19 | while cur: 20 | if cur.random: 21 | cur.random = old2new[cur.random] 22 | cur = cur.next 23 | return dummy.next 24 | 25 | class Solution: 26 | def copyRandomList(self, head: 'Node') -> 'Node': 27 | if not head: return head 28 | cur = head 29 | while cur: 30 | new_node = Node(cur.val,None,None) # 克隆新结点 31 | new_node.next = cur.next 32 | cur.next = new_node # 克隆新结点在cur 后面 33 | cur = new_node.next # 移动到下一个要克隆的点 34 | cur = head 35 | 36 | while cur: # 链接random 37 | cur.next.random = cur.random.next if cur.random else None 38 | cur = cur.next.next 39 | 40 | cur_old_list = head # 将两个链表分开 41 | cur_new_list = head.next 42 | new_head = head.next 43 | while cur_old_list: 44 | cur_old_list.next = cur_old_list.next.next 45 | cur_new_list.next = cur_new_list.next.next if cur_new_list.next else None 46 | cur_old_list = cur_old_list.next 47 | cur_new_list = cur_new_list.next 48 | return new_head 49 | 50 | 作者:z1m 51 | 链接:https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/solution/lian-biao-de-shen-kao-bei-by-z1m/ 52 | 来源:力扣(LeetCode) 53 | 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 -------------------------------------------------------------------------------- /3. 快慢指针-链表题目/剑指 Offer 52. 两个链表的第一个公共节点.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def FindFirstCommonNode(self, pHead1, pHead2): 3 | # write code here 4 | if not pHead1 or not pHead2: 5 | return None 6 | node_dict = {} 7 | while pHead1: 8 | node_dict[pHead1] = 1 9 | pHead1 = pHead1.next 10 | while pHead2: 11 | if pHead2 in node_dict: 12 | return pHead2 13 | pHead2 = pHead2.next 14 | return None 15 | 16 | class Solution: 17 | def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode: 18 | node1, node2 = headA, headB 19 | 20 | while node1 != node2: 21 | node1 = node1.next if node1 else headB 22 | node2 = node2.next if node2 else headA 23 | 24 | return node1 -------------------------------------------------------------------------------- /4. 原地链表翻转/206. Reverse Linked List.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, val=0, next=None): 4 | # self.val = val 5 | # self.next = next 6 | class Solution: 7 | def reverseList(self, head: ListNode) -> ListNode: 8 | if not head: 9 | return head 10 | rev = ListNode(-1) 11 | while head: 12 | next_head = head.next 13 | to_next = rev.next 14 | rev.next = head 15 | head.next = to_next 16 | head = next_head 17 | return rev.next -------------------------------------------------------------------------------- /4. 原地链表翻转/234. Palindrome Linked List.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def isPalindrome(self, head: ListNode) -> bool: 3 | if not head: 4 | return True 5 | fast = slow = head 6 | rev_head = ListNode(-1) 7 | while fast and fast.next: 8 | fast = fast.next.next 9 | rev_next = rev_head.next 10 | rev_head.next = slow 11 | print(slow.val) 12 | slow = slow.next 13 | rev_head.next.next = rev_next 14 | if fast: 15 | slow = slow.next 16 | 17 | rev_head = rev_head.next 18 | while slow and rev_head: 19 | if slow.val != rev_head.val: 20 | return False 21 | slow = slow.next 22 | rev_head = rev_head.next 23 | return True -------------------------------------------------------------------------------- /4. 原地链表翻转/25. Reverse Nodes in k-Group.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | class Solution: 8 | def reverseKGroup(self, head: ListNode, k: int) -> ListNode: 9 | 10 | if not head: 11 | return head 12 | 13 | dummy = ListNode(-1) 14 | dummy.next = head 15 | prev = dummy 16 | while(prev): 17 | prev = self.reverse(prev, k) 18 | 19 | return dummy.next 20 | 21 | def reverse(self, prev, k): 22 | last = prev 23 | for i in range(k+1): 24 | last = last.next 25 | if not last and i != k: 26 | return None 27 | 28 | tail = prev.next 29 | cur = tail.next 30 | while tail.next != last: 31 | _next = cur.next 32 | cur.next = prev.next 33 | prev.next = cur 34 | tail.next = _next 35 | cur = _next 36 | # print(prev.next) 37 | return tail 38 | -------------------------------------------------------------------------------- /4. 原地链表翻转/92. Reverse Linked List II.py: -------------------------------------------------------------------------------- 1 | # Definition for singly-linked list. 2 | # class ListNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.next = None 6 | 7 | class Solution: 8 | def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode: 9 | dummy = ListNode(-1) 10 | dummy.next = head 11 | prev = dummy 12 | end = dummy 13 | for i in range(m-1): 14 | prev = prev.next 15 | for j in range(n+1): 16 | end = end.next 17 | tail = prev.next 18 | 19 | cur = tail.next 20 | while tail.next != end: 21 | next_cur = cur.next 22 | cur.next = prev.next 23 | prev.next = cur 24 | tail.next = next_cur 25 | cur = next_cur 26 | 27 | return dummy.next 28 | -------------------------------------------------------------------------------- /5. 区间合并/56. Merge Intervals.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def merge(self, intervals: List[List[int]]) -> List[List[int]]: 3 | starts = [] 4 | ends = [] 5 | for interval in intervals: 6 | starts.append(interval[0]) 7 | ends.append(interval[1]) 8 | starts.sort() 9 | ends.sort() 10 | res = [] 11 | for start, end in zip(starts, ends): 12 | if not res: 13 | res.append([start, end]) 14 | else: 15 | prev_itv = res[-1] 16 | if start > prev_itv[1]: 17 | res.append([start, end]) 18 | else: 19 | if end <= prev_itv[1]: 20 | continue 21 | else: 22 | prev_itv[1] = end 23 | return res 24 | -------------------------------------------------------------------------------- /5. 区间合并/57. Insert Interval.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def insert(self, intervals: List[List[int]], newInterval: List[int]) -> List[List[int]]: 3 | if not newInterval: 4 | return intervals 5 | if not intervals: 6 | return [newInterval] 7 | if intervals[0][0] > newInterval[1]: 8 | return [newInterval]+intervals 9 | if intervals[-1][1] < newInterval[0]: 10 | return intervals+[newInterval] 11 | 12 | i = 0 13 | res = [] 14 | has_insert = False 15 | while i < len(intervals): 16 | interval = intervals[i] 17 | if not has_insert: 18 | if interval[0] <= newInterval[0]: 19 | res.append(interval) 20 | i += 1 21 | else: 22 | if not res or res[-1][1] < newInterval[0]: 23 | res.append(newInterval) 24 | else: 25 | res[-1][1] = max(res[-1][1], newInterval[1]) 26 | has_insert = True 27 | else: 28 | if res[-1][1] < interval[0]: 29 | res.append(interval) 30 | else: 31 | res[-1][1] = max(res[-1][1], interval[1]) 32 | i += 1 33 | if not has_insert: 34 | res[-1][1] = max(res[-1][1], newInterval[1]) 35 | return res 36 | -------------------------------------------------------------------------------- /5. 区间合并/986. Interval List Intersections.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def intervalIntersection(self, A: List[List[int]], B: List[List[int]]) -> List[List[int]]: 3 | i = 0 4 | j = 0 5 | res = [] 6 | while i < len(A) and j < len(B): 7 | if A[i][1] < B[j][0]: 8 | i += 1 9 | continue 10 | if A[i][0] > B[j][1]: 11 | j += 1 12 | continue 13 | # overlap 14 | start = max(A[i][0], B[j][0]) 15 | end = min(A[i][1], B[j][1]) 16 | res.append([start, end]) 17 | if A[i][1] > B[j][1]: 18 | j += 1 19 | else: 20 | i += 1 21 | return res 22 | -------------------------------------------------------------------------------- /6. 无序限定范围的数组元素查找O(N)/41. First Missing Positive.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def firstMissingPositive(self, nums: List[int]) -> int: 3 | for i in range(len(nums)): 4 | if nums[i] <= 0: 5 | nums[i] = len(nums)+1 6 | 7 | for i in range(len(nums)): 8 | idx = abs(nums[i])-1 9 | if idx >=0 and idx < len(nums): 10 | nums[idx] = - abs(nums[idx]) 11 | 12 | for i in range(len(nums)): 13 | if nums[i] > 0: 14 | return i+1 15 | return len(nums)+1 -------------------------------------------------------------------------------- /6. 无序限定范围的数组元素查找O(N)/448. Find All Numbers Disappeared in an Array.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def findDisappearedNumbers(self, nums: List[int]) -> List[int]: 3 | res = [] 4 | for i in range(len(nums)): 5 | idx = abs(nums[i])-1 6 | if idx < len(nums): 7 | nums[idx] = - abs(nums[idx]) 8 | 9 | for i in range(len(nums)): 10 | if nums[i] > 0: 11 | res.append(i+1) 12 | return res 13 | -------------------------------------------------------------------------------- /6. 无序限定范围的数组元素查找O(N)/剑指 Offer 03. 数组中重复的数字.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | # 这里要特别注意~找到任意重复的一个值并赋值到duplication[0] 3 | # 函数返回True/False 4 | def duplicate(self,nums, duplication): 5 | for i in range(len(nums)): 6 | idx = abs(nums[i]) 7 | if nums[idx] < 0: 8 | duplication[0] = idx 9 | return True 10 | else: 11 | nums[idx] = - abs(nums[idx]) 12 | # print(duplication) 13 | return False -------------------------------------------------------------------------------- /7. BFS/102. Binary Tree Level Order Traversal.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def levelOrder(self, root: TreeNode) -> List[List[int]]: 10 | if not root: 11 | return [] 12 | q = [] 13 | q.append(root) 14 | res = [] 15 | while q: 16 | tmp_res = [] 17 | tmp_len = len(q) 18 | while tmp_len: 19 | node = q.pop(0) 20 | tmp_res.append(node.val) 21 | if node.left: 22 | q.append(node.left) 23 | if node.right: 24 | q.append(node.right) 25 | tmp_len -= 1 26 | res.append(tmp_res) 27 | return res -------------------------------------------------------------------------------- /7. BFS/103. Binary Tree Zigzag Level Order Traversal.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def zigzagLevelOrder(self, root: TreeNode) -> List[List[int]]: 10 | res = [] 11 | if not root: 12 | return res 13 | q = [] 14 | reverse = False 15 | q.append(root) 16 | while q: 17 | tmp = [] 18 | count = len(q) 19 | print([_q.val for _q in q]) 20 | while count: 21 | count -= 1 22 | node = q.pop(0) 23 | tmp.append(node.val) 24 | if node.left: 25 | q.append(node.left) 26 | if node.right: 27 | q.append(node.right) 28 | if reverse: 29 | tmp = tmp[::-1] 30 | reverse = not reverse 31 | res.append(tmp) 32 | return res 33 | -------------------------------------------------------------------------------- /7. BFS/127. Word Ladder.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | 3 | 4 | class Solution: 5 | 6 | def build_map(self, wordList): 7 | memory = {} 8 | for word in wordList: 9 | for i in range(len(word)): 10 | tmp = word[:i] + '*' + word[i+1:] 11 | memory[tmp] = memory.get(tmp, []) + [word] 12 | return memory 13 | 14 | def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int: 15 | wordList = set(wordList) 16 | memory = self.build_map(wordList) 17 | queue = deque() 18 | queue.append(beginWord) 19 | steps = 1 20 | used = set([beginWord]) 21 | while queue: 22 | count = len(queue) 23 | steps += 1 24 | # print(queue, steps) 25 | while count: 26 | top_word = queue.popleft() 27 | trs_words = [] 28 | for i in range(len(top_word)): 29 | tmp = top_word[:i] + '*' + top_word[i+1:] 30 | if tmp in memory: 31 | trs_words.extend(memory[tmp]) 32 | count -= 1 33 | for word in trs_words: 34 | if word not in used: 35 | used.add(word) 36 | if word == endWord: 37 | return steps 38 | queue.append(word) 39 | return 0 40 | -------------------------------------------------------------------------------- /7. BFS/207. Course Schedule.py: -------------------------------------------------------------------------------- 1 | from collections import deque 2 | class Solution: 3 | def canFinish(self, numCourses: int, prerequisites: List[List[int]]) -> bool: 4 | course_pre_count = {} 5 | for prerequisite in prerequisites: 6 | course = prerequisite[0] 7 | course_pre_count[course] = course_pre_count.get(course, 0) + 1 8 | finished = deque([course for course in range(numCourses) if course not in course_pre_count]) 9 | for course in course_pre_count: 10 | if course_pre_count[course] == 0: 11 | finished.append(course) 12 | while finished: 13 | finished_course = finished.popleft() 14 | for prerequisite in prerequisites: 15 | to_learn_course = prerequisite[0] 16 | if course_pre_count[to_learn_course] <= 0: 17 | continue 18 | elif finished_course in prerequisite: 19 | course_pre_count[to_learn_course] -= 1 20 | if course_pre_count[to_learn_course] == 0: 21 | finished.append(to_learn_course) 22 | # print(course_pre_count) 23 | for course in course_pre_count: 24 | if course_pre_count[course] != 0: 25 | return False 26 | return True -------------------------------------------------------------------------------- /7. BFS/297. Serialize and Deserialize Binary Tree.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/dongxiaohuang/leetcode_solutions/c868a61f145387dbce18244774a87395744ef5bf/7. BFS/297. Serialize and Deserialize Binary Tree.py -------------------------------------------------------------------------------- /8. 树的DFS/100. Same Tree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def isSameTree(self, p: TreeNode, q: TreeNode) -> bool: 10 | if not p and not q: return True 11 | if not p or not q: return False 12 | if p.val != q.val: return False 13 | return self.isSameTree(p.right, q.right) and self.isSameTree(p.left, q.left) -------------------------------------------------------------------------------- /8. 树的DFS/101. Symmetric Tree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def isSymmetric(self, root: TreeNode) -> bool: 10 | if not root: return True 11 | else: 12 | return self.isSymHelper(root.left, root.right) 13 | 14 | def isSymHelper(self, root1: TreeNode, root2:TreeNode) -> bool: 15 | if not root1 and not root2: return True 16 | if not root1 or not root2: return False 17 | elif root1.val != root2.val: return False 18 | else: return self.isSymHelper(root1.left, root2.right) and self.isSymHelper(root1.right, root2.left) -------------------------------------------------------------------------------- /8. 树的DFS/104. Maximum Depth of Binary Tree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def maxDepth(self, root: TreeNode) -> int: 10 | if not root: return 0 11 | return 1+max(self.maxDepth(root.right) , self.maxDepth(root.left)) -------------------------------------------------------------------------------- /8. 树的DFS/110. Balanced Binary Tree.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def isBalanced(self, root: TreeNode) -> bool: 10 | if not root: return True 11 | 12 | right_depth = self.get_depth(root.right) 13 | left_depth = self.get_depth(root.left) 14 | 15 | if abs(right_depth-left_depth) > 1: 16 | return False 17 | else: 18 | return self.isBalanced(root.right) and self.isBalanced(root.left) 19 | 20 | 21 | def get_depth(self, root): 22 | if not root: return 0 23 | return max(1+self.get_depth(root.right), 1+self.get_depth(root.left)) -------------------------------------------------------------------------------- /8. 树的DFS/111. Minimum Depth of Binary Tree.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def minDepth(self, root: TreeNode) -> int: 3 | if not root: 4 | return 0 5 | 6 | left_depth = self.minDepth(root.left) 7 | right_depth = self.minDepth(root.right) 8 | if left_depth and right_depth: 9 | return min(left_depth, right_depth)+1 10 | elif not left_depth: 11 | return right_depth+1 12 | else: 13 | return left_depth+1 14 | -------------------------------------------------------------------------------- /8. 树的DFS/112. Path Sum.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def hasPathSum(self, root: TreeNode, sum: int) -> bool: 10 | if not root: 11 | return False 12 | if not root.left and not root.right and root.val == sum: 13 | return True 14 | return self.hasPathSum(root.left, sum-root.val) or self.hasPathSum(root.right, sum-root.val) 15 | -------------------------------------------------------------------------------- /8. 树的DFS/113. Path Sum II.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | class Solution: 8 | # 返回二维列表,内部每个列表表示找到的路径 9 | def pathSum(self, root, expectNumber): 10 | # write code here 11 | if not root: 12 | return [] 13 | res = [] 14 | self.helper(root, res, expectNumber, []) 15 | return res 16 | 17 | def helper(self, root, res, target, tmp): 18 | if not root: 19 | return 20 | tmp.append(root.val) 21 | if not root.left and not root.right and root.val == target: 22 | res.append(list(tmp)) 23 | else: 24 | target = target- root.val 25 | self.helper(root.left, res, target, tmp) 26 | self.helper(root.right, res, target, tmp) 27 | tmp.pop() -------------------------------------------------------------------------------- /8. 树的DFS/437. Path Sum III.py: -------------------------------------------------------------------------------- 1 | # Definition for a binary tree node. 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | 8 | class Solution: 9 | def pathSum(self, root: TreeNode, sum: int) -> int: 10 | return self.helper(root, sum, [sum]) 11 | def helper(self, root, origin, targets): 12 | if not root: 13 | return 0 14 | 15 | hits = 0 16 | for target in targets: 17 | if target == root.val: 18 | hits += 1 19 | 20 | # update targets 21 | targets = [target-root.val for target in targets] +[origin] 22 | return hits + self.helper(root.left, origin, targets) + \ 23 | self.helper(root.right, origin, targets) -------------------------------------------------------------------------------- /8. 树的DFS/剑指 Offer 26. 树的子结构.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | class Solution: 8 | def HasSubtree(self, root1, root2): 9 | # write code here 10 | if not root1 or not root2: 11 | return False 12 | res = False 13 | if root1.val == root2.val: 14 | if self.helper(root1, root2) : 15 | return True 16 | if self.HasSubtree(root1.left, root2): 17 | return True 18 | if self.HasSubtree(root1.right, root2): 19 | return True 20 | return False 21 | 22 | def helper(self, root1, root2): 23 | if not root1 and not root2: 24 | return True 25 | if not root1 and root2: 26 | return False 27 | if root1 and not root2: 28 | return True 29 | if root1.val != root2.val: 30 | return False 31 | return self.helper(root1.left, root2.left) and self.helper(root1.right, root2.right) -------------------------------------------------------------------------------- /8. 树的DFS/剑指 Offer 33. 二叉搜索树的后序遍历序列.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | def VerifySquenceOfBST(self, sequence): 4 | # write code here 5 | if not sequence: 6 | return False 7 | if len(sequence) == 1: 8 | return True 9 | root = sequence[-1] 10 | right_start = 0 11 | while sequence[right_start] < root: 12 | right_start += 1 13 | 14 | for i in range(right_start, len(sequence)-1): 15 | if sequence[i] < root: 16 | return False 17 | left_res = True 18 | right_res = True 19 | 20 | left_sequence = sequence[:right_start] 21 | right_sequence = sequence[right_start:len(sequence)-1] 22 | if left_sequence: 23 | left_res = self.VerifySquenceOfBST(left_sequence) 24 | if right_sequence: 25 | right_res = self.VerifySquenceOfBST(right_sequence) 26 | return left_res and right_res 27 | -------------------------------------------------------------------------------- /8. 树的DFS/剑指 Offer 54. 二叉搜索树的第k大节点.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | # class TreeNode: 3 | # def __init__(self, x): 4 | # self.val = x 5 | # self.left = None 6 | # self.right = None 7 | class Solution: 8 | # 返回对应节点TreeNode 9 | def KthNode(self, pRoot, k): 10 | # write code here 11 | res = [] 12 | self.in_order(pRoot, res, k) 13 | if k <= 0 or k > len(res): 14 | return None 15 | return res[k-1] 16 | 17 | def in_order(self, root, res, k): 18 | if not root: 19 | return 20 | self.in_order(root.left, res, k) 21 | res.append(root) 22 | if len(res) == k: 23 | return 24 | self.in_order(root.right, res, k) 25 | -------------------------------------------------------------------------------- /9. DFS-递归-回溯法/131. Palindrome Partitioning.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def partition(self, s: str) -> List[List[str]]: 3 | res = [] 4 | self.helper(s, res, [], 0) 5 | return res 6 | 7 | def helper(self, s, res, tmp, start): 8 | if start == len(s): 9 | res.append(list(tmp)) 10 | else: 11 | for i in range(start+1, len(s)+1): 12 | if self.isP(s[start:i]): 13 | tmp.append(s[start:i]) 14 | self.helper(s, res, tmp, i) 15 | tmp.pop() 16 | 17 | def isP(self, s): 18 | return s == s[::-1] 19 | -------------------------------------------------------------------------------- /9. DFS-递归-回溯法/17. Letter Combinations of a Phone Number.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def letterCombinations(self, digits: str) -> List[str]: 3 | res = [] 4 | d_map = { 5 | '2': 'abc', 6 | '3': 'def', 7 | '4': 'ghi', 8 | '5': 'jkl', 9 | '6': 'mno', 10 | '7': 'pqrs', 11 | '8': 'tuv', 12 | '9': 'wxyz', 13 | 14 | } 15 | if not digits: 16 | return [] 17 | self.helper(res, digits, d_map, '', 0) 18 | return res 19 | 20 | def helper(self, res, digits, d_map, tmp, idx): 21 | if idx == len(digits): 22 | res.append(tmp) 23 | else: 24 | for char in d_map[digits[idx]]: 25 | tmp += char 26 | self.helper(res, digits, d_map, tmp, idx+1) 27 | tmp = tmp[:-1] 28 | -------------------------------------------------------------------------------- /9. DFS-递归-回溯法/39. Combination Sum.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]: 3 | res = [] 4 | self.helper(candidates, res, [], 0, target) 5 | return res 6 | 7 | def helper(self, nums, res, tmp, start, target): 8 | if sum(tmp) == target: 9 | res.append(list(tmp)) 10 | else: 11 | for i in range(start, len(nums)): 12 | if sum(tmp) < target: 13 | tmp.append(nums[i]) 14 | self.helper(nums, res, tmp, i+1, target) 15 | tmp.pop() 16 | -------------------------------------------------------------------------------- /9. DFS-递归-回溯法/40. Combination Sum II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]: 3 | res = [] 4 | candidates.sort() 5 | self.helper(candidates, res, [], 0, target) 6 | return res 7 | 8 | def helper(self, nums, res, tmp, start, target): 9 | if sum(tmp) == target: 10 | res.append(list(tmp)) 11 | else: 12 | for i in range(start, len(nums)): 13 | if sum(tmp) < target: 14 | if i > 0 and nums[i-1] == nums[i] and i > start: 15 | continue 16 | tmp.append(nums[i]) 17 | self.helper(nums, res, tmp, i+1, target) 18 | tmp.pop() 19 | -------------------------------------------------------------------------------- /9. DFS-递归-回溯法/46. Permutations.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def permute(self, nums: List[int]) -> List[List[int]]: 3 | res = [] 4 | used = [False]*len(nums) 5 | self.helper(nums, res, [], used) 6 | return res 7 | 8 | def helper(self, nums, res, tmp, used): 9 | if len(tmp) == len(nums): 10 | res.append(list(tmp)) 11 | else: 12 | for i in range(len(used)): 13 | if not used[i]: 14 | used[i] = True 15 | tmp.append(nums[i]) 16 | self.helper(nums, res, tmp, used) 17 | used[i] = False 18 | tmp.pop() 19 | -------------------------------------------------------------------------------- /9. DFS-递归-回溯法/47. Permutations II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def permuteUnique(self, nums: List[int]) -> List[List[int]]: 3 | res = [] 4 | nums.sort() 5 | used = [False]*len(nums) 6 | self.helper(nums, res, [], used) 7 | return res 8 | 9 | def helper(self, nums, res, tmp, used): 10 | if len(tmp) == len(nums): 11 | res.append(list(tmp)) 12 | else: 13 | for i in range(len(used)): 14 | if not used[i]: 15 | if i > 0 and nums[i-1] == nums[i] and not used[i-1]: 16 | continue 17 | tmp.append(nums[i]) 18 | used[i] = True 19 | self.helper(nums, res, tmp, used) 20 | used[i] = False 21 | tmp.pop() 22 | -------------------------------------------------------------------------------- /9. DFS-递归-回溯法/78. Subsets.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def subsets(self, nums: List[int]) -> List[List[int]]: 3 | res = [] 4 | self.helper(nums, [], 0, res) 5 | return res 6 | 7 | def helper(self, nums, tmp, start, res): 8 | res.append(list(tmp)) 9 | for i in range(start, len(nums)): 10 | tmp.append(nums[i]) 11 | self.helper(nums, tmp, i+1, res) 12 | tmp.pop() 13 | -------------------------------------------------------------------------------- /9. DFS-递归-回溯法/79. Word Search.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def exist(self, board: List[List[str]], word: str) -> bool: 3 | if not board or not word: 4 | return False 5 | used = [[False]*len(board[0]) for i in range(len(board))] 6 | for i in range(len(board)): 7 | for j in range(len(board[0])): 8 | if self.helper(board, word, i, j, used, 0): 9 | return True 10 | return False 11 | 12 | def helper(self, board, word, i, j, used, idx): 13 | if idx == len(word): 14 | return True 15 | if i < 0 or i >= len(board): 16 | return False 17 | if j < 0 or j >= len(board[0]): 18 | return False 19 | if word[idx] != board[i][j]: 20 | return False 21 | else: 22 | if used[i][j]: 23 | return False 24 | used[i][j] = True 25 | # move right 26 | if self.helper(board, word, i, j+1, used, idx+1): 27 | return True 28 | # move left 29 | if self.helper(board, word, i, j-1, used, idx+1): 30 | return True 31 | # move up 32 | if self.helper(board, word, i-1, j, used, idx+1): 33 | return True 34 | # move down 35 | if self.helper(board, word, i+1, j, used, idx+1): 36 | return True 37 | used[i][j] = False 38 | 39 | return False 40 | -------------------------------------------------------------------------------- /9. DFS-递归-回溯法/90. Subsets II.py: -------------------------------------------------------------------------------- 1 | class Solution: 2 | def subsetsWithDup(self, nums: List[int]) -> List[List[int]]: 3 | nums.sort() 4 | res = [] 5 | self.helper(nums, res, [], 0) 6 | return res 7 | 8 | def helper(self, nums, res, tmp, start): 9 | res.append(list(tmp)) 10 | 11 | for i in range(start, len(nums)): 12 | if i > start and i > 0 and nums[i] == nums[i-1]: 13 | continue 14 | 15 | tmp.append(nums[i]) 16 | self.helper(nums, res, tmp, i+1) 17 | tmp.pop() 18 | -------------------------------------------------------------------------------- /9. DFS-递归-回溯法/剑指 Offer 13. 机器人的运动范围.py: -------------------------------------------------------------------------------- 1 | # -*- coding:utf-8 -*- 2 | class Solution: 3 | 4 | def movingCount(self, k, m, n): 5 | # write code here 6 | used = [[False]*n for i in range(m)] 7 | res = self.helper(k, m, n, 0, 0, used) 8 | return res 9 | 10 | def helper(self, k, m, n, i, j, used): 11 | if i < 0 or i >= m: 12 | return 0 13 | if j < 0 or j >= n: 14 | return 0 15 | r1, r2, r3, r4 = 0, 0, 0, 0 16 | if self.count_pos(i, j) <= k and not used[i][j]: 17 | used[i][j] = True 18 | # move right 19 | r1 = self.helper(k, m, n, i, j+1, used) 20 | # move left 21 | r2 = self.helper(k, m, n, i, j-1, used) 22 | # move up 23 | r3 = self.helper(k, m, n, i-1, j, used) 24 | # move down 25 | r4 = self.helper(k, m, n, i+1, j, used) 26 | return sum([r1, r2, r3, r4])+1 27 | return 0 28 | 29 | def count_pos(self, m, n): 30 | res = 0 31 | while m: 32 | res += m % 10 33 | m = m // 10 34 | while n: 35 | res += n % 10 36 | n = n // 10 37 | return res 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | - [1. 滑动窗口](#1-滑动窗口) 2 | - [2. 双指针](#2-双指针) 3 | - [3. 快慢指针/ 链表题目](#3-快慢指针-链表题目) 4 | - [4. 原地链表翻转](#4-原地链表翻转) 5 | - [5. 区间合并](#5-区间合并) 6 | - [6. 无序限定范围的数组元素查找O(N)](#6-无序限定范围的数组元素查找on) 7 | - [7. BFS](#7-bfs) 8 | - [8. 树的DFS](#8-树的dfs) 9 | - [9. DFS/递归/回溯法](#9-dfs递归回溯法) 10 | - [10. 双堆模式](#10-双堆模式) 11 | - [11. 2分变种](#11-2分变种) 12 | - [12. 前K大的数模式HEAP](#12-前k大的数模式heap) 13 | - [13. K路归并](#13-k路归并) 14 | - [14. DP 动态规划](#14-dp-动态规划) 15 | - [15. 排序算法](#15-排序算法) 16 | - [16. 树和链表结合](#16-树和链表结合) 17 | - [17. 树的重新构建](#17-树的重新构建) 18 | - [18. 位运算](#18-位运算) 19 | - [19. 字符串](#19-字符串) 20 | - [20. stack](#20-stack) 21 | - [21. math](#21-math) 22 | - [22. array](#22-array) 23 | - [23. 二叉搜索树](#23-二叉搜索树) 24 | - [ref](#ref) 25 | # 1. 滑动窗口 26 | 27 | [53. 大小为 K 的子数组的最大和](https://leetcode.com/problems/maximum-subarray/) 28 | 29 | [121. Best Time to Buy and Sell Stock](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/) 30 | 31 | [3. Longest Substring Without Repeating Characters](https://leetcode.com/problems/longest-substring-without-repeating-characters/) 32 | 33 | [239. Sliding Window Maximum](https://leetcode.com/problems/sliding-window-maximum/) 34 | 35 | [剑指 Offer 57 - II. 和为s的连续正数序列](https://leetcode-cn.com/problems/he-wei-sde-lian-xu-zheng-shu-xu-lie-lcof/solution/shi-yao-shi-hua-dong-chuang-kou-yi-ji-ru-he-yong-h/) 36 | 37 | # 2. 双指针 38 | 39 | 双指针通常用在**排好序**的数组或是链表中寻找对子, 或者是merge 或者是排序,或者去除element,反正一般都是头尾各一个指针,然后根据条件移动。【参考[Jaylen's Blog](https://linzhenglearn.github.io/2017/03/29/TwoPointer/#常见题型)】 40 | [1. Two Sum](https://leetcode.com/problems/two-sum/)(# 也可以用map的方式做) 41 | 42 | [167. Two Sum II - Input array is sorted](https://leetcode.com/submissions/detail/299213003/) 43 | 44 | [977. Squares of a Sorted Array (很像merge sort里的merge)](https://leetcode.com/problems/squares-of-a-sorted-array/) 45 | 46 | [283. Move Zeroes](https://leetcode.com/problems/move-zeroes/) 47 | 48 | [27. Remove Element](https://leetcode.com/problems/remove-element/) 49 | 50 | [26. Remove Duplicates from Sorted Array](https://leetcode.com/problems/remove-duplicates-from-sorted-array/) 51 | 52 | [16. 3Sum Closest](https://leetcode.com/problems/3sum-closest/) 53 | 54 | [18. 4Sum](https://leetcode.com/problems/4sum/) 55 | 56 | [86. Partition List](https://leetcode.com/problems/partition-list/) 57 | 58 | [11. Container With Most Water](https://leetcode.com/problems/container-with-most-water/) 59 | 60 | [42. Trapping Rain Water](https://leetcode.com/problems/trapping-rain-water/) 61 | 62 | [75. Sort Colors](https://leetcode.com/problems/sort-colors/) 63 | 64 | [剑指 Offer 04. 二维数组中的查找](https://leetcode-cn.com/problems/er-wei-shu-zu-zhong-de-cha-zhao-lcof/) 65 | 66 | [剑指 Offer 21. 调整数组顺序使奇数位于偶数前面](https://leetcode-cn.com/problems/diao-zheng-shu-zu-shun-xu-shi-qi-shu-wei-yu-ou-shu-qian-mian-lcof/) 67 | # 3. 快慢指针/ 链表题目 68 | 快慢指针是处理linked list常用的套路,通常是用来判断成环以及环的入口,或者是寻找 list中第k个元素。 69 | 70 | [141. Linked List Cycle](https://leetcode.com/problems/linked-list-cycle/) 71 | 72 | [142. Linked List Cycle II](https://leetcode.com/problems/linked-list-cycle-ii/) 73 | 74 | [234. Palindrome Linked List](https://leetcode.com/problems/palindrome-linked-list/) 75 | 76 | [61. Rotate List](https://leetcode.com/problems/rotate-list/) 77 | 78 | [剑指 Offer 18. 删除链表的节点](https://leetcode-cn.com/problems/shan-chu-lian-biao-de-jie-dian-lcof/) 79 | 80 | [JZ56 删除链表中重复的结点](https://www.nowcoder.com/practice/fc533c45b73a41b0b44ccba763f866ef?tpId=13&&tqId=11209&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking) 81 | 82 | [剑指 Offer 22. 链表中倒数第k个节点](https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/) 83 | 84 | [剑指 Offer 35. 复杂链表的复制](https://leetcode-cn.com/problems/fu-za-lian-biao-de-fu-zhi-lcof/) 85 | 86 | [剑指 Offer 52. 两个链表的第一个公共节点](https://leetcode-cn.com/problems/liang-ge-lian-biao-de-di-yi-ge-gong-gong-jie-dian-lcof/) 87 | 88 | # 4. 原地链表翻转 89 | 90 | [234. Palindrome Linked List](https://leetcode.com/problems/palindrome-linked-list/) 91 | 92 | [206. Reverse Linked List](https://leetcode.com/problems/reverse-linked-list/) 93 | 94 | [25. Reverse Nodes in k-Group](https://leetcode.com/problems/reverse-nodes-in-k-group/) 95 | 96 | [92. Reverse Linked List II](https://leetcode.com/problems/reverse-linked-list-ii/) 97 | 98 | # 5. 区间合并 99 | 区间合并的问题,通常是重新把区间按照start和end排序,重新组合区间。 100 | 101 | [56. Merge Intervals](https://leetcode.com/problems/merge-intervals/) 102 | 103 | [986. Interval List Intersections](https://leetcode.com/problems/interval-list-intersections/) 104 | 105 | [57. Insert Interval](https://leetcode.com/problems/insert-interval/) 106 | 107 | # 6. 无序限定范围的数组元素查找O(N) 108 | 109 | 要求 inplace, 通常是采用正负反转的做法 110 | 111 | [41. First Missing Positive](https://leetcode.com/problems/first-missing-positive/) 112 | 113 | [448. Find All Numbers Disappeared in an Array](https://leetcode.com/problems/find-all-numbers-disappeared-in-an-array/) 114 | 115 | [剑指 Offer 03. 数组中重复的数字](https://leetcode-cn.com/problems/shu-zu-zhong-zhong-fu-de-shu-zi-lcof/) 116 | 117 | # 7. BFS 118 | 119 | BFS 通常采用queue 来实现 120 | 121 | [102. Binary Tree Level Order Traversal](https://leetcode.com/problems/binary-tree-level-order-traversal/) 122 | 123 | [103. Binary Tree Zigzag Level Order Traversal](https://leetcode.com/problems/binary-tree-zigzag-level-order-traversal/) 124 | 125 | [297. Serialize and Deserialize Binary Tree](https://leetcode.com/problems/serialize-and-deserialize-binary-tree/) 126 | 127 | [127. Word Ladder I ](https://leetcode.com/problems/word-ladder/) 128 | 129 | [207. Course Schedule](https://leetcode.com/problems/course-schedule/)【拓扑排序】 130 | 131 | 132 | # 8. 树的DFS 133 | 通常采用递归 134 | [111. Minimum Depth of Binary Tree](https://leetcode.com/problems/minimum-depth-of-binary-tree/) 135 | 136 | [112. Path Sum](https://leetcode.com/problems/path-sum/) 137 | 138 | [113. Path Sum II](https://leetcode.com/problems/path-sum-ii/)(和[剑指 Offer 34. 二叉树中和为某一值的路径](https://leetcode-cn.com/problems/er-cha-shu-zhong-he-wei-mou-yi-zhi-de-lu-jing-lcof/)一样) 139 | 140 | [437. Path Sum III](https://leetcode.com/problems/path-sum-iii/submissions/) 141 | 142 | [100. Same Tree](https://leetcode.com/problems/same-tree/) 143 | 144 | [101. Symmetric Tree](https://leetcode.com/problems/symmetric-tree/) 145 | 146 | [104. Maximum Depth of Binary Tree](https://leetcode.com/problems/maximum-depth-of-binary-tree/) 147 | 148 | [110. Balanced Binary Tree](https://leetcode.com/problems/balanced-binary-tree/) 149 | 150 | [剑指 Offer 26. 树的子结构](https://leetcode-cn.com/problems/shu-de-zi-jie-gou-lcof/) 151 | 152 | [剑指 Offer 33. 二叉搜索树的后序遍历序列](https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-hou-xu-bian-li-xu-lie-lcof/) 153 | 154 | 155 | [剑指 Offer 54. 二叉搜索树的第k大节点](https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-di-kda-jie-dian-lcof/)(inorder) 156 | 157 | # 9. DFS/递归/回溯法 158 | 159 | 对于排列和组合的题目,需要主要判断是否会有重复数字,如有重复,需要先进行sort,而且需要进行剪枝。 160 | 161 | [78. Subsets](https://leetcode.com/problems/subsets/) 162 | 163 | [90. Subsets II](https://leetcode.com/problems/subsets-ii/) 164 | 165 | [46. Permutations](https://leetcode.com/problems/permutations/) 166 | 167 | [47. Permutations II](https://leetcode.com/problems/permutations-ii/) 168 | 169 | [39. Combination Sum](https://leetcode.com/problems/combination-sum/) 170 | 171 | (区别 [322. Coin Change](https://leetcode.com/problems/coin-change) 172 | 173 | [518. Coin Change 2](https://leetcode.com/problems/coin-change)) 174 | 175 | [40. Combination Sum II](https://leetcode.com/problems/combination-sum-ii/) 176 | 177 | [131. Palindrome Partitioning](https://leetcode.com/problems/palindrome-partitioning/) ! 178 | 179 | [17. Letter Combinations of a Phone Number](https://leetcode.com/problems/letter-combinations-of-a-phone-number/) (differ from [91. Decode Ways](https://leetcode.com/problems/decode-ways/)) 180 | 181 | [79. Word Search](https://leetcode.com/problems/word-search/)(same as 剑指 Offer 12. 矩阵中的路径) 182 | 183 | [剑指 Offer 13. 机器人的运动范围](https://leetcode-cn.com/problems/ji-qi-ren-de-yun-dong-fan-wei-lcof/) 184 | 185 | # 10. 双堆模式 186 | 187 | 通常是查找中位数,构建一个最小堆和最大堆。 188 | 以及查找数据流中最小的或者最大的数。 189 | 190 | [295 Find-Median-from-Data-Stream](https://leetcode.com/problems/find-median-from-data-stream/) 191 | 192 | [480. Sliding Window Median](https://leetcode.com/problems/sliding-window-median/) 193 | 194 | [155. Min Stack](https://leetcode.com/problems/min-stack/) 195 | 196 | [剑指 Offer 09. 用两个栈实现队列](https://leetcode-cn.com/problems/yong-liang-ge-zhan-shi-xian-dui-lie-lcof/) 197 | 198 | # 11. 2分变种 199 | 200 | > 当你需要解决的问题的输入是排好序的数组,链表,或是排好序的矩阵,要求咱们寻找某些特定元素。这个时候的不二选择就是二分搜索。这种模式是一种超级牛的用二分来解决问题的方式。 201 | 对于一组满足上升排列的数集来说,这种模式的步骤是这样的: 202 | 首先,算出左右端点的中点。最简单的方式是这样的:middle = (start + end) / 2。但这种计算方式有不小的概率会出现整数越界。因此一般都推荐另外这种写法:middle = start + (end — start) // 2 203 | 如果要找的目标改好和中点所在的数值相等,我们返回中点的下标就行 204 | 如果目标不等的话:我们就有两种移动方式了 205 | 如果目标比中点在的值小(key < arr[middle]):将下一步搜索空间放到左边(end = middle - 1) 206 | 如果比中点的值大,则继续在右边搜索,丢弃左边:left = middle + 1 207 | 图示该过程的话,如下图所示: 208 | 我习惯的循环结束条件是 $start + 1 < end$, 然后在分别判断start 和 end 的结果 209 | [参考Jaylen's Blog](https://linzhenglearn.github.io/2017/03/20/BinarySearch/) 210 | [参考模版](https://leetcode-cn.com/problems/search-insert-position/solution/te-bie-hao-yong-de-er-fen-cha-fa-fa-mo-ban-python-/) 211 | 212 | [35. Search Insert Position](https://leetcode.com/problems/search-insert-position/) 213 | 214 | [34. Find First and Last Position of Element in Sorted Array](https://leetcode.com/problems/find-first-and-last-position-of-element-in-sorted-array/) 215 | 216 | [33. Search in Rotated Sorted Array](https://leetcode.com/problems/search-in-rotated-sorted-array/submissions/) 217 | 218 | [153. Find Minimum in Rotated Sorted Array](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array/) 219 | 220 | [154. Find Minimum in Rotated Sorted Array II](https://leetcode.com/problems/find-minimum-in-rotated-sorted-array-ii/submissions/)(same as [剑指 Offer 11. 旋转数组的最小数字]) 221 | 222 | [162. Find Peak Element](https://leetcode.com/problems/find-peak-element/?utm_source=LCUS&utm_medium=ip_redirect_q_uns&utm_campaign=transfer2china) 223 | 224 | [540. Single Element in a Sorted Array](https://leetcode.com/problems/single-element-in-a-sorted-array/) 225 | 226 | [剑指 Offer 16. 数值的整数次方](https://leetcode-cn.com/problems/shu-zhi-de-zheng-shu-ci-fang-lcof/)(2分法) 227 | 228 | # 12. 前K大的数模式HEAP 229 | 230 | 采用priority queue 或者 说在python 中的heapq 231 | 求top k 采用最小堆(默认) 232 | 采用最大堆的时候可以采用push 负的value 233 | 234 | [215. Kth Largest Element in an Array](https://leetcode.com/problems/kth-largest-element-in-an-array/) 235 | 236 | [347. Top K Frequent Elements](https://leetcode.com/problems/top-k-frequent-elements/) 237 | 238 | [373. Find K Pairs with Smallest Sums](https://leetcode.com/problems/find-k-pairs-with-smallest-sums/) 239 | 240 | # 13. K路归并 241 | 242 | K路归并能帮咱们解决那些涉及到多组排好序的数组的问题。 243 | 244 | 每当你的输入是K个排好序的数组,你就可以用堆来高效顺序遍历其中所有数组的所有元素。你可以将每个数组中最小的一个元素加入到最小堆中,从而得到全局最小值。当我们拿到这个全局最小值之后,再从该元素所在的数组里取出其后面紧挨着的元素,加入堆。如此往复直到处理完所有的元素。 245 | 246 | 特殊情况:2路并归 (mergesort 中的merge, 双指针就可以完成) 247 | 248 | [23. Merge k Sorted Lists](https://leetcode.com/problems/merge-k-sorted-lists/) 249 | 250 | [21. Merge Two Sorted Lists](https://leetcode.com/problems/merge-two-sorted-lists/) 251 | 252 | 253 | # 14. DP 动态规划 254 | 参考:https://zhuanlan.zhihu.com/p/91582909 255 | 参考:https://zhuanlan.zhihu.com/p/126546914 256 | 257 | [300. Longest Increasing Subsequence](https://leetcode.com/problems/longest-increasing-subsequence/) 258 | 259 | [1143. Longest Common Subsequence](https://leetcode.com/problems/longest-common-subsequence/) 260 | 261 | [72. Edit Distance](https://leetcode.com/problems/edit-distance/) 262 | 263 | [44. Wildcard Matching](https://leetcode.com/problems/wildcard-matching/) 264 | 265 | [10. Regular Expression Matching](https://leetcode.com/problems/regular-expression-matching/) 266 | 267 | [120. Triangle](https://leetcode.com/problems/triangle/) 268 | 269 | [53. Maximum Subarray](https://leetcode.com/problems/maximum-subarray/) 270 | 271 | [152. Maximum Product Subarray](https://leetcode.com/problems/maximum-product-subarray/) 272 | 273 | [887. Super Egg Drop](https://leetcode.com/problems/super-egg-drop/)[ref](https://leetcode-cn.com/problems/super-egg-drop/solution/dong-tai-gui-hua-zhi-jie-shi-guan-fang-ti-jie-fang/) 274 | 275 | [198. House Robber](https://leetcode.com/problems/house-robber/) 276 | 277 | [213. House Robber II](https://leetcode.com/problems/house-robber-ii/) (两个dp) 278 | 279 | [121. Best Time to Buy and Sell Stock](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/) 280 | 281 | [122. Best Time to Buy and Sell Stock II](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-ii/) 282 | 283 | 284 | [188. Best Time to Buy and Sell Stock IV](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iv/) 285 | 286 | [123. Best Time to Buy and Sell Stock III](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/) [ref](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-iii/discuss/39743/Python-DP-solution-120ms) 287 | 288 | [714. Best Time to Buy and Sell Stock with Transaction Fee](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-transaction-fee/) 289 | 290 | [309. Best Time to Buy and Sell Stock with Cooldown](https://leetcode.com/problems/best-time-to-buy-and-sell-stock-with-cooldown/discuss/76040/Share-my-python-solution-with-explanation) 291 | 292 | [516. Longest Palindromic Subsequence](https://leetcode.com/problems/longest-palindromic-subsequence/) ! 293 | 294 | [5. Longest Palindromic Substring](https://leetcode.com/problems/longest-palindromic-substring/) 295 | 296 | [416. Partition Equal Subset Sum](https://leetcode.com/problems/partition-equal-subset-sum/submissions/) 297 | 298 | 299 | [322. Coin Change](https://leetcode.com/problems/coin-change) 300 | 301 | [518. Coin Change 2](https://leetcode.com/problems/coin-change-2/) 302 | 303 | [91. Decode Ways](https://leetcode.com/problems/decode-ways/) 304 | 305 | [139. Word Break](https://leetcode.com/problems/word-break/) 306 | 307 | [剑指 Offer 10- I. 斐波那契数列](https://leetcode-cn.com/problems/fei-bo-na-qi-shu-lie-lcof/) 308 | 309 | [剑指 Offer 10- II. 青蛙跳台阶问题](https://leetcode-cn.com/problems/qing-wa-tiao-tai-jie-wen-ti-lcof/) 310 | 311 | [矩形覆盖](https://www.nowcoder.com/practice/72a5a919508a4251859fb2cfb987a0e6?tpId=13&&tqId=11163&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking) 312 | 313 | [变态跳台阶](https://www.nowcoder.com/practice/22243d016f6b47f2a6928b4313c85387?tpId=13&&tqId=11162&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking) 314 | 315 | [剑指 Offer 14- I. 剪绳子](https://leetcode-cn.com/problems/jian-sheng-zi-lcof/) 316 | 317 | [剑指 Offer 46. 把数字翻译成字符串](https://leetcode-cn.com/problems/ba-shu-zi-fan-yi-cheng-zi-fu-chuan-lcof/) 318 | 319 | [剑指 Offer 47. 礼物的最大价值](https://leetcode-cn.com/problems/li-wu-de-zui-da-jie-zhi-lcof/) 320 | 321 | [剑指 Offer 49. 丑数](https://leetcode-cn.com/problems/chou-shu-lcof/) 322 | 323 | [剑指 Offer 60. n个骰子的点数](https://leetcode-cn.com/problems/nge-tou-zi-de-dian-shu-lcof/) 324 | 325 | # 15. 排序算法 326 | [Selection Sort](#ss) 327 | [Heapsort](#hs) 328 | [Mergesort](#ms) 329 | [Insertion Sort](#is) 330 | [Shell's Sort](#shell) 331 | [Quicksort](#qs) 332 | [Bubblesort](#bs) 333 | [Linear Sorting](#ls) 334 | 335 | # 16. 树和链表结合 336 | 337 | [剑指 Offer 36. 二叉搜索树与双向链表](https://leetcode-cn.com/problems/er-cha-sou-suo-shu-yu-shuang-xiang-lian-biao-lcof/) 338 | 339 | 340 | [109. Convert Sorted List to Binary Search Tree](https://leetcode.com/problems/convert-sorted-list-to-binary-search-tree/) 341 | 342 | [114. Flatten Binary Tree to Linked List](https://leetcode.com/problems/flatten-binary-tree-to-linked-list/) 343 | 344 | # 17. 树的重新构建 345 | [105. Construct Binary Tree from Preorder and Inorder Traversal](https://leetcode.com/problems/construct-binary-tree-from-preorder-and-inorder-traversal) 346 | 347 | [106. Construct Binary Tree from Inorder and Postorder Traversal](https://leetcode.com/problems/construct-binary-tree-from-inorder-and-postorder-traversal/) 348 | 349 | [606. Construct String from Binary Tree](https://leetcode.com/problems/construct-string-from-binary-tree/) 350 | 351 | [1008. Construct Binary Search Tree from Preorder Traversal](https://leetcode.com/problems/construct-binary-search-tree-from-preorder-traversal/) 352 | 353 | [889. Construct Binary Tree from Preorder and Postorder Traversal](https://leetcode.com/problems/construct-binary-tree-from-preorder-and-postorder-traversal) 354 | 355 | 356 | # 18. 位运算 357 | [136. Single Number](https://leetcode.com/problems/single-number/) 358 | 359 | [540. Single Element in a Sorted Array](https://leetcode.com/problems/single-element-in-a-sorted-array/) 360 | 361 | [190. Reverse Bits](https://leetcode.com/problems/reverse-bits/) 362 | 363 | [剑指 Offer 15. 二进制中1的个数](https://leetcode-cn.com/problems/er-jin-zhi-zhong-1de-ge-shu-lcof/) 364 | 365 | [剑指 Offer 56 - I. 数组中数字出现的次数](https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/) 366 | 367 | [剑指 Offer 56 - II. 数组中数字出现的次数 II](https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-ii-lcof/) 368 | 369 | # 19. 字符串 370 | 一般都有很多corner cases 需要考虑 371 | [8. String to Integer (atoi)](https://leetcode.com/problems/string-to-integer-atoi/) 372 | 373 | [剑指 Offer 20. 表示数值的字符串](https://leetcode-cn.com/problems/biao-shi-shu-zhi-de-zi-fu-chuan-lcof/) 374 | 375 | [剑指 Offer 58 - I. 翻转单词顺序](https://leetcode-cn.com/problems/fan-zhuan-dan-ci-shun-xu-lcof/)(2次翻转) 376 | 377 | [剑指 Offer 58 - II. 左旋转字符串](https://leetcode-cn.com/problems/zuo-xuan-zhuan-zi-fu-chuan-lcof/) 378 | # 20. stack 379 | [剑指 Offer 31. 栈的压入、弹出序列](https://leetcode-cn.com/problems/zhan-de-ya-ru-dan-chu-xu-lie-lcof/) 380 | 381 | # 21. math 382 | [172. Factorial Trailing Zeroes](https://leetcode.com/problems/factorial-trailing-zeroes/) 383 | 384 | [470. Implement Rand10() Using Rand7()](https://leetcode.com/problems/implement-rand10-using-rand7/) 385 | 386 | # 22. array 387 | [剑指 Offer 66. 构建乘积数组](https://leetcode-cn.com/problems/gou-jian-cheng-ji-shu-zu-lcof/) 388 | 389 | # 23. 二叉搜索树 390 | [剑指 Offer 68 - I. 二叉搜索树的最近公共祖先](https://leetcode-cn.com/problems/er-cha-sou-suo-shu-de-zui-jin-gong-gong-zu-xian-lcof/) 391 | 392 | [剑指 Offer 68 - II. 二叉树的最近公共祖先](https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/) 393 | 394 | [二叉树的下一个结点](https://www.nowcoder.com/practice/9023a0c988684a53960365b889ceaf5e?tpId=13&&tqId=11210&rp=1&ru=/ta/coding-interviews&qru=/ta/coding-interviews/question-ranking) 395 | 396 | # ref 397 | [basketwangCoding Youtube link ](https://www.youtube.com/channel/UCE35PnPX7EZi8nHSegjMn6Q) 398 | 399 | [剑指offer](https://leetcode-cn.com/problemset/lcof/) --------------------------------------------------------------------------------