lengthOfLongestSubstring (cache) O(n)
Given a string s, find the length of the longest substring without duplicate characters.
Example 1:
1 | Input: s = "abcabcbb" |
Example 2:
1 | Input: s = "bbbbb" |
Example 3:
1 | Input: s = "pwwkew" |
Constraints:
0 <= s.length <= 5 * 10^4sconsists of English letters, digits, symbols and spaces.
设两个指针 i 和 j:i 指向滑动窗口起点,j 指向终点。
先把 j 向右移动,遇到重复字符就停下,计算当前长度。
然后把 i 向右移动以越过那个重复字符。
用一个字典记录每个字符出现的位置。
1 | # O(kn) |
findMedianSortedArrays (binary search) O(log(m+n))
Given two sorted arrays nums1 and nums2 of size m and n respectively, return the median of the two sorted arrays.
The overall run time complexity should be O(log (m+n)).
Example 1:
1 | Input: nums1 = [1,3], nums2 = [2] |
Example 2:
1 | Input: nums1 = [1,2], nums2 = [3,4] |
Constraints:
nums1.length == mnums2.length == n0 <= m <= 10000 <= n <= 10001 <= m + n <= 2000-10^6 <= nums1[i], nums2[i] <= 10^6left_part | right_partA[0], A[1], …, A[i-1] | A[i], A[i+1], …, A[m-1]
B[0], B[1], …, B[j-1] | B[j], B[j+1], …, B[n-1]
我们用 i 和 j 把数组 A、B 各切两半。当下面三个条件同时满足时即可拿到中位数:
- len(left_part)=len(right_part)
- max(left_part)≤min(right_part)
- median = (max(left_part) + min(right_part)) / 2
可以化简为:
- B[j−1]≤A[i] 且 A[i−1]≤B[j]
- j=(m+n+1)/2-i
对 i 做二分搜索:
- 若 B[j−1]≤A[i] 且 A[i−1]≤B[j],找到中位数
- 若 B[j−1]>A[i],需要把 i 向右移(二分)
- 若 A[i−1]>B[j],需要把 i 向左移(二分)
注意:
- imin, imax, half_len = 0, m, (m+n+1)//2
- i = (imin+imax)//2, j = half_len – i
- if i < m and nums2[j-1] > nums1[i]: imin = i + 1 # binary search
- elif i > 0 and nums1[i-1] > nums2[j]: imax = i - 1 # binary search
1 | def solution(nums1, nums2): |
longestPalindrome (dp) O(N^2)
Given a string s, return the longest palindromic substring in s.
Example 1:
1 | Input: s = "babad" |
Example 2:
1 | Input: s = "cbbd" |
Constraints:
1 <= s.length <= 1000sconsist of only digits and English letters.
设两个下标,i 表示窗口长度,j 表示窗口起点,状态转移方程:
P(i, j) = P(i+1, j-1) + 2, if s[i] == s[j].
注意:
- P(i, i) = 1
- ‘aa’ 也是回文,所以 P(i, i+1) = 2 if s[i] = s[i+1]
1 | # O(n^2) |
isMatch (recursive with memo) O(MN)
Given an input string s and a pattern p, implement regular expression matching with support for '.' and '*' where:
'.'Matches any single character.'*'Matches zero or more of the preceding element.
Return a boolean indicating whether the matching covers the entire input string (not partial).
Example 1:
1 | Input: s = "aa", p = "a" |
Example 2:
1 | Input: s = "aa", p = "a*" |
Example 3:
1 | Input: s = "ab", p = ".*" |
Constraints:
1 <= s.length <= 201 <= p.length <= 20scontains only lowercase English letters.pcontains only lowercase English letters,'.', and'*'.It is guaranteed for each appearance of the character
'*', there will be a previous valid character to match.
加备忘录避免重复检查。
1 | def solution(s, p): |
maxArea (trick) O(n)
You are given an integer array height of length n. There are n vertical lines drawn such that the two endpoints of the i^th line are (i, 0) and (i, height[i]).
Find two lines that together with the x-axis form a container, such that the container contains the most water.
Return the maximum amount of water a container can store.
Notice that you may not slant the container.
Example 1:

1 | Input: height = [1,8,6,2,5,4,8,3,7] |
Example 2:
1 | Input: height = [1,1] |
Constraints:
n == height.length2 <= n <= 10^50 <= height[i] <= 10^4
令 i = 0,j = len(heights)-1。每次把较矮的那一根向中间移动,重新计算最大面积。因为如果下一根比当前还矮,宽度变小、高度也没增加,体积不可能更大。
注意:这题不能用 dp,因为没有最优子结构。
这个 trick 之所以成立:我们从两端往里收,宽度一直在减小,只有高度变大才有机会出现更大面积。而之所以移动较矮的那根:如果固定较矮的、移动较高的,min 高度仍然是较矮那根,面积只会随宽度减小而下降。
1 | # O(n) |
(mark) threeSum (trick) O(n^2)
Given an integer array nums, return all the triplets [nums[i], nums[j], nums[k]] such that i != j, i != k, and j != k, and nums[i] + nums[j] + nums[k] == 0.
Notice that the solution set must not contain duplicate triplets.
Example 1:
1 | Input: nums = [-1,0,1,2,-1,-4] |
Example 2:
1 | Input: nums = [0,1,1] |
Example 3:
1 | Input: nums = [0,0,0] |
Constraints:
3 <= nums.length <= 3000-10^5 <= nums[i] <= 10^5
先排序,然后三指针 i, j, k。固定 i 后,j = i+1,k = n-1,目标是让 nums[j] + nums[k] = -nums[i]:和偏小就 j++,和偏大就 k--(因为已排序)。
1 | # O(n^2) sort |
letterCombinations (full permutation), O(3^N * 4^M)
Given a string containing digits from 2-9 inclusive, return all possible letter combinations that the number could represent. Return the answer in any order.
A mapping of digits to letters (just like on the telephone buttons) is given below. Note that 1 does not map to any letters.

