Leetcode 400刷题计划
博主又又又回来了,申请almost done,开始leetcode400刷题计划了,打算前期每天5-10题吧,最近耍了一天,感觉太久没写代码了,A率下降了好多😭,开始回炉重造。
题解:对每个位置i, 考虑i是最低情况时可以组成的最大长方形,那要预处理i左边和右边不能到达的位置(比i还小),复杂度O(N)
if(heights[i] > heights[i - 1]){ lf[i] = i-1; } else { int t = lf[i-1]; while(t != -1 && heights[i] <= heights[t]) { t = lf[t]; } lf[i] = t; }
class Solution { public: string longestPalindrome(string s) { string ans; bool dp[1005][2]; ans = s[0]; int n = s.length(); // length = 1 for(int i = 0; i < n; i++) dp[i][1] = dp[i][0] = 1; // length = k, longest one for(int k = 2; k <= n; k++){ int now = k % 2; for(int ed = n - 1; ed; ed--) { if (ed - k + 1 < 0) break; bool fg = dp[ed - 1][now] && (s[ed] == s[ed - k + 1]); if (fg) { dp[ed][now] = 1; ans = s.substr(ed - k + 1, k); } else { dp[ed][now] = 0; } // printf("%d %d %d %d %c %c\n", k, ed, dp[ed-1][now], dp[ed][now], s[ed], s[ed-k+1]); } } return ans; } };
2024.06.06
Medium::水题, T(N), S(N)
Medium:完全背包,T(N), S(N^2)
Medium:水题, T(NM), S(N)
Medium:利用第5题dp,每个dp为true则ans+1,T(N^2), S(N)
1851. Minimum Interval to Include Each Query
2024.7.7
300. Longest Increasing Subsequence
Medium:最长单调子序列,T(NlogN), S(N)
Medium:Coin Change和变成一半版本,T(N*SUM), S(SUM)
1143. Longest Common Subsequence
Medium:最长公共子序列,水题,T(N^2), S(N^2)
2024.06.12
Medium: 简单DP,T(N), S(N)
Medium: 水题,T(N), S(1)
Medium: 简单DP,T(N), S(N)
class Solution { public: int getSum(int a, int b) { int carry = (a & b) << 1, rest = a ^ b; int ans = 0; while(carry & rest) { int tmp = carry; carry &= rest; carry <<= 1; rest ^= tmp; } return carry | rest; } };
def countBits(n: int) -> list[int]: dp = [0] * (n + 1) offset = 1 for i in range(1, n+1): if offset * 2 == i: offset = i dp[i] = 1 + dp[i - offset] print(i, offset, dp[i]) return dp
2024.06.14 & 2024.0615
Medium:旋转矩阵S(1)要求,for loop模拟位置变换, T(N^2)
Medium:建一个方向数组和边界检查,细节题,S(1), T(NM)
Medium:笔试原题, S(1), T(NM), We can use the first cell of every row and column as a flag. This flag would determine whether a row or column has been set to zero. 注意0行0列特判
Easy: set找重复,S(N), T(N)
Easy: 快速幂,S(1), T(logN)
Easy: 水题
Medium: 水题
Medium:模拟,用map记录位置点的数量
2024.06.16
if(i) dp[i][j] += dp[i - 1][j]; if(i && j && s[i] == t[j] && dp[i - 1][j - 1] <= LLONG_MAX - dp[i][j]) dp[i][j] += dp[i - 1][j - 1];
Hard: 区间DP,DP[i][j]表示扎爆i到j之间气球最大收益,S(N^2) T(N^3)
class Solution { public: int dp[305][305]; int maxCoins(vector<int>& nums) { int n = nums.size(); nums.insert(nums.begin(), 1); nums.push_back(1); for(int len = 1; len <= n; len++) for(int i = 1; i <= n; i++) { int j = i + len - 1; if(j > n) break; for(int k = i; k <= j; k++){ int tmp = nums[k] * nums[i - 1] * nums[j + 1]; if(k > i) tmp += dp[i][k - 1]; if(k < j) tmp += dp[k + 1][j]; dp[i][j] = max(dp[i][j], tmp); } // printf("%d %d %d\n", i, j, dp[i][j]); } return dp[1][n]; } };
10. Regular Expression Matching
Hard: 好题, real hard, S(N^2) T(N^2)
class Solution { public: bool isMatch(string s, string p) { bool dp[25][25]; memset(dp, 0, sizeof(dp)); dp[0][0] = 1; for(int i = 0; i <= s.size(); i++) for(int j = 1; j <= p.size(); j++){ if(p[j - 1] == '*') { dp[i][j] = dp[i][j - 2] | ((i > 0) && dp[i-1][j] & (s[i - 1] == p[j - 2] || p[j - 2] == '.')); } else { dp[i][j] = (i > 0) && (dp[i - 1][j - 1] & (s[i - 1] == p[j - 1] | p[j - 1] == '.')); } cout<<i<<" "<<j<<" "<<dp[i][j]<<endl; } return dp[s.size()][p.size()]; } };
329. Longest Increasing Path in a Matrix
Hard: 四个方向都可以拓展,记忆化搜索,T(N^2), S(N^2)
class Solution { public: int dp[205][205]; int dir[4][2] = {{1,0}, {0, 1}, {-1,0},{0,-1}}; int dfs(int x, int y, int n, int m, vector<vector<int>>& matrix){ if(dp[x][y]) return dp[x][y]; dp[x][y] = 1; int tmp = 0; for(int k = 0; k < 4; k++) { int i = x + dir[k][0], j = y + dir[k][1]; if(i >= 0 && j >= 0 && i < n && j < m && matrix[i][j] < matrix[x][y]) tmp = max(tmp, dfs(i, j, n, m, matrix)); } dp[x][y] += tmp; return dp[x][y]; } int longestIncreasingPath(vector<vector<int>>& matrix) { int n = matrix.size(), m = matrix[0].size(); int ret = 0; for(int i = 0; i < n; i++) for(int j = 0; j < m; j++) if(!dp[i][j]) { ret = max(ret, dfs(i, j, n, m, matrix)); } return ret; } };
2024.06.17
295. Find Median from Data Stream (H) TlogN, SN,好题
维护一个大根堆和一个小根堆,保证两个堆大小相差不超过1,小根堆堆顶大于大根堆堆顶,中位数看堆顶即可
class MedianFinder: import heapq def __init__(self): self.max_h = [] self.min_h = [] self.n1, self.n2 = 0, 0 def addNum(self, num: int) -> None: if self.n1 <= self.n2: if self.n2 and num > self.min_h[0]: x = heapq.heappushpop(self.min_h, num) heapq.heappush(self.max_h, -x) else: heapq.heappush(self.max_h, -num) self.n1 += 1 else: if self.n1 and num < -self.max_h[0]: x = heapq.heappushpop(self.max_h, -num) heapq.heappush(self.min_h, -x) else: heapq.heappush(self.min_h, num) self.n2 += 1 def findMedian(self) -> float: if self.n1 > self.n2: return -self.max_h[0] return (-self.max_h[0] + self.min_h[0]) / 2 # Your MedianFinder object will be instantiated and called as such: # obj = MedianFinder() # obj.addNum(num) # param_2 = obj.findMedian()
621. Task Scheduler (M)TN, SN,好题
额外维护一个队列储存元素到期时间(FIFO),到期加入优先队列
class Solution { public: int cnt[26]; int leastInterval(vector<char>& tasks, int n) { struct fr{ int id, cnt, time; bool operator < (const fr &a)const{ return a.cnt == cnt ? a.id < id : a.cnt > cnt; } }; priority_queue<fr> q; queue<fr> sq; for(int i = 0; i < tasks.size(); i++) cnt[tasks[i] - 'A']++; for(int i = 0; i < 26; i++) if(cnt[i]) {q.push((fr){i, cnt[i], -n-1});} int pos = 0; while(!q.empty() || !sq.empty()) { while(!sq.empty() && sq.front().time == pos) { q.push(sq.front()); sq.pop(); } if(!q.empty()) { fr now = q.top(); cout<<now.id<<endl; q.pop(); now.cnt--; if(now.cnt) { now.time = pos + n + 1; sq.push(now); } } pos++; } return pos; } };
355. Design Twitter (M) 纯模拟
class Twitter { public: int time; struct data{ int tid, idx, pid; bool operator < (const data &a) const { return idx < a.idx; } }; unordered_map <int, priority_queue<data> > qs; unordered_map <int, set<int> > fs; Twitter() { time = 0; } void postTweet(int userId, int tweetId) { if(qs.find(userId) == qs.end()) { priority_queue<data> q; qs[userId] = q; } follow(userId, userId); qs[userId].push((data){tweetId, ++time, userId}); } vector<int> getNewsFeed(int userId) { queue<data> tmp; vector<int> ans; for(int i = 0; i < 10; i++) { data now = (data) {-1, 0, -1}; for(auto ppl: fs[userId]) if(!qs[ppl].empty()){ data tw = qs[ppl].top(); if(tw.idx > now.idx) now = tw; } if(now.tid == -1) break; tmp.push(now); ans.push_back(now.tid); qs[now.pid].pop(); } while(!tmp.empty()) { data a = tmp.front(); tmp.pop(); qs[a.pid].push(a); } return ans; } void follow(int followerId, int followeeId) { if(fs.find(followerId) == fs.end()) { set <int> f; fs[followerId] = f; } fs[followerId].insert(followeeId); } void unfollow(int followerId, int followeeId) { fs[followerId].erase(followeeId); } };
2024.06.28
155. Min Stack:(M) T1, SN
维护一个递减栈,其余元素放另一个栈,那么递减栈栈顶一定最小,POP的时候注意顺序
class MinStack: def __init__(self): self.min_stk = [] self.other_stk = [] def push(self, val: int) -> None: if not self.min_stk or self.min_stk[-1][0] >= val: self.min_stk.append([val, 0]) else: self.min_stk[-1][1] += 1 self.other_stk.append(val) def pop(self) -> None: if self.min_stk[-1][1]: self.other_stk.pop() self.min_stk[-1][1] -= 1 else: self.min_stk.pop() def top(self) -> int: if self.min_stk[-1][1]: return self.other_stk[-1] else: return self.min_stk[-1][0] def getMin(self) -> int: return self.min_stk[-1][0]
739. Daily Temperatures (M) TN, SN
class Solution: def dailyTemperatures(self, temperatures: List[int]) -> List[int]: ret = [0] * len(temperatures) ans = [] for i, x in enumerate(temperatures): tmp = 1 while ans and x > ans[-1][0]: ret[ans[-1][2]] = tmp tmp += ans[-1][1] ans.pop() ans.append([x, tmp, i]) tmp = 1 return ret
853. Car Fleet (M), TNlogN, SN
class Solution: def carFleet(self, target: int, position: List[int], speed: List[int]) -> int: node = [] n = len(position) for i in range(n): node.append([position[i], speed[i]]) node = sorted(node) # print(node) stk = [] for i in range(n): while stk: if stk[-1][1] <= node[i][1]: break t = (node[i][0] - stk[-1][0]) / (stk[-1][1] - node[i][1]) if node[i][0] + t * node[i][1] <= target: stk.pop() else: break stk.append(node[i]) return len(stk)
84. Largest Rectangle in Histogram (H)好题,经典题 TN, SN
找一列竖条中组成的最大长方形,维护一个递增栈,出栈时更新宽度贡献
class Solution: def largestRectangleArea(self, heights: List[int]) -> int: stk = [] ans = 0 for x in heights: if not stk or x > stk[-1][0]: stk.append([x, 1]) else: tmp = 0 while stk and x <= stk[-1][0]: stk[-1][1] += tmp ans = max(ans, stk[-1][0] * stk[-1][1]) tmp = stk[-1][1] # print(ans, stk[-1][0], stk[-1][1]) stk.pop() stk.append([x, tmp+1]) tmp = 0 while stk: stk[-1][1] += tmp ans = max(ans, stk[-1][0] * stk[-1][1]) # print(ans, stk[-1][0], stk[-1][1]) tmp = stk[-1][1] stk.pop() return ans
150. Evaluate Reverse Polish Notation M, TN,SN, 逆波兰式
2024.06.29
153. Find Minimum in Rotated Sorted Array M, TlogN, S1
class Solution: def findMin(self, nums: List[int]) -> int: lf, rg = 0, len(nums) - 1 if nums[0] < nums[rg]: return nums[0] while lf < rg: mid = (lf + rg) // 2 if nums[mid] >= nums[lf]: if nums[mid + 1] < nums[lf]: lf = mid + 1 break lf = mid + 1 else: rg = mid return nums[lf]
33. Search in Rotated Sorted Array M, TlogN, S1
class Solution: def search(self, nums: List[int], target: int) -> int: lf, rg = 0, len(nums) - 1 n = len(nums) idx = 0 if nums[0] > nums[rg]: while lf < rg: mid = (lf + rg) // 2 if nums[mid] >= nums[lf]: if nums[mid + 1] < nums[lf]: lf = mid + 1 break lf = mid + 1 else: rg = mid idx = lf n = len(nums) L, R = 0, n - 1 # print(idx) while L <= R: mid = (L + R) // 2 mm = (mid + idx) % n # print(L, R, mm) if nums[mm] == target: return mm elif nums[mm] < target: L = mid + 1 else: R = mid - 1 return -1
435. Non-overlapping Intervals M, TNlogN, S1, 好题,贪心
class Solution: def eraseOverlapIntervals(self, intervals: List[List[int]]) -> int: array = sorted(intervals, key=lambda x: (x[0], -x[1])) i, n = 0, len(intervals) # print(array) i = 0 while i < n - 1: while i < n - 1 and array[i][1] > array[i+1][0]: if array[i][1] > array[i+1][1]: array.pop(i) else: array.pop(i+1) n -= 1 i += 1 # print(i, array) return len(intervals) - len(array)
1851. Minimum Interval to Include Each Query H, TNlogN, SN, 好题
一个优先队列的滑动窗口问题
class Solution: def minInterval(self, intervals: List[List[int]], queries: List[int]) -> List[int]: ql = [[queries[i], i] for i in range(len(queries))] ql.sort() intervals.sort() idx = 0 pq = [] ret = [-1] * len(ql) # print(ql) # print(intervals) for q in ql: while idx < len(intervals) and intervals[idx][0] <= q[0]: heappush(pq, (intervals[idx][1] - intervals[idx][0] + 1, intervals[idx][1])) idx += 1 # print(q, pq) while pq and pq[0][1] < q[0]: heappop(pq) if pq: ret[q[1]] = pq[0][0] return ret
2024.06.30
167. Two Sum II - Input Array Is Sorted M, TN, S1, 双指针
11. Container With Most Water M, TN, S1, 双指针
class Solution: def maxArea(self, height: List[int]) -> int: i, j = 0, len(height) - 1 ans = 0 while i < j: ans = max(ans, (j-i)*min(height[i], height[j])) if height[i] < height[j]: i += 1 else: j -= 1 return ans
42. Trapping Rain Water H, TN, SN,单调栈,好题
class Solution { public: int trap(vector<int>& height) { int stk[20005], tp = 0; int sum = 0; for(int i = 0; i < height.size(); i++){ if(!tp || height[i] < height[stk[tp]]) stk[++tp] = i; else { while(tp && height[stk[tp]] < height[i]){ int li = min(height[stk[tp-1]], height[i]); if(li > height[stk[tp]]) sum += (li - height[stk[tp]]) * (i - stk[tp-1] - 1); tp--; // cout<<i<<" "<<li<<" "<<stk[tp]<<" "<<sum<<endl; } stk[++tp] = i; } } return sum; } };
15. 3Sum M, TN^2, S1, 双指针(... slow)
class Solution: def threeSum(self, nums: List[int]) -> List[List[int]]: nums = sorted(nums) n = len(nums) ans = [] # print(nums) for i in range(n): j = i + 1 k = n - 1 while j < k: if nums[i] + nums[j] + nums[k] < 0: j += 1 elif nums[i] + nums[j] + nums[k] > 0: k -= 1 elif j < k: t = (nums[i], nums[j], nums[k]) ans.append(t) j += 1 k -= 1 filter_list = list(set(ans)) ret = [list(x) for x in filter_list] return ret
2024.07.01
131. Palindrome Partitioning M: 水题
90. Subsets II M:水题
class Solution: def subsetsWithDup(self, nums: List[int]) -> List[List[int]]: ret = set() n = len(nums) nums.sort() for s in range(1<<n): t = [] for i in range(n): if (1<<i) & s: t.append(nums[i]) ret.add(tuple(t)) return [list(x) for x in list(ret)]
51. N-Queens M:水题
class Solution: def doSolve(self, now: int, n: int, mp: List[str]): if now == n: self.ret.append(mp.copy()) return for i in range(n): if not self.col[i] and not self.sum[i+now] and not self.diff[i - now + n]: self.col[i] = self.sum[i+now] = self.diff[i-now+n] = True t = '.' * i + 'Q' + '.' * (n-i-1) mp.append(t) self.doSolve(now+1, n, mp) mp.pop() self.col[i] = self.sum[i+now] = self.diff[i-now+n] = False def solveNQueens(self, n: int) -> List[List[str]]: self.ret = [] self.col = [False] * n self.sum = [False] * (n<<1) self.diff = [False] * (n<<1) self.doSolve(0, n, []) return self.ret
2024.7.11. sliding window
121. Best Time to Buy and Sell Stock E, T1, S1
3. Longest Substring Without Repeating Characters M, TN, SN
find the length of the longest substring without repeating characters
class Solution: def lengthOfLongestSubstring(self, s: str) -> int: from queue import Queue q = Queue() vis = {} ans = 0 for x in s: if not vis.get(x) or vis[x] == 0: vis[x] = 1 q.put(x) ans = max(q.qsize(), ans) # print(x, ans) else: cnt = 0 while True: t = q.get() vis[t] = 0 # print(t) if t == x: q.put(x) vis[x] = 1 break # cnt += 1 return ans
424. Longest Repeating Character Replacement M, TN, SN
string s & t, You can choose any character of the string and change it to any other uppercase English character. You can perform this operation at most k
times.
Return the length of the longest substring containing the same letter you can get after performing the above operations.
class Solution: def characterReplacement(self, s: str, k: int) -> int: gr = set() for x in s: gr.add(x) ret = 0 if k == 0: ans = 1 for i in range(1, len(s)): if s[i] == s[i-1]: ans += 1 else: ret = max(ret, ans) ans = 1 ret = max(ret, ans) else: from queue import Queue for x in gr: cnt = k q = Queue() for ch in s: if ch != x: if cnt == 0: while q.qsize(): t = q.get() if t != x: break else: cnt -= 1 q.put(ch) ret = max(ret, q.qsize()) return ret
567. Permutation in String M, TN, SN
s1
and s2
, return true
if s2
contains a permutation of s1
, or false
otherwise. (permutation->same # of character)class Solution: def checkInclusion(self, s1: str, s2: str) -> bool: dic = {} for ch in s1: dic[ch] = dic.get(ch, 0) + 1 from queue import Queue q = [] head, tail = 0, 1 ret = 0 for ch in s2: if ch in dic: dic[ch] -= 1 if dic[c] q.put(ch) if q.qsize() == len(s1): return True # print(ch, q.qsize(), dic) else: while not q.empty(): t = q.get() dic[t] += 1 return False
76. Minimum Window Substring H, TN, SN
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. 加强版567,real hard, 定义无用元素a: 不在t中的,在substring中但重复次数>在t中重复次数, 出队:{a}*{not a}{a}* [{not a}..... queue]
class Solution: def minWindow(self, s: str, t: str) -> str: dic = {} for ch in t: dic[ch] = dic.get(ch, 0) + 1 q = [] head, tail = 0, 0 ret = 1e9 ret_s = "" cnt = 0 for ch in s: if ch in dic: dic[ch] -= 1 q.append(ch) tail += 1 if dic[ch] >= 0: cnt += 1 elif dic[ch] < 0: while head < tail: tt = q[head] if tt not in dic: head += 1 elif dic[tt] < 0: head += 1 dic[tt] += 1 else: break # print(ch, cnt) if cnt == len(t): # print('haha', ch, q[head: tail], ret) if tail - head < ret: ret = tail - head ret_s = "" for i in range(head, tail): ret_s += q[i] fg = 0 while head < tail: tt = q[head] if tt not in dic: head += 1 continue if dic[tt] >= 0 and fg: break head += 1 dic[tt] += 1 if dic[tt] >= 1: cnt -= 1 fg = 1 else: if tail - head > 0: q.append(ch) tail += 1 # print(ch, dic, q[head: tail], cnt, ret) return ret_s
239. Sliding Window Maximum H, TN, SN
第一想法,TNlogN, sortedlist(logN取出优先队列);TN:维护一个双向队列,保持递减,队首元素要在窗口内,可以保证这个是当前window Max
class Solution: def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]: from sortedcontainers import SortedList sl = SortedList() ret = [] for i in range(k): sl.add(nums[i]) ret.append(sl[-1]) for i in range(k, len(nums)): sl.add(nums[i]) sl.remove(nums[i-k]) ret.append(sl[-1]) # print(sl) return ret
class Solution: def minWindow(self, s: str, t: str) -> str: dic = {} for ch in t: dic[ch] = dic.get(ch, 0) + 1 q = [] head, tail = 0, 0 ret = 1e9 ret_s = "" cnt = 0 for ch in s: if ch in dic: dic[ch] -= 1 q.append(ch) tail += 1 if dic[ch] >= 0: cnt += 1 elif dic[ch] < 0: while head < tail: tt = q[head] if tt not in dic: head += 1 elif dic[tt] < 0: head += 1 dic[tt] += 1 else: break # print(ch, cnt) if cnt == len(t): # print('haha', ch, q[head: tail], ret) if tail - head < ret: ret = tail - head ret_s = "" for i in range(head, tail): ret_s += q[i] fg = 0 while head < tail: tt = q[head] if tt not in dic: head += 1 continue if dic[tt] >= 0 and fg: break head += 1 dic[tt] += 1 if dic[tt] >= 1: cnt -= 1 fg = 1 else: if tail - head > 0: q.append(ch) tail += 1 # print(ch, dic, q[head: tail], cnt, ret) return ret_s
2024.8.26 & 2024.8.27
143. Reorder List. M, TN, S1, backtrace
class Solution { public: ListNode *hh; void reorder(ListNode* lst, ListNode* now){ if (now->next != nullptr) reorder(now, now->next); if(hh == nullptr || hh->next == nullptr) return; if(lst != nullptr) lst->next = nullptr; // cout<<(now->val)<<" "; // cout<<(hh->val)<<"\n"; now->next = hh->next; hh->next = now; hh = now->next; return; } void reorderList(ListNode* head) { hh = head; reorder(nullptr, head); for(auto t = head; t->next != nullptr; t = t->next) cout<<(t->val)<<"\n"; } };
19. Remove Nth Node From End of List. M, TN, S1, two pointer
138. Copy List with Random Pointer M, TN, SN, hash table
""" # Definition for a Node. class Node: def __init__(self, x: int, next: 'Node' = None, random: 'Node' = None): self.val = int(x) self.next = next self.random = random """ class Solution: from collections import defaultdict def copyRandomList(self, head: 'Optional[Node]') -> 'Optional[Node]': if not head: return None mp = defaultdict() current = head # First pass: Create the mapping from the original nodes to their copies while current: new_node = Node(current.val) mp[current] = new_node current = current.next # Second pass: Set the next and random pointers for the copied nodes current = head while current: mp[current].next = mp.get(current.next) mp[current].random = mp.get(current.random) current = current.next return mp[head]
235. Lowest Common Ancestor of a Binary Search Tree M, TN, S1
class Solution: def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': anc = {} dep = {} def dfs(now, prev): anc[now] = [-1] * 20 if prev is not None: dep[now] = dep[prev] + 1 anc[now][0] = prev else: dep[now] = 0 for u in range(1, 20): if anc[now][u-1] in anc: anc[now][u] = anc[anc[now][u-1]][u-1] if now.left: dfs(now.left, now) if now.right: dfs(now.right, now) dfs(root, None) if dep[p] < dep[q]: p, q = q, p for u in range(19, -1, -1): if anc[p][u] != -1 and dep[anc[p][u]] >= dep[q]: p = anc[p][u] if p == q: return p for u in range(19, -1, -1): if anc[p][u] != anc[q][u]: p = anc[p][u] q = anc[q][u] return anc[p][0]
class Solution: def lowestCommonAncestor(self, root: 'TreeNode', p: 'TreeNode', q: 'TreeNode') -> 'TreeNode': if p.val == root.val or q.val == root.val: return root if p.val < root.val and q.val < root.val: return self.lowestCommonAncestor(root.left, p, q) if p.val > root.val and q.val > root.val: return self.lowestCommonAncestor(root.right, p, q) return root
102. Binary Tree Level Order Traversal. 199. Binary Tree Right Side View M, TN, SN, same approach
# Definition for a binary tree node. # class TreeNode: # def __init__(self, val=0, left=None, right=None): # self.val = val # self.left = left # self.right = right class Solution: def rightSideView(self, root: Optional[TreeNode]) -> List[int]: dep = {} nodes = {} max_dep = 0 def dfs(now, prev): nonlocal dep, nodes, max_dep if prev: dep[now] = dep[prev] + 1 else: dep[now] = 0 max_dep = max(max_dep, dep[now]) if dep[now] in nodes: nodes[dep[now]].append(now.val) else: nodes[dep[now]] = [now.val] if now.left: dfs(now.left, now) if now.right: dfs(now.right, now) ret = [] if root: dfs(root, None) ret = [nodes[d][-1] for d in range(max_dep+1)] return ret
146. LRU Cache M,细节比较多
class Node: def __init__(self, key = None, val = None, prev = None, nxt = None): self.nxt = nxt self.prev = prev self.val = val self.key = key class LRUCache: def __init__(self, capacity: int): self.head = Node() self.head.val = -1 self.tail = None self.table = {} self.size = 0 self.cap = capacity def get(self, key: int) -> int: if key not in self.table: return -1 val = self.table[key].val self.put(key, val) return val def put(self, key: int, value: int) -> None: if key in self.table: old_node = self.table[key] old_node.val = value # print(old_node) old_node.prev.nxt = old_node.nxt if old_node.nxt: old_node.nxt.prev = old_node.prev elif old_node.prev != self.head: self.tail = old_node.prev else: self.tail = old_node old_node.nxt = self.head.nxt old_node.prev = self.head self.head.nxt = old_node if old_node.nxt: old_node.nxt.prev = old_node else: if self.size == self.cap: # print(self.size, self.cap, self.table, self.tail.key) del self.table[self.tail.key] self.tail.prev.nxt = None self.size -= 1 if self.tail.prev != self.head: self.tail = self.tail.prev new_node = Node(key, value, self.head, self.head.nxt) self.head.nxt = new_node self.size += 1 self.table[key] = new_node if self.tail == None or new_node.nxt == None: self.tail = new_node elif new_node.nxt: new_node.nxt.prev = new_node # Your LRUCache object will be instantiated and called as such: # obj = LRUCache(capacity) # param_1 = obj.get(key) # obj.put(key,value)
23. Merge k Sorted Lists H, 优先队列,但实际上可以少开extra space,不过同一个数量级
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: ListNode* mergeKLists(vector<ListNode*>& lists) { priority_queue<int, vector<int>, greater<int> > q; for(int i = 0; i < lists.size(); i++){ ListNode *head = lists[i]; while(head != nullptr) { q.push(head->val); head = head->next; } } ListNode *ret, *now; ret = new ListNode(); now = ret; while(!q.empty()){ int val = q.top(); q.pop(); ListNode *node = new ListNode(val); now->next = node; now = now->next; } return ret->next; } };
25. Reverse Nodes in k-Group H,dfs
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode() : val(0), next(nullptr) {} * ListNode(int x) : val(x), next(nullptr) {} * ListNode(int x, ListNode *next) : val(x), next(next) {} * }; */ class Solution { public: ListNode *newhead, *oldhead; pair<ListNode*, ListNode*> reversePart(int dep, int k, ListNode* now, ListNode* pre){ if(dep == k) { ListNode *tmp = now->next; now->next = pre; pair<ListNode*, ListNode*> ret(now, tmp); return ret; } cout<<k<<" "<<now->val<<endl; pair<ListNode*, ListNode*> ret = reversePart(dep + 1, k, now->next, now); now->next = pre; return ret; } ListNode* reverseKGroup(ListNode* head, int k) { ListNode *now = head, *oldnow = nullptr; int sz = 0, cnt = 0; while(now != nullptr){now = now->next;sz++;} if(sz < k) return head; int t = sz / k; pair<ListNode*, ListNode*> ret; now = head; while(cnt < t){ cnt++; ret = reversePart(1, k, now, nullptr); if(oldnow != nullptr) oldnow->next = ret.first; oldnow = now; now = ret.second; if(cnt == 1) head = ret.first; } if(sz % k) oldnow->next = ret.second; return head; } };