Example 1:
1 | Input: digits = "23" |
Example 2:
1 | Input: digits = "2" |
Constraints:
1 <= digits.length <= 4digits[i]is a digit in the range['2', '9'].
直接递归:每层枚举当前数字对应的所有字符,调用下一层递归。
1 | phone = {'2': ['a', 'b', 'c'], |
removeNthFromEnd (trick) O(n)
Given the head of a linked list, remove the n^th node from the end of the list and return its head.
Example 1:

1 | Input: head = [1,2,3,4,5], n = 2 |
Example 2:
1 | Input: head = [1], n = 1 |
Example 3:
1 | Input: head = [1,2], n = 1 |
Constraints:
The number of nodes in the list is
sz.1 <= sz <= 300 <= Node.val <= 1001 <= n <= sz
Follow up: Could you do this in one pass?
双指针 p, q:先让 p 向前走 n 步,再让两个指针一起走,当 p 走到末尾时,q 正好停在倒数第 n 个节点。
1 | def solution(head, n): |
generateParenthesis (recursive) O(4^n/√2)
Given n pairs of parentheses, write a function to generate all combinations of well-formed parentheses.
Example 1:
1 | Input: n = 3 |
Example 2:
1 | Input: n = 1 |
Constraints:
1 <= n <= 8
用计数器 n 记录还可用的左括号数量,k 记录已经放下、待匹配的左括号数量。
- n == 0 且 k == 0:输出
- n == 0 且 k > 0:recursive(n, k-1),加 ‘)’
- n > 0 且 k == 0:recursive(n-1, k+1),加 ‘(‘
- 否则两个分支都试:recursive(n-1, k+1) 加 ‘(‘ 和 recursive(n, k-1) 加 ‘)’
1 | def solution(n): |
nextPermutation (trick), O(n)
A permutation of an array of integers is an arrangement of its members into a sequence or linear order.
- For example, for
arr = [1,2,3], the following are all the permutations ofarr:[1,2,3], [1,3,2], [2, 1, 3], [2, 3, 1], [3,1,2], [3,2,1].
The next permutation of an array of integers is the next lexicographically greater permutation of its integer. More formally, if all the permutations of the array are sorted in one container according to their lexicographical order, then the next permutation of that array is the permutation that follows it in the sorted container. If such arrangement is not possible, the array must be rearranged as the lowest possible order (i.e., sorted in ascending order).
For example, the next permutation of
arr = [1,2,3]is[1,3,2].Similarly, the next permutation of
arr = [2,3,1]is[3,1,2].While the next permutation of
arr = [3,2,1]is[1,2,3]because[3,2,1]does not have a lexicographical larger rearrangement.
Given an array of integers nums, find the next permutation of nums.
The replacement must be in place and use only constant extra memory.
Example 1:
1 | Input: nums = [1,2,3] |
Example 2:
1 | Input: nums = [3,2,1] |
Example 3:
1 | Input: nums = [1,1,5] |
Constraints:
1 <= nums.length <= 1000 <= nums[i] <= 100
j = len(n)-1,i = len(n)-2。从后往前找 i,一旦发现 n[i] < n[j],就交换 n[i] 与 n[j],然后把 n[i:j+1] 反转。
要点:从末尾扫描,找到第一个”变小”的位置就把这两个值之间整段反转。
1 | def solution(nums): |
longestValidParentheses
Given a string containing just the characters '(' and ')', return *the length of the longest valid (well-formed) parentheses *substring.
Example 1:
1 | Input: s = "(()" |
Example 2:
1 | Input: s = ")()())" |
Example 3:
1 | Input: s = "" |
Constraints:
0 <= s.length <= 3 * 10^4s[i]is'(', or')'.
longestValidParentheses (stack trick) O(n)
核心想法:当遇到 ‘)’(栈非空)时,需要知道这一段合法子串从哪里开始 —— 把”开始位置”压栈即可。
每当遇到一个无效字符(仍需要 pop)或者一个 ‘(‘,就把当前位置入栈。这样以后再碰到 ‘)’,先 pop,栈顶 stack[-1] 就是当前合法子串的起点。
1 | # dp O(n) |
(mark) longestValidParentheses (dp) O(n)
dp[i] 表示以 i 结尾的最长合法子串长度。合法子串总以 ‘)’ 结尾,所以:
- s[i-1, i] = ‘()’:dp[i] = dp[i-2] + 2(dp[i-1]=0)
- s[i-1, i] = ‘))’:检查 s[i-dp[i-1]-1](也就是上一个合法子串前面那个字符)是否为 ‘(‘。如果是,dp[i] = dp[i-1] + dp[i-dp[i-1]-2] + 2 —— 即”上一个合法子串”+”再之前的合法子串”+”配对的两个括号”。
1 | # dp O(n) |
(mark) search (binary search trick) O(log n)
There is an integer array nums sorted in ascending order (with distinct values).
Prior to being passed to your function, nums is possibly left rotated at an unknown index k (1 <= k < nums.length) such that the resulting array is [nums[k], nums[k+1], ..., nums[n-1], nums[0], nums[1], ..., nums[k-1]] (0-indexed). For example, [0,1,2,4,5,6,7] might be left rotated by 3 indices and become [4,5,6,7,0,1,2].
Given the array nums after the possible rotation and an integer target, return *the index of target if it is in nums, or -1 if it is not in *nums.
You must write an algorithm with O(log n) runtime complexity.
Example 1:
1 | Input: nums = [4,5,6,7,0,1,2], target = 0 |
Example 2:
1 | Input: nums = [4,5,6,7,0,1,2], target = 3 |
Example 3:
1 | Input: nums = [1], target = 0 |
Constraints:
1 <= nums.length <= 5000-10^4 <= nums[i] <= 10^4All values of
numsare unique.numsis an ascending array that is possibly rotated.-10^4 <= target <= 10^4
举例:输入 [4, 5, 6, 7, 0, 1, 2],s = 0,e = n-1,m = (s+e)//2。
考虑四种情况:
- 旋转点在右边、目标在左半段:nums[s] <= target < nums[m] → recursive(s, m-1)
- 旋转点在左边、目标在右半段:nums[m] < target <= nums[e] → recursive(s+1, m)
- 旋转点在右边、目标在右边:nums[m] > nums[e] → recursive(m+1, e)
- 旋转点在左边、目标在左边:nums[s] > nums[m] → recursive(s, m-1)
第三种情况隐含一个条件:若 nums[m] > nums[e],则旋转点必在右边,因此 nums[s] 必小于 nums[m]。这种情况下只需检查目标是否落在右段;若落在左段,会被第一种情况捕获。第四种情况同理。
而且这种递归不会破坏旋转数组的性质。
1 | def solution(nums, target): |
searchRange (Binary Search trick) O(log n)
Given an array of integers nums sorted in non-decreasing order, find the starting and ending position of a given target value.
If target is not found in the array, return [-1, -1].
You must write an algorithm with O(log n) runtime complexity.
Example 1:
1 | Input: nums = [5,7,7,8,8,10], target = 8 |
Example 2:
1 | Input: nums = [5,7,7,8,8,10], target = 6 |
Example 3:
1 | Input: nums = [], target = 0 |
Constraints:
0 <= nums.length <= 10^5-10^9 <= nums[i] <= 10^9numsis a non-decreasing array.-10^9 <= target <= 10^9
两次二分:一次找左边界,一次找右边界。
魔改普通二分:找到 target 时不停下,继续向另一侧搜索。当 right_index < left_index 时,左边界搜索返回 left_index,右边界搜索返回 right_index。
1 | def solution(nums, target): |
combinationSum (dfs) O(exponential)
Given an array of distinct integers candidates and a target integer target, return a list of all unique combinations of candidates where the chosen numbers sum to target. You may return the combinations in any order.
The same number may be chosen from candidates an unlimited number of times. Two combinations are unique if the frequency of at least one of the chosen numbers is different.
The test cases are generated such that the number of unique combinations that sum up to target is less than 150 combinations for the given input.
Example 1:
1 | Input: candidates = [2,3,6,7], target = 7 |
Example 2:
1 | Input: candidates = [2,3,5], target = 8 |
Example 3:
1 | Input: candidates = [2], target = 1 |
Constraints:
1 <= candidates.length <= 302 <= candidates[i] <= 40All elements of
candidatesare distinct.1 <= target <= 40
外面套个 for 循环依次调用递归即可。
1 | def solution(candidates, target): |
firstMissingPositive (trick: hash with mod position) O(n)
Given an unsorted integer array nums. Return the smallest positive integer that is not present in nums.
You must implement an algorithm that runs in O(n) time and uses O(1) auxiliary space.
Example 1:
1 | Input: nums = [1,2,0] |
Example 2:
1 | Input: nums = [3,4,-1,1] |
Example 3:
1 | Input: nums = [7,8,9,11,12] |
Constraints:
1 <= nums.length <= 10^5-2^31 <= nums[i] <= 2^31 - 1
最大挑战是只能用常数额外空间,不能开 O(n) 哈希表。因此用输入数组本身充当哈希表。
做法:先把所有 <0 或 >=n 的位置置 0,然后 nums[nums[i] % n] += n,用这种方式标记某个 bin 已经出现过。最后遍历,第一个值仍小于 n 的下标就是答案。
1 | def solution(nums): |
Trap (two dp, left and right) O(n)
Given n non-negative integers representing an elevation map where the width of each bar is 1, compute how much water it can trap after raining.
Example 1:

1 | Input: height = [0,1,0,2,1,0,1,3,2,1,2,1] |
Example 2:
1 | Input: height = [4,2,0,3,2,5] |
Constraints:
n == height.length1 <= n <= 2 * 10^40 <= height[i] <= 10^5
两个 dp 数组:分别记录从左、从右两个方向看过来的最大高度。
- dp_l[i] = max(dp_l[i-1], height[i])
- dp_r[i] = max(dp_r[i+1], height[i])
每个坑的水量 = min(dp_l[i], dp_r[i]) - height[i]。
1 | def solution(height): |
Permute (loop call recusive) O(2^n)
Given an array nums of distinct integers, return all the possible permutations. You can return the answer in any order.
Example 1:
1 | Input: nums = [1,2,3] |
Example 2:
1 | Input: nums = [0,1] |
Example 3:
1 | Input: nums = [1] |
Constraints:
1 <= nums.length <= 6-10 <= nums[i] <= 10All the integers of
numsare unique.
1 | def solution(nums): |
Rotate (trick) O(n^2)
You are given an n x n 2D matrix representing an image, rotate the image by 90 degrees (clockwise).
You have to rotate the image in-place, which means you have to modify the input 2D matrix directly. DO NOT allocate another 2D matrix and do the rotation.
Example 1:

1 | Input: matrix = [[1,2,3],[4,5,6],[7,8,9]] |
Example 2:

1 | Input: matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]] |
Constraints:
n == matrix.length == matrix[i].length1 <= n <= 20-1000 <= matrix[i][j] <= 1000
先反转再转置(reverse + transpose)。
1 | def solution(matrix): |
(mark) groupAnagrams (hash) O(m)
Given an array of strings strs, group the anagrams together. You can return the answer in any order.
Example 1:
Input: strs = [“eat”,”tea”,”tan”,”ate”,”nat”,”bat”]
Output: [[“bat”],[“nat”,”tan”],[“ate”,”eat”,”tea”]]
Explanation:
There is no string in strs that can be rearranged to form
"bat".The strings
"nat"and"tan"are anagrams as they can be rearranged to form each other.The strings
"ate","eat", and"tea"are anagrams as they can be rearranged to form each other.
Example 2:
Input: strs = [“”]
Output: [[“”]]
Example 3:
Input: strs = [“a”]
Output: [[“a”]]
Constraints:
1 <= strs.length <= 10^40 <= strs[i].length <= 100strs[i]consists of lowercase English letters.
用 collections.defaultdict(list),把 tuple(sorted(s)) 作为哈希 key。
1 | from collections import defaultdict |
** 必须用 sorted(s);用 set(s) 不行(会丢失字符频次)。
(mark) maxSubArray (trick) O(n)
Given an integer array nums, find the subarray with the largest sum, and return its sum.
Example 1:
1 | Input: nums = [-2,1,-3,4,-1,2,1,-5,4] |
Example 2:
1 | Input: nums = [1] |
Example 3:
1 | Input: nums = [5,4,-1,7,8] |
Constraints:
1 <= nums.length <= 10^5-10^4 <= nums[i] <= 10^4
Follow up: If you have figured out the O(n) solution, try coding another solution using the divide and conquer approach, which is more subtle.
从左到右扫一遍,用一个累计 sum:只要左边累计是正的就保留,否则把累计的负值丢弃从头开始。
转移:nums[i] = max(0, nums[i-1]) + nums[i]
每段连续正子串里取最大:ret = max(ret, nums[i])。
1 | def solution(nums): |
canJump (greedy) O(n)
You are given an integer array nums. You are initially positioned at the array’s first index, and each element in the array represents your maximum jump length at that position.
Return true* if you can reach the last index, or false otherwise*.
Example 1:
1 | Input: nums = [2,3,1,1,4] |
Example 2:
1 | Input: nums = [3,2,1,0,4] |
Constraints:
1 <= nums.length <= 10^40 <= nums[i] <= 10^5
从左往右扫,维护”当前能到达的最远位置”。每遇到新位置就更新。能到末尾就返回 true。
1 | def solution(nums): |
merge (greedy) O(n)
Given an array of intervals where intervals[i] = [start_i, end_i], merge all overlapping intervals, and return an array of the non-overlapping intervals that cover all the intervals in the input.
Example 1:
1 | Input: intervals = [[1,3],[2,6],[8,10],[15,18]] |
Example 2:
1 | Input: intervals = [[1,4],[4,5]] |
Example 3:
1 | Input: intervals = [[4,7],[1,4]] |
Constraints:
1 <= intervals.length <= 10^4intervals[i].length == 20 <= start_i <= end_i <= 10^4
先按起点排序,然后维护一个结果数组:每次检查上一个区间的右端点是否 ≥ 当前区间的左端点,如果是就合并,否则直接 append。
1 | def solution(intervals): |
uniquePaths (dp) O(m+n)
There is a robot on an m x n grid. The robot is initially located at the top-left corner (i.e., grid[0][0]). The robot tries to move to the bottom-right corner (i.e., grid[m - 1][n - 1]). The robot can only move either down or right at any point in time.
Given the two integers m and n, return the number of possible unique paths that the robot can take to reach the bottom-right corner.
The test cases are generated so that the answer will be less than or equal to 2 * 10^9.
Example 1:

1 | Input: m = 3, n = 7 |
Example 2:
1 | Input: m = 3, n = 2 |
Constraints:
1 <= m, n <= 100
dp[i][j] = dp[i][j-1] + dp[i-1][j]
1 | def solution(m, n): |
minPathSum (dp) O(mn)
Given a m x n grid filled with non-negative numbers, find a path from top left to bottom right, which minimizes the sum of all numbers along its path.
Note: You can only move either down or right at any point in time.
Example 1:

1 | Input: grid = [[1,3,1],[1,5,1],[4,2,1]] |
Example 2:
1 | Input: grid = [[1,2,3],[4,5,6]] |
Constraints:
m == grid.lengthn == grid[i].length1 <= m, n <= 2000 <= grid[i][j] <= 200
dp[i][j] = min(dp[i][j-1], dp[i-1][j]) + m[i][j]
1 | def solution(grid): |
climbStairs (dp) O(n)
You are climbing a staircase. It takes n steps to reach the top.
Each time you can either climb 1 or 2 steps. In how many distinct ways can you climb to the top?
Example 1:
1 | Input: n = 2 |
Example 2:
1 | Input: n = 3 |
Constraints:
1 <= n <= 45
dp[i] = dp[i-1] + dp[i-2], dp[0]=1, dp[1] = 1
1 | def solution(n): |
(mark) minDistance (dc) O(mn)
Given two strings word1 and word2, return the minimum number of operations required to convert word1 to word2.
You have the following three operations permitted on a word:
Insert a character
Delete a character
Replace a character
Example 1:
1 | Input: word1 = "horse", word2 = "ros" |
Example 2:
1 | Input: word1 = "intention", word2 = "execution" |
Constraints:
0 <= word1.length, word2.length <= 500word1andword2consist of lowercase English letters.
定义递归 recursive(word1, word2, i, j, memo) 返回 word1[i:] 转成 word2[j:] 所需的最少操作数,用 memo 缓存子问题。
若 word1[i] == word2[j]:memo[i][j] = recursive(word1, word2, i+1, j+1, memo)。否则有三种操作:
- insert = 1 + recursive(word1, word2, i, j+1, memo):在 word1[i] 前插入 word2[j],使两端字符相等,然后比较 word1[i] 与 word2[j+1]。
- delete = 1 + recursive(word1, word2, i+1, j, memo):删掉 word2[j],比较 word1[i+1] 与 word2[j]。
- replace = 1 + recursive(word1, word2, i+1, j+1, memo):用 word2[j] 替换 word1[i],再比较 word1[i+1] 与 word2[j+1]。
memo[i][j] = min(insert, delete, replace)。
终止条件:i == m && j == n 时已处理完两个字符串,返回 0;i == m 时返回 n - j;j == n 时返回 m - i(剩下的字符全靠插入)。
1 | def solution(word1, word2): |
sortColors (trick) O(n)
Given an array nums with n objects colored red, white, or blue, sort them **in-place **so that objects of the same color are adjacent, with the colors in the order red, white, and blue.
We will use the integers 0, 1, and 2 to represent the color red, white, and blue, respectively.
You must solve this problem without using the library’s sort function.
Example 1:
1 | Input: nums = [2,0,2,1,1,0] |
Example 2:
1 | Input: nums = [2,0,1] |
Constraints:
n == nums.length1 <= n <= 300nums[i]is either0,1, or2.
Follow up: Could you come up with a one-pass algorithm using only constant extra space?
三指针 i, j, k:i 与 j 圈定待处理范围,k 指向当前处理的值。nums[k] 三种情况:
- nums[k] == 0:交换 nums[i] 与 nums[k],i+=1,k+=1
- nums[k] == 1:什么都不做,k+=1
- nums[k] == 2:交换 nums[j] 与 nums[k],j-=1
实际上 i 标识 0 区间的末尾,j 标识 2 区间的开头:每次遇到 0 就把它换到 0 区间末尾,遇到 2 就换到 2 区间开头,最后中间留下的全是 1。
1 | def solution(nums): |
minWindow (trick hash) O(n)
Given two strings s and t of lengths m and n respectively, return the minimum window substring* of s such that every character in t (including duplicates) is included in the window*. If there is no such substring, return *the empty string *"".
The testcases will be generated such that the answer is unique.
Example 1:
1 | Input: s = "ADOBECODEBANC", t = "ABC" |
Example 2:
1 | Input: s = "a", t = "a" |
Example 3:
1 | Input: s = "a", t = "aa" |
Constraints:
m == s.lengthn == t.length1 <= m, n <= 10^5sandtconsist of uppercase and lowercase English letters.
Follow up: Could you find an algorithm that runs in O(m + n) time?
双指针 i, j 维护滑动窗口。哈希表 m 像一个”平衡钱包”:先把 T 中的字符加进去,遍历 S 时再扣除。m[c] > 0 表示这个字符还需要找;m[c] < 0 表示这个字符已经超额(出现次数比 T 中需要的还多)。再用 count = len(T) 记录还有多少字符要找。
向右移 j:m[s[j]] -= 1;只有当 m[s[j]] > 0(说明命中了一个真正需要的字符)时才 count -= 1。当 count == 0 表示窗口包含了 T 的所有字符,开始向右移 i 缩小窗口:每次 m[s[i]] += 1,若 m[s[i]] > 0(说明丢掉了一个真正需要的字符)才 count += 1。
1 | def minWindow(self, s, t): |
Subsets (dfs) O(2^n)
Given an integer array nums of unique elements, return all possible subsets (the power set).
The solution set must not contain duplicate subsets. Return the solution in any order.
Example 1:
1 | Input: nums = [1,2,3] |
Example 2:
1 | Input: nums = [0] |
Constraints:
1 <= nums.length <= 10-10 <= nums[i] <= 10All the numbers of
numsare unique.
跟全排列类似,但中间节点也要输出。
1 | def solution(nums): |
(mark) Exist (dfs) O(mn * len(words))
Given an m x n grid of characters board and a string word, return true if word exists in the grid.
The word can be constructed from letters of sequentially adjacent cells, where adjacent cells are horizontally or vertically neighboring. The same letter cell may not be used more than once.
Example 1:

1 | Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCCED" |
Example 2:

1 | Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "SEE" |
Example 3:

1 | Input: board = [["A","B","C","E"],["S","F","C","S"],["A","D","E","E"]], word = "ABCB" |
Constraints:
m == board.lengthn = board[i].length1 <= m, n <= 61 <= word.length <= 15boardandwordconsists of only lowercase and uppercase English letters.
Follow up: Could you use search pruning to make your solution faster with a larger board?
定义递归 dfs(row, col, idx):从 nums[row][col] 开始匹配 word[idx:]。遍历每个 cell,仅当其等于 word[0] 时调用 dfs。
dfs 内:若 idx == len(word) 返回 True;否则向四个方向探索,若邻居等于 word[idx] 就递归下去;都失败则返回 False。
1 | def solution(board, word): |
largestRectangleArea (left and right dp) O(n)
Given an array of integers heights representing the histogram’s bar height where the width of each bar is 1, return the area of the largest rectangle in the histogram.
Example 1:

1 | Input: heights = [2,1,5,6,2,3] |
Example 2:

1 | Input: heights = [2,4] |
Constraints:
1 <= heights.length <= 10^50 <= heights[i] <= 10^4
两个数组 left_min、right_min 分别记录左右两侧第一个比当前更矮的位置。每个矩形面积 = height[i] * (right_min[i] - left_min[i] - 1)。
left_min[0] = -1。计算 left_min[i] 时从 j = i-1 开始,发现 height[j] >= height[i] 就跳到 j = left_min[j],递归往前找更矮的位置。
1 | def solution(heights): |
maximalRectangle (greedy) O(mn)
Given a rows x cols binary matrix filled with 0‘s and 1‘s, find the largest rectangle containing only 1‘s and return its area.
Example 1:

1 | Input: matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]] |
Example 2:
1 | Input: matrix = [["0"]] |
Example 3:
1 | Input: matrix = [["1"]] |
Constraints:
rows == matrix.lengthcols == matrix[i].length1 <= rows, cols <= 200matrix[i][j]is'0'or'1'.
三个数组分别记录最远高度、最远左边界、最远右边界。
height:
- matrix[i][j] == ‘1’ → height[j] += 1,否则 height[j] = 0
left:
- matrix[i][j] == ‘1’ → left[j] = max(left[j], cur_left),否则 left[j] = 0,cur_left = j+1
right:
- matrix[i][j] == ‘1’ → right[j] = min(right[j], cur_right),否则 right[j] = n,cur_right = j
流程:先确定矩形高度,再找它的最远左右边界。cur_left 记录当前行的最远左边界,left[j] 记录所有行的最远左边界,max(left[j], cur_left) 给出当前行内矩形的最远左边界。
1 | def solution(matrix): |
inorderTraversal (iterative) O(n)
Given the root of a binary tree, return the inorder traversal of its nodes’ values.
Example 1:
Input: root = [1,null,2,3]
Output: [1,3,2]
Explanation:

Example 2:
Input: root = [1,2,3,4,5,null,8,null,null,6,7,9]
Output: [4,2,6,5,7,1,3,9,8]
Explanation:

Example 3:
Input: root = []
Output: []
Example 4:
Input: root = [1]
Output: [1]
Constraints:
The number of nodes in the tree is in the range
[0, 100].-100 <= Node.val <= 100
Follow up: Recursive solution is trivial, could you do it iteratively?
用栈:每次 pop 一个节点,把它的子节点按 (node.left, node.val, node.right) 顺序入栈;pop 出整数就直接输出。
另一种写法:先一路把左节点压栈到最左叶子;每次 pop 一个节点输出,然后递归地把它右子节点的左链压栈。
1 | def solution(root): |
numTrees (dp) O(n^2)
Given an integer n, return *the number of structurally unique **BST’*s (binary search trees) which has exactly n nodes of unique values from 1 to n.
Example 1:

1 | Input: n = 3 |
Example 2:
1 | Input: n = 1 |
Constraints:
1 <= n <= 19
定义两个函数:
- G(n):长度为 n 的序列能形成的 BST 数量
- F(i, n),1 ≤ i ≤ n:以 i 为根、序列范围 1~n 的 BST 数量
那么 G(n) = F(1, n) + F(2, n) + … + F(n, n),且 G(0) = G(1) = 1。
注意 F(i, n) = G(i-1) * G(n-i)。
合起来:
G(n) = G(0) * G(n-1) + G(1) * G(n-2) + … + G(n-1) * G(0)。
从 G(2) 开始:G(2) = G(0) * G(1),G(3) = G(0) * G(2) + G(1) * G(1) + G(2) * G(0),… 最终得 G(n)。
一开始想用 2D dp,但发现起点终点不重要、只看子问题长度,所以用 1D dp 就够了。
1 | def solution(n): |
isValidBST (post-order, dfs) O(n)
Given the root of a binary tree, determine if it is a valid binary search tree (BST).
A valid BST is defined as follows:
The left subtree of a node contains only nodes with keys strictly less than the node’s key.
The right subtree of a node contains only nodes with keys strictly greater than the node’s key.
Both the left and right subtrees must also be binary search trees.
Example 1:

1 | Input: root = [2,1,3] |
Example 2:

1 | Input: root = [5,1,4,null,null,3,6] |
Constraints:
The number of nodes in the tree is in the range
[1, 10^4].-2^31 <= Node.val <= 2^31 - 1
解法 1(自底向上):返回每个子树的 max 和 min。合法节点要求:节点值 > 左子树 max,且 < 右子树 min。
解法 2(自顶向下):维护合法值域 (low, upper)。进入左子树时收紧上界,进入右子树时收紧下界。
1 | def solution(root): |
(mark) isSymmetric (dfs or bfs) O(n)
Given the root of a binary tree, check whether it is a mirror of itself (i.e., symmetric around its center).
Example 1:

1 | Input: root = [1,2,2,3,4,4,3] |
Example 2:

1 | Input: root = [1,2,2,null,3,null,3] |
Constraints:
The number of nodes in the tree is in the range
[1, 1000].-100 <= Node.val <= 100
Follow up: Could you solve it both recursively and iteratively?
1 | def solution(root): |
(mark) buildTree (recursive) O(n)
Given two integer arrays preorder and inorder where preorder is the preorder traversal of a binary tree and inorder is the inorder traversal of the same tree, construct and return the binary tree.
Example 1:

1 | Input: preorder = [3,9,20,15,7], inorder = [9,3,15,20,7] |
Example 2:
1 | Input: preorder = [-1], inorder = [-1] |
Constraints:
1 <= preorder.length <= 3000inorder.length == preorder.length-3000 <= preorder[i], inorder[i] <= 3000preorderandinorderconsist of unique values.Each value of
inorderalso appears inpreorder.preorderis guaranteed to be the preorder traversal of the tree.inorderis guaranteed to be the inorder traversal of the tree.
观察:preorder 按层序给出每个根,每个根又把 inorder 切成左右两段子树。
用 dict 记录 inorder 中每个值的位置以便快速查找。然后定义 helper(start, end):每次给它一个 inorder 区间,递归构造左右子树:
- root.left = helper(start, idx-1)
- root.right = helper(idx+1, end)
(若 start > end 返回 None)
1 | def solution(preorder, inorder): |
(mark) Flatten (iterative pre-order dfs) O(n)
Given the root of a binary tree, flatten the tree into a “linked list”:
The “linked list” should use the same
TreeNodeclass where therightchild pointer points to the next node in the list and theleftchild pointer is alwaysnull.The “linked list” should be in the same order as a pre-order** traversal** of the binary tree.
Example 1:

1 | Input: root = [1,2,5,3,4,null,6] |
Example 2:
1 | Input: root = [] |
Example 3:
1 | Input: root = [0] |
Constraints:
The number of nodes in the tree is in the range
[0, 2000].-100 <= Node.val <= 100
Follow up: Can you flatten the tree in-place (with O(1) extra space)?
每次找到最深的左节点,把它接到当前节点的右孩子之前;再走到原右孩子继续递归。
1 | def solution(root): |
maxProfit (trick) O(n)
You are given an array prices where prices[i] is the price of a given stock on the i^th day.
You want to maximize your profit by choosing a single day to buy one stock and choosing a different day in the future to sell that stock.
Return the maximum profit you can achieve from this transaction. If you cannot achieve any profit, return 0.
Example 1:
1 | Input: prices = [7,1,5,3,6,4] |
Example 2:
1 | Input: prices = [7,6,4,3,1] |
Constraints:
1 <= prices.length <= 10^50 <= prices[i] <= 10^4
要找 [lowest, highest] 这种二元组,且 highest 必须出现在 lowest 之后。所以记录历史最低,每次更新:
- lowest = min(lowest, prices[i])
- profit = max(profit, prices[i] - lowest)
1 | def solution(prices): |
maxPathSum (tree dp) O(n)
A path in a binary tree is a sequence of nodes where each pair of adjacent nodes in the sequence has an edge connecting them. A node can only appear in the sequence at most once. Note that the path does not need to pass through the root.
The path sum of a path is the sum of the node’s values in the path.
Given the root of a binary tree, return the maximum path sum of any non-empty path.
Example 1:

1 | Input: root = [1,2,3] |
Example 2:

1 | Input: root = [-10,9,20,null,null,15,7] |
Constraints:
The number of nodes in the tree is in the range
[1, 3 * 10^4].-1000 <= Node.val <= 1000
自底向上。每个节点拿到左、右子树各自能贡献的最大路径和,尝试更新全局答案 result = max(result, left_max + right_max + node.val);返回值为 max(left_max + node.val, right_max + node.val),表示从这个节点向上延伸的最大单链路径。注意要跟 0 比较:若小于 0 就当成不取(路径里不要这一段)。
1 | def solution(root): |
longestConsecutive (hash) O(n)
Given an unsorted array of integers nums, return the length of the longest consecutive elements sequence.
You must write an algorithm that runs in O(n) time.
Example 1:
1 | Input: nums = [100,4,200,1,3,2] |
Example 2:
1 | Input: nums = [0,3,7,2,5,8,4,6,0,1] |
Example 3:
1 | Input: nums = [1,0,1,2] |
Constraints:
0 <= nums.length <= 10^5-10^9 <= nums[i] <= 10^9
把数组转成 set。遍历时若 nums[i]-1 在 set 里就跳过;只有遇到序列起点(即没有 nums[i]-1)时才开始向后逐 +1 计数,求出连续长度。
1 | def solution(nums): |
copyRandomList (hash) O(n)
A linked list of length n is given such that each node contains an additional random pointer, which could point to any node in the list, or null.
Construct a deep copy of the list. The deep copy should consist of exactly n brand new nodes, where each new node has its value set to the value of its corresponding original node. Both the next and random pointer of the new nodes should point to new nodes in the copied list such that the pointers in the original list and copied list represent the same list state. None of the pointers in the new list should point to nodes in the original list.
For example, if there are two nodes X and Y in the original list, where X.random --> Y, then for the corresponding two nodes x and y in the copied list, x.random --> y.
Return the head of the copied linked list.
The linked list is represented in the input/output as a list of n nodes. Each node is represented as a pair of [val, random_index] where:
val: an integer representingNode.valrandom_index: the index of the node (range from0ton-1) that therandompointer points to, ornullif it does not point to any node.
Your code will only be given the head of the original linked list.
Example 1:

1 | Input: head = [[7,null],[13,0],[11,4],[10,2],[1,0]] |
Example 2:

1 | Input: head = [[1,1],[2,1]] |
Example 3:

1 | Input: head = [[3,null],[3,0],[3,null]] |
Constraints:
0 <= n <= 1000-10^4 <= Node.val <= 10^4Node.randomisnullor is pointing to some node in the linked list.
用 collections.defaultdict 记录已访问的节点。
1 | def solution(head): |
wordbreak (dp) O(mn)
Given a string s and a dictionary of strings wordDict, return true if s can be segmented into a space-separated sequence of one or more dictionary words.
Note that the same word in the dictionary may be reused multiple times in the segmentation.
Example 1:
1 | Input: s = "leetcode", wordDict = ["leet","code"] |
Example 2:
1 | Input: s = "applepenapple", wordDict = ["apple","pen"] |
Example 3:
1 | Input: s = "catsandog", wordDict = ["cats","dog","sand","and","cat"] |
Constraints:
1 <= s.length <= 3001 <= wordDict.length <= 10001 <= wordDict[i].length <= 20sandwordDict[i]consist of only lowercase English letters.All the strings of
wordDictare unique.
dp[i] 表示 s[0:i] 是否可被切分。转移:dp[i] = True 当存在 w 使得 dp[i - len(w)] == True 且 s[i - len(w):i] == w。
1 | def solution(s, wordDict): |
DetectCycle (trick) O(n)
Given the head of a linked list, return *the node where the cycle begins. If there is no cycle, return *null.
There is a cycle in a linked list if there is some node in the list that can be reached again by continuously following the next pointer. Internally, pos is used to denote the index of the node that tail’s next pointer is connected to (0-indexed). It is -1 if there is no cycle. Note that pos is not passed as a parameter.
Do not modify the linked list.
Example 1:

1 | Input: head = [3,2,0,-4], pos = 1 |
Example 2:

1 | Input: head = [1,2], pos = 0 |
Example 3:

1 | Input: head = [1], pos = -1 |
Constraints:
The number of the nodes in the list is in the range
[0, 10^4].-10^5 <= Node.val <= 10^5posis-1or a valid index in the linked-list.
Follow up: Can you solve it using O(1) (i.e. constant) memory?
设头节点到环入口距离为 A,慢指针走了 A+B 与快指针相遇。快指针走了 2(A+B)。设环长 N,相遇时快指针比慢指针多走的恰好是若干圈环长。
- A+B+N = 2A+2B
- N = A+B
所以两者相遇后,再让一个新指针从 head 出发,与 slow 同步前进,相遇点就是环的入口(因为 B + A = N)。
1 | def solution(head): |
LRUCache (double linked list) O(1)
Design a data structure that follows the constraints of a Least Recently Used (LRU) cache.
Implement the LRUCache class:
LRUCache(int capacity)Initialize the LRU cache with positive sizecapacity.int get(int key)Return the value of thekeyif the key exists, otherwise return-1.void put(int key, int value)Update the value of thekeyif thekeyexists. Otherwise, add thekey-valuepair to the cache. If the number of keys exceeds thecapacityfrom this operation, evict the least recently used key.
The functions get and put must each run in O(1) average time complexity.
Example 1:
1 | Input |
Constraints:
1 <= capacity <= 30000 <= key <= 10^40 <= value <= 10^5At most
2 * 10^5calls will be made togetandput.
用双向链表,封装两个基本操作:remove(按 id 移除节点)和 add(追加到尾部)。
- get:先 remove 再 add(提到尾部)
- put:add 到尾部;超容量时从头部 remove
1 | class Node: |
SortList (merge sort or quick sort) O(nlogn)
Given the head of a linked list, return the list after sorting it in ascending order.
Example 1:

1 | Input: head = [4,2,1,3] |
Example 2:

1 | Input: head = [-1,5,3,4,0] |
Example 3:
1 | Input: head = [] |
Constraints:
The number of nodes in the list is in the range
[0, 5 * 10^4].-10^5 <= Node.val <= 10^5
Follow up: Can you sort the linked list in O(n logn) time and O(1) memory (i.e. constant space)?
用三个子链表存放节点:以 head 为 partition 节点;left_head 存比它小的节点,right_head 存比它大的节点,middle_head 存与它相等的节点。
然后对 left_head 和 right_head 递归排序,最后把三段串起来。
1 | def solution(head): |
(mark) maxProduct (greedy) O(n)
Given an integer array nums, find a subarray that has the largest product, and return the product.
The test cases are generated so that the answer will fit in a 32-bit integer.
Note that the product of an array with a single element is the value of that element.
Example 1:
1 | Input: nums = [2,3,-2,4] |
Example 2:
1 | Input: nums = [-2,0,-1] |
Constraints:
1 <= nums.length <= 2 * 10^4-10 <= nums[i] <= 10The product of any subarray of
numsis guaranteed to fit in a 32-bit integer.
同时记录当前最大值和最小值(因为负数乘负数可能成为最大)。每步用三者 (num, b*num, s*num) 取 max/min 更新。
1 | def solution(nums): |
MinStack (trick) O(n)
Design a stack that supports push, pop, top, and retrieving the minimum element in constant time.
Implement the MinStack class:
MinStack()initializes the stack object.void push(int value)pushes the elementvalueonto the stack.void pop()removes the element on the top of the stack.int top()gets the top element of the stack.int getMin()retrieves the minimum element in the stack.
You must implement a solution with O(1) time complexity for each function.
Example 1:
1 | Input |
Constraints:
-2^31 <= val <= 2^31 - 1Methods
pop,topandgetMinoperations will always be called on non-empty stacks.At most
3 * 10^4calls will be made topush,pop,top, andgetMin.
再开一个栈记录”当前最小”。每次 push 一个新值时,与原栈顶最小比较:新值大就复制旧最小,否则把新值压入。pop 时两个栈一起 pop。
1 | class MinStack(object): |
GetIntersectionNode (trick) O(m+n)
Given the heads of two singly linked-lists headA and headB, return the node at which the two lists intersect. If the two linked lists have no intersection at all, return null.
For example, the following two linked lists begin to intersect at node c1:

The test cases are generated such that there are no cycles anywhere in the entire linked structure.
Note that the linked lists must retain their original structure after the function returns.
Custom Judge:
The inputs to the judge are given as follows (your program is not given these inputs):
intersectVal- The value of the node where the intersection occurs. This is0if there is no intersected node.listA- The first linked list.listB- The second linked list.skipA- The number of nodes to skip ahead inlistA(starting from the head) to get to the intersected node.skipB- The number of nodes to skip ahead inlistB(starting from the head) to get to the intersected node.
The judge will then create the linked structure based on these inputs and pass the two heads, headA and headB to your program. If you correctly return the intersected node, then your solution will be accepted.
Example 1:

1 | Input: intersectVal = 8, listA = [4,1,8,4,5], listB = [5,6,1,8,4,5], skipA = 2, skipB = 3 |
Example 2:

1 | Input: intersectVal = 2, listA = [1,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 1 |
Example 3:

1 | Input: intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2 |
Constraints:
The number of nodes of
listAis in them.The number of nodes of
listBis in then.1 <= m, n <= 3 * 10^41 <= Node.val <= 10^50 <= skipA <= m0 <= skipB <= nintersectValis0iflistAandlistBdo not intersect.intersectVal == listA[skipA] == listB[skipB]iflistAandlistBintersect.
Follow up: Could you write a solution that runs in O(m + n) time and use only O(1) memory?
两条链表 p、q,把 p 接到 q 尾部、q 接到 p 尾部之后再走,两个指针相遇时即为交点。
1 | def solution(headA, headB): |
MajorityElement (trick) O(n)
Given an array nums of size n, return the majority element.
The majority element is the element that appears more than ⌊n / 2⌋ times. You may assume that the majority element always exists in the array.
Example 1:
1 | Input: nums = [3,2,3] |
Example 2:
1 | Input: nums = [2,2,1,1,1,2,2] |
Constraints:
n == nums.length1 <= n <= 5 * 10^4-10^9 <= nums[i] <= 10^9The input is generated such that a majority element will exist in the array.
Follow-up: Could you solve the problem in linear time and in O(1) space?
Boyer-Moore 投票法。维护 value 和 count:count == 0 时把 value 置为 nums[i] 并 count += 1;nums[i] == value 则 count += 1,否则 count -= 1。
1 | def solution(nums): |
Rob (dp) O(n)
You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security systems connected and it will automatically contact the police if two adjacent houses were broken into on the same night.
Given an integer array nums representing the amount of money of each house, return the maximum amount of money you can rob tonight without alerting the police.
Example 1:
1 | Input: nums = [1,2,3,1] |
Example 2:
1 | Input: nums = [2,7,9,3,1] |
Constraints:
1 <= nums.length <= 1000 <= nums[i] <= 400
解法 1:两个数组 max_rob、max_not_rob。max_rob[i] 表示打劫第 i 家时的最大金额,max_not_rob[i] 表示不打劫时的最大金额:
- max_rob[i] = max_not_rob[i-1] + nums[i]
- max_not_rob[i] = max(max_not_rob[i-1], max_rob[i-1])
解法 2:
- f(0) = nums[0]
- f(1) = max(num[0], num[1])
- f(k) = max(f(k-2) + nums[k], f(k-1))
1 | def solution(nums): |
numIslands (BFS DFS) O(mn)
Given an m x n 2D binary grid grid which represents a map of '1's (land) and '0's (water), return the number of islands.
An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assume all four edges of the grid are all surrounded by water.
Example 1:
1 | Input: grid = [ |
Example 2:
1 | Input: grid = [ |
Constraints:
m == grid.lengthn == grid[i].length1 <= m, n <= 300grid[i][j]is'0'or'1'.
双重 for 循环遍历所有 cell;遇到 ‘1’ 就 BFS(用栈/队列),把同一连通块的 ‘1’ 都改成 ‘0’。
1 | def solution(grid): |
(mark) canFinish (dfs) O(n^3)
There are a total of numCourses courses you have to take, labeled from 0 to numCourses - 1. You are given an array prerequisites where prerequisites[i] = [a_i, b_i] indicates that you must take course b_i first if you want to take course a_i.
- For example, the pair
[0, 1], indicates that to take course0you have to first take course1.
Return true if you can finish all courses. Otherwise, return false.
Example 1:
1 | Input: numCourses = 2, prerequisites = [[1,0]] |
Example 2:
1 | Input: numCourses = 2, prerequisites = [[1,0],[0,1]] |
Constraints:
1 <= numCourses <= 20000 <= prerequisites.length <= 5000prerequisites[i].length == 20 <= a_i, b_i < numCoursesAll the pairs prerequisites[i] are unique.
visited 数组记录每个节点状态:初始为 0,开始递归时置 -1,递归结束置 1。递归中若发现 visited[i] == -1 直接返回 False(找到环);若 visited[i] == 1 返回 True(已确认无环,避免重复搜索)。
1 | def solution(numCourses, prerequisites): |
Trie (tree) O(n)
A trie (pronounced as “try”) or prefix tree is a tree data structure used to efficiently store and retrieve keys in a dataset of strings. There are various applications of this data structure, such as autocomplete and spellchecker.
Implement the Trie class:
Trie()Initializes the trie object.void insert(String word)Inserts the stringwordinto the trie.boolean search(String word)Returnstrueif the stringwordis in the trie (i.e., was inserted before), andfalseotherwise.boolean startsWith(String prefix)Returnstrueif there is a previously inserted stringwordthat has the prefixprefix, andfalseotherwise.
Example 1:
1 | Input |
Constraints:
1 <= word.length, prefix.length <= 2000wordandprefixconsist only of lowercase English letters.At most
3 * 10^4calls in total will be made toinsert,search, andstartsWith.
1 | class TrieNode(): |
(mark) findKthLargest (heap, quickselect) O(nlogn)
Given an integer array nums and an integer k, return the k^th largest element in the array.
Note that it is the k^th largest element in the sorted order, not the k^th distinct element.
Can you solve it without sorting?
Example 1:
1 | Input: nums = [3,2,1,5,6,4], k = 2 |
Example 2:
1 | Input: nums = [3,2,3,1,2,4,5,5,6], k = 4 |
Constraints:
1 <= k <= nums.length <= 10^5-10^4 <= nums[i] <= 10^4
堆解法直接用 heap。quickselect 类似快排:每次选 pivot 把数组划成两部分;若 len(left_part) == k-1 就返回 pivot;否则在大的那一部分继续找第 k 大或第 k-len(left_part)-1 大。
1 | # O(klogk+2(n-k)logk) |
maximalSquare (dp) O(n^2)
Given an m x n binary matrix filled with 0‘s and 1‘s, find the largest square containing only 1‘s and return its area.
Example 1:

1 | Input: matrix = [["1","0","1","0","0"],["1","0","1","1","1"],["1","1","1","1","1"],["1","0","0","1","0"]] |
Example 2:

1 | Input: matrix = [["0","1"],["1","0"]] |
Example 3:
1 | Input: matrix = [["0"]] |
Constraints:
m == matrix.lengthn == matrix[i].length1 <= m, n <= 300matrix[i][j]is'0'or'1'.dp[i][j] = min(dp[i-1][j-1], dp[i][j-1], dp[i-1][j]) + 1,若 matrix[i][j] == ‘1’
max_v = max(max_v, dp[i][j])
1 | def solution(matrix): |
invertTree (recursive) O(n)
Given the root of a binary tree, invert the tree, and return its root.
Example 1:

1 | Input: root = [4,2,7,1,3,6,9] |
Example 2:

1 | Input: root = [2,1,3] |
Example 3:
1 | Input: root = [] |
Constraints:
The number of nodes in the tree is in the range
[0, 100].-100 <= Node.val <= 100
root.left, root.right = recursive(root.right), recursive(root.left)
1 | def solution(root): |
isPalindrome (trick) O(n)
Given the head of a singly linked list, return true* if it is a palindrome or false otherwise*.
Example 1:

1 | Input: head = [1,2,2,1] |
Example 2:

1 | Input: head = [1,2] |
Constraints:
The number of nodes in the list is in the range
[1, 10^5].0 <= Node.val <= 9
Follow up: Could you do it in O(n) time and O(1) space?
快慢指针:fast 每次走两步、slow 每次走一步。fast 走到尾时把链表后半段反转,再与前半段逐一比较。
1 | def solution(head): |
lowestCommonAncestor (recursive) O(n)
Given a binary tree, find the lowest common ancestor (LCA) of two given nodes in the tree.
According to the definition of LCA on Wikipedia: “The lowest common ancestor is defined between two nodes p and q as the lowest node in T that has both p and q as descendants (where we allow a node to be a descendant of itself).”
Example 1:

1 | Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1 |
Example 2:

1 | Input: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 |
Example 3:
1 | Input: root = [1,2], p = 1, q = 2 |
Constraints:
The number of nodes in the tree is in the range
[2, 10^5].-10^9 <= Node.val <= 10^9All
Node.valare unique.p != qpandqwill exist in the tree.
后序递归。count = recursive(root.left, p, q) + recursive(root.right, p, q);若 root.val == p or == q,则 cur_count = 1 否则 0。当 count + cur_count == 2 时,记录答案。
1 | def solution(root, p, q): |
productExceptSelf (two pointers, reverse list) O(n)
Given an integer array nums, return an array answer such that answer[i] is equal to the product of all the elements of nums except nums[i].
The product of any prefix or suffix of nums is guaranteed to fit in a 32-bit integer.
You must write an algorithm that runs in O(n) time and without using the division operation.
Example 1:
1 | Input: nums = [1,2,3,4] |
Example 2:
1 | Input: nums = [-1,1,0,-3,3] |
Constraints:
2 <= nums.length <= 10^5-30 <= nums[i] <= 30The input is generated such that
answer[i]is guaranteed to fit in a 32-bit integer.
Follow up: Can you solve the problem in O(1) extra space complexity? (The output array does not count as extra space for space complexity analysis.)
两个数组:第一个记录左侧累积乘积,第二个记录右侧累积乘积,最后 result[i] = left[i] * right[i]。
1 | def solution(nums): |
maxSlidingWindow (trick) O(n)
You are given an array of integers nums, there is a sliding window of size k which is moving from the very left of the array to the very right. You can only see the k numbers in the window. Each time the sliding window moves right by one position.
Return the max sliding window.
Example 1:
1 | Input: nums = [1,3,-1,-3,5,3,6,7], k = 3 |
Example 2:
1 | Input: nums = [1], k = 1 |
Constraints:
1 <= nums.length <= 10^5-10^4 <= nums[i] <= 10^41 <= k <= nums.length
不需要每次重算最大值。维护一个结果数组,每次:
- 新进入的值 ≥ 当前最大:直接 append 新值
- 即将出窗的值 < 当前最大:append 当前最大(不变)
- 否则才在窗口内重新求 max
1 | def solution(nums, k): |
(mark) searchMatrix (trick) O(m+n)
Write an efficient algorithm that searches for a value target in an m x n integer matrix matrix. This matrix has the following properties:
Integers in each row are sorted in ascending from left to right.
Integers in each column are sorted in ascending from top to bottom.
Example 1:

1 | Input: matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 5 |
Example 2:

1 | Input: matrix = [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],[10,13,14,17,24],[18,21,23,26,30]], target = 20 |
Constraints:
m == matrix.lengthn == matrix[i].length1 <= n, m <= 300-10^9 <= matrix[i][j] <= 10^9All the integers in each row are sorted in ascending order.
All the integers in each column are sorted in ascending order.
-10^9 <= target <= 10^9
第一行从右端开始,把比 target 大的列排除,记录下当前列下标;第二行从该列继续往左排除…… 找到 target 返回 True,否则 False。
1 | def solution(matrix, target): |
numSquares (dp) O(n^1.5)
Given an integer n, return the least number of perfect square numbers that sum to n.
A perfect square is an integer that is the square of an integer; in other words, it is the product of some integer with itself. For example, 1, 4, 9, and 16 are perfect squares while 3 and 11 are not.
Example 1:
1 | Input: n = 12 |
Example 2:
1 | Input: n = 13 |
Constraints:
1 <= n <= 10^4
候选范围 [1, floor(n^0.5)]。dp[i] = min(dp[i - j^2] + 1),j 取所有候选。
1 | import math, sys |
moveZeroes (trick) O(n)
Given an integer array nums, move all 0‘s to the end of it while maintaining the relative order of the non-zero elements.
Note that you must do this in-place without making a copy of the array.
Example 1:
1 | Input: nums = [0,1,0,3,12] |
Example 2:
1 | Input: nums = [0] |
Constraints:
1 <= nums.length <= 10^4-2^31 <= nums[i] <= 2^31 - 1
Follow up: Could you minimize the total number of operations done?
每遇到非零值,就把它和”第一个 0”的位置交换。维护 index 记录第一个 0 的位置:nums[i] != 0 时 swap 并 index += 1,否则不动。
1 | def solution(nums): |
findDuplicate (trick) O(n)
Given an array of integers nums containing n + 1 integers where each integer is in the range [1, n] inclusive.
There is only one repeated number in nums, return this repeated number.
You must solve the problem without modifying the array nums and using only constant extra space.
Example 1:
1 | Input: nums = [1,3,4,2,2] |
Example 2:
1 | Input: nums = [3,1,3,4,2] |
Example 3:
1 | Input: nums = [3,3,3,3,3] |
Constraints:
1 <= n <= 10^5nums.length == n + 11 <= nums[i] <= nAll the integers in
numsappear only once except for precisely one integer which appears two or more times.
Follow up:
How can we prove that at least one duplicate number must exist in
nums?Can you solve the problem in linear runtime complexity?
转化为”链表找环入口”:把下标 i 看成节点,i → nums[i]。因为有重复值,这条链一定有环;环的入口就是重复值。
1 | def solution(nums): |
MedianFinder (trick) O(nlogn)
The median is the middle value in an ordered integer list. If the size of the list is even, there is no middle value, and the median is the mean of the two middle values.
For example, for
arr = [2,3,4], the median is3.For example, for
arr = [2,3], the median is(2 + 3) / 2 = 2.5.
Implement the MedianFinder class:
MedianFinder()initializes theMedianFinderobject.void addNum(int num)adds the integernumfrom the data stream to the data structure.double findMedian()returns the median of all elements so far. Answers within10^-5of the actual answer will be accepted.
Example 1:
1 | Input |
Constraints:
-10^5 <= num <= 10^5There will be at least one element in the data structure before calling
findMedian.At most
5 * 10^4calls will be made toaddNumandfindMedian.
Follow up:
If all integer numbers from the stream are in the range
[0, 100], how would you optimize your solution?If
99%of all integer numbers from the stream are in the range[0, 100], how would you optimize your solution?
解法 1:维护一个有序列表,每次用二分找到插入位置。
解法 2:双堆 —— 大顶堆(存较小一半)+ 小顶堆(存较大一半)。每次插入时若两堆大小相等,先入大堆再 pop 一个最大值送进小堆;否则反之。求中位数:两堆等长时取两个堆顶平均,否则取大堆堆顶。
1 | import heapq |
Serialize (bfs) O(n)
Serialization is the process of converting a data structure or object into a sequence of bits so that it can be stored in a file or memory buffer, or transmitted across a network connection link to be reconstructed later in the same or another computer environment.
Design an algorithm to serialize and deserialize a binary tree. There is no restriction on how your serialization/deserialization algorithm should work. You just need to ensure that a binary tree can be serialized to a string and this string can be deserialized to the original tree structure.
Clarification: The input/output format is the same as how LeetCode serializes a binary tree. You do not necessarily need to follow this format, so please be creative and come up with different approaches yourself.
Example 1:

1 | Input: root = [1,2,3,null,null,4,5] |
Example 2:
1 | Input: root = [] |
Constraints:
The number of nodes in the tree is in the range
[0, 10^4].-1000 <= Node.val <= 1000
按完全二叉树编号:node[i] 的子节点是 node[2i] 和 node[2i+1]。
1 | def serialize(self, root): |
lengthOfLIS(dp)
Given an integer array nums, return *the length of the longest **strictly increasing ***subsequence.
Example 1:
1 | Input: nums = [10,9,2,5,3,7,101,18] |
Example 2:
1 | Input: nums = [0,1,0,3,2,3] |
Example 3:
1 | Input: nums = [7,7,7,7,7,7,7] |
Constraints:
1 <= nums.length <= 2500-10^4 <= nums[i] <= 10^4
Follow up: Can you come up with an algorithm that runs in O(n log(n)) time complexity?
lengthOfLIS(dp) O(n^2)
dp[i] 表示以位置 i 结尾的最长上升子序列长度。每次把当前值与之前所有值比较,若当前更大就尝试更新:
1 | def lengthOfLIS(nums): |
(mark) lengthOfLIS(dp) O(nlogn)
dp[i] 存放当前已遍历元素能构成的”潜在上升子序列”的第 i 个位置候选值。
例:输入 [0, 8, 4, 12, 2]:
逐元素扫描,每次在 dp 里二分找到第一个 ≥ 当前值的位置替换。
- 0 → dp = [0]
- 8 → dp = [0, 8]
- 4 → dp = [0, 4]
- 12 → dp = [0, 4, 12]
- 2 → dp = [0, 2, 12]
注意:最终的 dp 不是真正的 LIS,但它的长度就是 LIS 长度。
为什么把 [0, 4, 12] 改成 [0, 2, 12] 仍然合法?(1) 不破坏长度本身;(2) 之后碰到比 2 大的值时,可以接在 2 后面延伸出更长的 LIS。
1 | # o(n^2) |
removeInvalidParentheses(recursive) O(n^2)
Given a string s that contains parentheses and letters, remove the minimum number of invalid parentheses to make the input string valid.
Return a list of unique strings that are valid with the minimum number of removals. You may return the answer in any order.
Example 1:
1 | Input: s = "()())()" |
Example 2:
1 | Input: s = "(a)())()" |
Example 3:
1 | Input: s = ")(" |
Constraints:
1 <= s.length <= 25sconsists of lowercase English letters and parentheses'('and')'.There will be at most
20parentheses ins.
用计数器扫描:’(‘ 时 +1,’)’ 时 -1。一旦计数器为负,说明前缀里 ‘)’ 比 ‘(‘ 多。
要修复,需要删一个 ‘)’。删哪一个?理论上前缀里任意一个都行,但为避免重复结果(如 “())” 删 s[1] 或 s[2] 都得到 “()”),约定只删一连串 ‘)’ 中的第一个。
删完后前缀合法,再递归处理剩下部分。但还需要追加信息:上一次删除的位置。否则两次删除按不同顺序会产生重复。
所以维护两个游标:i 表示扫描到哪、j 表示从哪开始可以删 ‘)’。i 与 j 之间的每一个 ‘)’ 都尝试递归。
那 ‘(‘ 怎么办?比如 s = '(()(('。答案是从右往左做一遍。更聪明的做法:把字符串反转,复用同一段代码!
1 | def removeInvalidParentheses(self, s): |
maxProfit(dp) O(3n)
You are given an array prices where prices[i] is the price of a given stock on the i^th day.
Find the maximum profit you can achieve. You may complete as many transactions as you like (i.e., buy one and sell one share of the stock multiple times) with the following restrictions:
- After you sell your stock, you cannot buy stock on the next day (i.e., cooldown one day).
Note: You may not engage in multiple transactions simultaneously (i.e., you must sell the stock before you buy again).
Example 1:
1 | Input: prices = [1,2,3,0,2] |
Example 2:
1 | Input: prices = [1] |
Constraints:
1 <= prices.length <= 50000 <= prices[i] <= 1000
stack[n][3]:stack[i][0] 记录冷冻期,stack[i][1] 记录买入,stack[i][2] 记录卖出。
- 冷冻:取前一天三种状态的最大值 stack[i][0] = max(stack[i-1])
- 买入:只能从前一天的冷冻期转过来 stack[i][1] = stack[i-1][0] - prices[i]。不会出现 [买, 冷, 买] 因为冷冻已取了 max。
- 卖出:stack[i][2] = bought + prices[i]。bought = max(bought, stack[i][1]),记录当下最便宜的买入成本。
- 维护 bought 是为了避免 [卖, 休, 卖] 的退化路径,每步都保最大 bought(即最小成本)。
1 | def solution(prices): |
maxCoins(dp) O(n^3)
You are given n balloons, indexed from 0 to n - 1. Each balloon is painted with a number on it represented by an array nums. You are asked to burst all the balloons.
If you burst the i^th balloon, you will get nums[i - 1] * nums[i] * nums[i + 1] coins. If i - 1 or i + 1 goes out of bounds of the array, then treat it as if there is a balloon with a 1 painted on it.
Return the maximum coins you can collect by bursting the balloons wisely.
Example 1:
1 | Input: nums = [3,1,5,8] |
Example 2:
1 | Input: nums = [1,5] |
Constraints:
n == nums.length1 <= n <= 3000 <= nums[i] <= 100
dp[i][j] 表示已经把 i 与 j 之间的气球全部戳掉后所获得的最大金币数。转移:
1 | for k in range(i+1, j): |
含义:要让 [i, j] 之间金币最大,枚举每个气球 k 作为最后一个被戳的。也就是先把 (i, k) 和 (k, j) 之间的气球戳完,最后只剩 i、k、j 三个。
注意:在数组首尾各 append 一个 1,每次只处理 i+1 到 j(跳过哨兵)。这个 trick 保证 nums[i] * nums[k] * nums[j] 公式成立。
1 | def solution(nums): |
coinChange(dp) O(nm)
You are given an integer array coins representing coins of different denominations and an integer amount representing a total amount of money.
Return the fewest number of coins that you need to make up that amount. If that amount of money cannot be made up by any combination of the coins, return -1.
You may assume that you have an infinite number of each kind of coin.
Example 1:
1 | Input: coins = [1,2,5], amount = 11 |
Example 2:
1 | Input: coins = [2], amount = 3 |
Example 3:
1 | Input: coins = [1], amount = 0 |
Constraints:
1 <= coins.length <= 121 <= coins[i] <= 2^31 - 10 <= amount <= 10^4
dp[i] = min(dp[i - coin] + 1) for coin in coins。
1 | def solution(coins, amount): |
Rob(dp in a tree), O(n)
The thief has found himself a new place for his thievery again. There is only one entrance to this area, called root.
Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that all houses in this place form a binary tree. It will automatically contact the police if two directly-linked houses were broken into on the same night.
Given the root of the binary tree, return the maximum amount of money the thief can rob without alerting the police.
Example 1:

1 | Input: root = [3,2,3,null,3,null,1] |
Example 2:

1 | Input: root = [3,4,5,1,3,null,1] |
Constraints:
The number of nodes in the tree is in the range
[1, 10^4].0 <= Node.val <= 10^4
1 | def solution(root): |
countBits(dp) O(n)
Given an integer n, return *an array ans of length n + 1 such that for each i (0 <= i <= n), ans[i] is the number of 1‘s in the binary representation of *i.
Example 1:
1 | Input: n = 2 |
Example 2:
1 | Input: n = 5 |
Constraints:
0 <= n <= 10^5
Follow up:
It is very easy to come up with a solution with a runtime of
O(n log n). Can you do it in linear timeO(n)and possibly in a single pass?Can you do it without using any built-in function (i.e., like
__builtin_popcountin C++)?
f[i] = f[i // 2] + i % 2
直观上:右移一位等于减半,再加上是否末位为 1。
1 | def solution(num): |
topKFrequent(heap) O(nlogn)
Given an integer array nums and an integer k, return the k most frequent elements. You may return the answer in any order.
Example 1:
Input: nums = [1,1,1,2,2,3], k = 2
Output: [1,2]
Example 2:
Input: nums = [1], k = 1
Output: [1]
Example 3:
Input: nums = [1,2,1,2,1,2,3,1,3,2], k = 2
Output: [1,2]
Constraints:
1 <= nums.length <= 10^5-10^4 <= nums[i] <= 10^4kis in the range[1, the number of unique elements in the array].It is guaranteed that the answer is unique.
Follow up: Your algorithm’s time complexity must be better than O(n log n), where n is the array’s size.
1 | from collections import defaultdict |
decodeString(stack) O(n)
Given an encoded string, return its decoded string.
The encoding rule is: k[encoded_string], where the encoded_string inside the square brackets is being repeated exactly k times. Note that k is guaranteed to be a positive integer.
You may assume that the input string is always valid; there are no extra white spaces, square brackets are well-formed, etc. Furthermore, you may assume that the original data does not contain any digits and that digits are only for those repeat numbers, k. For example, there will not be input like 3a or 2[4].
The test cases are generated so that the length of the output will never exceed 10^5.
Example 1:
1 | Input: s = "3[a]2[bc]" |
Example 2:
1 | Input: s = "3[a2[c]]" |
Example 3:
1 | Input: s = "2[abc]3[cd]ef" |
Constraints:
1 <= s.length <= 30sconsists of lowercase English letters, digits, and square brackets'[]'.sis guaranteed to be a valid input.All the integers in
sare in the range[1, 300].
栈解法:遇到 ‘]’ 时 pop 出 ‘[‘ 之前的字符串,再继续 pop 数字字符拼成倍数,把字符串重复后压回栈。
1 | def solution(s): |
reconstructQueue(trick) O(nlog)
You are given an array of people, people, which are the attributes of some people in a queue (not necessarily in order). Each people[i] = [h_i, k_i] represents the i^th person of height h_i with exactly k_i other people in front who have a height greater than or equal to h_i.
Reconstruct and return *the queue that is represented by the input array *people. The returned queue should be formatted as an array queue, where queue[j] = [h_j, k_j] is the attributes of the j^th person in the queue (queue[0] is the person at the front of the queue).
Example 1:
1 | Input: people = [[7,0],[4,4],[7,1],[5,0],[6,1],[5,2]] |
Example 2:
1 | Input: people = [[6,0],[5,0],[4,0],[3,2],[2,2],[1,4]] |
Constraints:
1 <= people.length <= 20000 <= h_i <= 10^60 <= k_i < people.lengthIt is guaranteed that the queue can be reconstructed.
先按 (-x[0], x[1]) 排序:身高降序、k 升序。
然后按每个 tuple 的第二个元素(k)作为下标插入:result.insert(p[1], p)。
原理:一个 tuple 的位置只受比它高的 tuple 影响,所以先处理高的;同身高里 k 小的先插入,能保证后续插入不打乱已经成立的”前面有几个 ≥ 自己”的条件。
1 | def solution(people): |
canPartition
Given an integer array nums, return true if you can partition the array into two subsets such that the sum of the elements in both subsets is equal or false otherwise.
Example 1:
1 | Input: nums = [1,5,11,5] |
Example 2:
1 | Input: nums = [1,2,3,5] |
Constraints:
1 <= nums.length <= 2001 <= nums[i] <= 100
canPartition(dp) O(n*s), n<=200, s<=10000
矩阵 dp[n][s],n 是元素数,s = sum(input)//2。dp[i][j] = True 表示从前 i 个数中能选出和为 j 的子集。
- 先令 dp[i][nums[i]-1] = 1,表示只选第 i 个值
- dp[i][j] 来自两种情况:不选第 i 个 dp[i-1][j];选第 i 个 dp[i-1][j-nums[i]]
Partition(dp) O(2^n with cutting branch)
递归调用 helper(nums[i+1:], target - num) for i, num in enumerate(nums),剪枝即可。
1 | # O(N * S) |
pathSum(dp) O(n)
Given the root of a binary tree and an integer targetSum, return the number of paths where the sum of the values along the path equals targetSum.
The path does not need to start or end at the root or a leaf, but it must go downwards (i.e., traveling only from parent nodes to child nodes).
Example 1:

1 | Input: root = [10,5,-3,3,2,null,11,3,-2,null,1], targetSum = 8 |
Example 2:
1 | Input: root = [5,4,8,11,null,13,4,7,2,null,null,5,1], targetSum = 22 |
Constraints:
The number of nodes in the tree is in the range
[0, 1000].-10^9 <= Node.val <= 10^9-1000 <= targetSum <= 1000
假设所有路径都从 root 出发。维护一个”老的累计和” oldPathSum 和当前累计和 currPathSum:当 oldPathSum == currPathSum - target 时,就找到一条满足条件的路径,因此 result += cache.get(oldPathSum, 0)。
注意:进入节点时 cache[currPathSum] = cache.get(currPathSum, 0) + 1,递归子节点;离开节点时 cache[currPathSum] -= 1。
1 | def solution(root, target): |
findAnagrams(cache) O(n)
Given two strings s and p, return an array of all the start indices of p‘s anagrams in s. You may return the answer in any order.
Example 1:
1 | Input: s = "cbaebabacd", p = "abc" |
Example 2:
1 | Input: s = "abab", p = "ab" |
Constraints:
1 <= s.length, p.length <= 3 * 10^4sandpconsist of lowercase English letters.
用一个长度 26 的桶记录当前子串字符频次。每次滑动窗口更新桶,与 target 桶比较。
1 | def solution(s, p): |
findDisappearedNumbers(trick) (n)
Given an array nums of n integers where nums[i] is in the range [1, n], return an array of all the integers in the range [1, n] that do not appear in nums.
Example 1:
1 | Input: nums = [4,3,2,7,8,2,3,1] |
Example 2:
1 | Input: nums = [1,1] |
Constraints:
n == nums.length1 <= n <= 10^51 <= nums[i] <= n
Follow up: Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.
遍历数组,把”已出现”的对应位置标记为负数。最后剩下正数的下标 +1 就是缺失的数。
1 | def solution(nums): |
findTargetSumWays(dp) O(n*2s) s=sum(nums)
dp 矩阵 dp[0:n][-s:s]:第 0 行 dp[0][±nums[0]] = 1;后续行 dp[i][j] = dp[i][j - nums[i]] + dp[i][j + nums[i]]。
You are given an integer array nums and an integer target.
You want to build an expression out of nums by adding one of the symbols '+' and '-' before each integer in nums and then concatenate all the integers.
- For example, if
nums = [2, 1], you can add a'+'before2and a'-'before1and concatenate them to build the expression"+2-1".
Return the number of different expressions that you can build, which evaluates to target.
Example 1:
1 | Input: nums = [1,1,1,1,1], target = 3 |
Example 2:
1 | Input: nums = [1], target = 1 |
Constraints:
1 <= nums.length <= 200 <= nums[i] <= 10000 <= sum(nums[i]) <= 1000-1000 <= target <= 1000
1 | def solution(nums, S): |
diameterOfBinaryTree(tree dp) (n)
Given the root of a binary tree, return the length of the diameter of the tree.
The diameter of a binary tree is the length of the longest path between any two nodes in a tree. This path may or may not pass through the root.
The length of a path between two nodes is represented by the number of edges between them.
Example 1:

1 | Input: root = [1,2,3,4,5] |
Example 2:
1 | Input: root = [1,2] |
Constraints:
The number of nodes in the tree is in the range
[1, 10^4].-100 <= Node.val <= 100
从叶子开始,每个父节点更新 result = max(result, a + b + 1),a/b 分别是来自左、右子树的最长路径长度。返回 max(a, b) 给上一层作为它能向上延伸的最长链。
1 | def solution(root): |
subarraySum(hash trick) O(n)
Given an array of integers nums and an integer k, return the total number of subarrays whose sum equals to k.
A subarray is a contiguous non-empty sequence of elements within an array.
Example 1:
1 | Input: nums = [1,1,1], k = 2 |
Example 2:
1 | Input: nums = [1,2,3], k = 3 |
Constraints:
1 <= nums.length <= 2 * 10^4-1000 <= nums[i] <= 1000-10^7 <= k <= 10^7
跟 findTargetSumWays 思路类似:前缀和 + 哈希。
1 | # O(n^2) |
findUnsortedSubarray(trick) O(n)
Given an integer array nums, you need to find one continuous subarray such that if you only sort this subarray in non-decreasing order, then the whole array will be sorted in non-decreasing order.
Return the shortest such subarray and output its length.
Example 1:
1 | Input: nums = [2,6,4,8,10,9,15] |
Example 2:
1 | Input: nums = [1,2,3,4] |
Example 3:
1 | Input: nums = [1] |
Constraints:
1 <= nums.length <= 10^4-10^5 <= nums[i] <= 10^5
Follow up: Can you solve it in O(n) time complexity?
先从左往右扫,维护当前最大值,发现 nums[i] < cur_max 就更新 right。再从右往左扫,维护当前最小值,发现 nums[i] > cur_min 就更新 left。最终结果 max(right - left + 1, 0)。
1 | def solution(nums): |
mergeTrees(recursive) O(n)
You are given two binary trees root1 and root2.
Imagine that when you put one of them to cover the other, some nodes of the two trees are overlapped while the others are not. You need to merge the two trees into a new binary tree. The merge rule is that if two nodes overlap, then sum node values up as the new value of the merged node. Otherwise, the NOT null node will be used as the node of the new tree.
Return the merged tree.
Note: The merging process must start from the root nodes of both trees.
Example 1:

1 | Input: root1 = [1,3,2,5], root2 = [2,1,3,null,4,null,7] |
Example 2:
1 | Input: root1 = [1], root2 = [1,2] |
Constraints:
The number of nodes in both trees is in the range
[0, 2000].-10^4 <= Node.val <= 10^4
1 | def solution(t1, t2): |
leastInterval(trick) O(n)
You are given an array of CPU tasks, each labeled with a letter from A to Z, and a number n. Each CPU interval can be idle or allow the completion of one task. Tasks can be completed in any order, but there’s a constraint: there has to be a gap of at least n intervals between two tasks with the same label.
Return the minimum number of CPU intervals required to complete all tasks.
Example 1:
Input: tasks = [“A”,”A”,”A”,”B”,”B”,”B”], n = 2
Output: 8
Explanation: A possible sequence is: A -> B -> idle -> A -> B -> idle -> A -> B.
After completing task A, you must wait two intervals before doing A again. The same applies to task B. In the 3^rd interval, neither A nor B can be done, so you idle. By the 4^th interval, you can do A again as 2 intervals have passed.
Example 2:
Input: tasks = [“A”,”C”,”A”,”B”,”D”,”B”], n = 1
Output: 6
Explanation: A possible sequence is: A -> B -> C -> D -> A -> B.
With a cooling interval of 1, you can repeat a task after just one other task.
Example 3:
Input: tasks = [“A”,”A”,”A”, “B”,”B”,”B”], n = 3
Output: 10
Explanation: A possible sequence is: A -> B -> idle -> idle -> A -> B -> idle -> idle -> A -> B.
There are only two types of tasks, A and B, which need to be separated by 3 intervals. This leads to idling twice between repetitions of these tasks.
Constraints:
1 <= tasks.length <= 10^4tasks[i]is an uppercase English letter.0 <= n <= 100
1 | def solution(tasks, n): |
countSubstrings
Given a string s, return the number of palindromic substrings in it.
A string is a palindrome when it reads the same backward as forward.
A substring is a contiguous sequence of characters within the string.
Example 1:
1 | Input: s = "abc" |
Example 2:
1 | Input: s = "aaa" |
Constraints:
1 <= s.length <= 1000sconsists of lowercase English letters.
countSubstrings() O(n^2)
1 | n = len(s) |
countSubstrings(Manacher’s Algorithm?) O(n)
dailyTemperatures(stack) O(n)
Given an array of integers temperatures represents the daily temperatures, return an array answer such that answer[i] is the number of days you have to wait after the i^th day to get a warmer temperature. If there is no future day for which this is possible, keep answer[i] == 0 instead.
Example 1:
1 | Input: temperatures = [73,74,75,71,69,72,76,73] |
Example 2:
1 | Input: temperatures = [30,40,50,60] |
Example 3:
1 | Input: temperatures = [30,60,90] |
Constraints:
1 <= temperatures.length <= 10^530 <= temperatures[i] <= 100
单调栈。把比栈顶小的值入栈;遇到比栈顶大的就不断弹栈,把弹出位置的答案设为 current_position - popped_position。
1 | def solution(T): |