# Leetcode [TOC] ## 16. 3Sum Closest - 在list中找 3 個數使得總合越接近 $target$ - **Attempt 1:** - 暴力法:三層 $for$ 迴圈 - $for\ i\in (1,n)$ $for\ j\in (i+1,n)$ $for\ k\in (j+1,n)$ - $O(n^3)$ - **Attempt 2:** - 先 $sort$ - $k$ 用 $\text{binary search}$ - $for\ i\in (1,n)$ $for\ j\in (i+1,n)$ $\text{binary search}$ 後面陣列 - $\text{binary search}$ 要找最接近的 若 $num[mid] \neq target$ 先 search 後比較 $num[mid]$ 和 $num[searched]$ 哪個跟 $target$ 差較小 - $O(n^2logn)$ - **Solution 1:** - $j$ 也用 $\text{binary search}$ - 找到 $k$ 後 - 下個 $j$ 也用 $\text{binary search}$ - $O(nlog^2n)$ > Runtime: 60 ms, faster than **98.70%** of Python online submissions for 3Sum Closest. Memory Usage: 11.9 MB, less than **12.90%** of Python online submissions for 3Sum Closest. - **Solution 2:** - 若目前 $sum$ 小於 $target$,$j$ 才往右找 目前 $sum$ 大於 $target$,$k$ 才往左找 ## 22. Generate Parentheses - $Catalan\ Number$ 1. Stack permutation 2. valid binary search tree 3. valid parentheses - Binary Search Tree $T(n) = T(i) + T(1) + T(n-i-1),i \in [0,n]$ 第n顆數= 左子樹 + root + 右子樹 - Parentheses $T(n) = (T(i))T(n-i-1), i \in [0,n]$ 第n個排列 = $($ 左子樹 $)$ 右子樹 - **Time complexity:** $O(\frac{4^n}{\sqrt{n}})$ ## 32. Longest Valid Parentheses - 找出最長的合法的括號子字串(substring) - **Solution 1:** - 若 $stack$ 為空但要$pop$,紀錄不合法位置 - 若有元素沒有被 $pop$ 掉,也是不合法位置 > Runtime: 36 ms, faster than **76.30%** of Python online submissions for Longest Valid Parentheses. Memory Usage: 12.8 MB, less than **14.29%** of Python online submissions for Longest Valid Parentheses. ## 42. Trapping Rain Water - 給一List,判斷可以儲存多少單位的水(凹陷下去的面積) - **Attempt 1:** - 若 $num[i-1],num[i+1]< num[i]$ (突起處) - 則計算前一個突起處到這裡的總和 - 突起處更新 > **WA** 若左右兩邊有更高的突起處,此突起處會被淹沒 - **Solution 1:** - $maxFront[i] = max(nums[0:i])$ - $maxEnd[i] = max(nums[i:n])$ - 得知目前最左邊的最大值和最右邊的最大值 取兩個中較小的為可能的積水高度 - $flow = min(maxFront[i], maxEnd[i])-nums[i]$ > Runtime: 40 ms, faster than **54.80%** of Python online submissions for Trapping Rain Water. Memory Usage: 12.6 MB, less than **8.22%** of Python online submissions for Trapping Rain Water. ## 55. Jump Game - 是否可以從起點跳到終點,$list[i]$ 儲存此格可跳的最大步數 - **Solution 1:** - 計算 $target = max(target, i+list[i])$ - $target$ 為目前要去的最遠的目的點 - 如果最後 $target>=len(list)$ 則為 True > Runtime: 72 ms, faster than **76.72%** of Python online submissions for Jump Game. Memory Usage: 13.2 MB, less than **77.14%** of Python online submissions for Jump Game. ## 75. Sort Colors in-place: 不需要data structure儲存 - 2-pass sorting: 用一個for迴圈紀錄0,1,2出現幾次,再用一個for迴圈輸出對應的0,1,2 - 1-pass sorting: 紀錄第一個1的位置及第一個2的位置,若$nums[i]==1$則跟第一個2的位置交換;若$nums[i]==0$則跟第一個1的位置交換,再把1和第一個2的位置交換 (注意第一個1及第一個2是否有出現) ## 84. Largest Rectangle in Histogram - 找出最大面積 ![](https://assets.leetcode.com/uploads/2018/10/12/histogram_area.png) - **First Attemp** - 紀錄陣列 $i$ 到 $j$ 之間的最小值 - 用 $n\times n$ 矩陣儲存 - 計算 $n\times n$ 的面積最大值 - 重複性高、占空間 | | 2 | 1 | 5 | 6 | 2 | 3 | | --- | --- | --- | --- | --- | --- | --- | | 2 | 2 | 1 | 1 | 1 | 1 | 1 | | 1 | | 1 | 1 | 1 | 1 | 1 | | 5 | | | 5 | 5 | 2 | 2 | | 6 | | | | 6 | 2 | 2 | | 2 | | | | | 2 | 2 | | 3 | | | | | | 3 | > Memory Limit Exceeded - **Second Attemp** - 用 `min` 直接找 $i$ 到 $j$ 之間的最小值 - 不用矩陣空間儲存 - 仍是 $O(n^2)$ 執行時間 > Time Limit Exceeded > `[0,1,2,3,.....]` - **Third Attemp** - $Divide\ and\ conquer$ - 找出目前陣列中最小的值的index ($minIndex$) - $maxArea(startIndex,endIndex)=\begin{cases} len(\text{heights})\times min(\text{heights}) \\ maxArea(startIndex, minIndex-1) \\ maxArea(minIndex+1, endIndex) \end{cases}$ - worse case: 全部陣列數都一樣 $O(n^2)$ > Time Limit Exceeded > `[1,1,1,1,1,1,....,1]` - **Solution 1** - [ref](https://www.cnblogs.com/grandyang/p/4322653.html) - 只處理 $heights[i+1] < heights[i]$ 的情形 - 若 $heights[i+1] < heights[i]$ 令 $j$ 為從 $i$ 開始往回推到 $0$ 如果 $heights[j] < heights[i]$ 則算出此面積值 - $Time\ complexity:$ - $heights[i+1] > heights[i]$: $m$ 次 $heights[i+1] < heights[i]$: $n$ 次 $heights[i+1] == heights[i]$: $o$ 次 - $O(n+m)$ - $O(n)$ - **Solution 2** - [ref](https://leetcode.com/problems/largest-rectangle-in-histogram/discuss/510500/python-using-stack) - 與 **solution 1** 類似 只處理 $heights[i+1] < heights[i]$ 的情形 - 用 $stack$ 存遞增數列 - 若stack頂端的數`stack[-1]` 大於 $heights[i]$ 則 pop stack 頂端的index (index: $k$) 計算現在 stack 頂端的 index 跟 $k$ 之間的面積 - 優點:不用往回搜尋 $heights[j] < heights[i]$ 直接從 stack 中 pop 取得 ## 94. Binary Tree Inorder Traversal - recursive解: 左子樹+root.val+右子樹 - iterative解: 一直往左子樹走(while迴圈)(儲存root位址),輸出root.val,往右子樹走一次 $Algorithm:Morris\ Traversal$ ```python= while stack or root: while root: stack.append(root) root = root.left root = stack.pop() res.append(root.val) root = root.right ``` - **Attempt:** - while - ~~node為stack最上面元素~~ - 遞迴走左子樹 - pop出stack元素 - 走右子樹 - **會造成每次pop後再往左子樹走** - **解法:** - 同時用 `cur` 跟 `stack` ## 97. Interleaving String - $s3$ 是否可以由 $s1,s2$ 的子序列組合成 - **Attempt 1:** - recursive: - 若遇到相同字母則嘗試選擇 $s1$ 或 $s2$ > **TLE** - **Attempt 2:** - 看 $s1,s2$ 是否為 $s3$ 的子序列 > **WA** > `s1="ab"` > `s2="ab"` > `s3="abac"` > 兩者都是 `s3` 子序列可是不能組成 `s3` - **Attempt 3:** - 用 $\text{dictionary}$ - 如果此字母的 count 小於零則 False > **WA** > 無法保證`s1`中順序 > `s1="aabd"` > `s2="abdc"` > `s3="aabdbadc"` - **Solution 1:** - $DP$ - `s1` 為 $x$ 軸,`s2` 為 $y$ 軸 - 從 $[0,0]$ 到 $[m,n]$ 的任何路徑即為 `s1`, `s2` 的 interleaving - `s3="aadbbcbcac"` - | | 0 | d | b | b | c | a | | --- | --- | --- | --- | --- | --- | --- | | 0 | 1 | | | | | | | a | 1 | | | | | | | a | 1 | 1 | 1 | 1 | 1 | | | b | | | | | 1 | | | c | | | | | 1 | 1 | | c | | | | | | 1 | - return $dp[m][n]$ > Runtime: 32 ms, faster than **39.78%** of Python online submissions for Interleaving String. Memory Usage: 11.9 MB, less than **12.50%** of Python online submissions for Interleaving String. ## 120. Triangle - ```python [ [2], [3,4], [6,5,7], [4,1,8,3] ] ``` - 找到 top 到 bottom 的最短路徑 - **Attemp 1:** - 遞迴解法 - 比較左下三角形和右下三角形的最短路徑 加上頂端的值 回傳 > **TLE** - **Solution 1:** - $DP$ - 用 $minSum$ 陣列 ```python [ [0], [0,0], [0,0,0], [0,0,0,0] ] ``` 存取目前路徑最小值 $minSum[i,j]=triangle[i,j]+min(minSum[i+1,j],minSum[i+1,j+1])$ - 記憶體用量大 - **Solution 2:** - 直接複寫input $triangle$ 矩陣 - 記憶體用量差不多 - **Solution 3:** - 用一維陣列 $minSum=triangle[-1]$ 存取目前最小值 - $minSum[j]=triangle[i,j]+min(minSum[j],minSum[j+1])$ - 記憶體用量較少 - $j$ 須從小到大更新,不然新的會覆寫原本的資料 > Runtime: 36 ms, faster than **98.92%** of Python online submissions for Triangle. > Memory Usage: 12.3 MB, less than **50.00%** of Python online submissions for Triangle. ## 124. Binary Tree Maximum Path Sum - 找總和最大的連續子路徑,不得為空,可以跨左右子樹 - **Solution 1:** - `max(None, -3) = -3` - 若沒有 node 可以 return `None` - 用 `self.res` 儲存現在最大的路徑總和 - $search(node)$ 函數:回傳含有 $node$ 的最大路徑總和 - 函數內比較 $max(node.val+left, node.val+right, node.val+left+right)$ - 如果比 `self.res` 大則更新 - return $max(node.val+left, node.val+right)$ > Runtime: 76 ms, faster than **90.66%** of Python online submissions for Binary Tree Maximum Path Sum. Memory Usage: 25.9 MB, less than **32.50** of Python online submissions for Binary Tree Maximum Path Sum. ## 141. Linked List Cycle - 找 linked list 有沒有 cycle - **Solution 1:** - 用 $dictionary$ 存 node 跟對應的 index - `nodeDict[node] = index` - 檢查若 `node` 在 `nodeDict` 中,回傳 `True` (有cycle) - 直到`node.next == null` > 挑戰用 $O(1)$ 的記憶體 - **Solution 2:** - 用兩個 $pointer$ - 一個一次走兩個一個一次走一格 - 若兩個走到一樣的 node,則 `True` ## 144. Binary Tree Preorder Traversal - 類似**94** - 往左找時,每次append(root.val) ```python= while stack or root: while root: res.append(root.val) stack.append(root) root = root.left root = stack.pop() root = root.right ``` ## 145. Binary Tree Postorder Traversal - 類似 **94**及**145** - $Algorithm:Morris\ Traversal$ 每次都先走左子樹,此題stack中存右子樹的root,但是走右子樹。每走到一個點時存入值到 $res$ ,但 $res$ 最後要反向輸出 (因為此時存入數字是中右左) ## 200. Number of Islands - 找出二維矩陣中有幾個Islands (相鄰的 $1$ 為一個島) - **Attempt 1:** - 用兩個 $queue$ - 一個紀錄矩陣中 $1$ 的點 一個紀錄 $0$ 的點 - 如果 $queue_1$ 不為空則 $pop$ 否則 $pop\ queue_0$ - 若 $queue_1$ 為空則紀錄島的數量加一 > 例外: > 0 1 0 > 1 0 1 > 0 1 0 > 跑過點 $(0,0)$ 時同時紀錄 $(0,1), (1,0)$ > 雖然 $(0,1)$ 被 $pop$ 了且為一個 island > 但 $queue_1$ 仍不為空 (還有 $(1,0)$) - **Attempt 2:** - 用三個 $queue(queue_1, queue_0, queue)$ - 當 $pop\ queue_1$ 時 $BFS$ 用 $queue$ 搜尋地圖 - 搜尋到 $queue$ 中沒有值為止 - 輸出 $count$ 加一 (表示此區域搜尋完畢) 且搜尋過的區域標示為 $visited$ > 例外: > 0 1 > 1 1 > 若有點在 $queue_1$ 中 (已被標為 $visited$ ) > 在 $queue$ 的搜尋時就無法找到此點 > 此例中在 $(0,0)$ 點時,同時加入 $(1,0),(0,1)$ 點 > 在 $(0,1)$ 點搜尋時無法找到 $(1,0)$ 點 - **Solution 1:** - 對 <font color=red>$queue_0$</font> $pop$ 時做修改 - **Attempt 2** 時如果上下左右有點則都加入 $queue$ - **Solution 1** 修改為,一次只加入一個點 (原先全部 $if$ 改為 $elif$) > Runtime: **70.69%** > Memory: **18.92%** - **Solution 2:** - 用兩層 $for$ 迴圈 - 如果遇到 $1$ 則 $DFS$,找過的點標記為 $visited$ > Runtime 較佳 ## 201. Bitwise AND of Numbers Range - 從 $m$ 到 $n$ 每個數字的每個 bit 做 $AND$ - 5=101 6=110 7=100 return 100 = 4 - **Solution 1:** - 如果有零則全部為零 - 若 $m=n$ 則 return $m$ - 若第 $k$ bit要為 $1$,則 $2^{k-1}\leq m,n\leq 2^k-1$ - 檢查 $m,n$ 是否在範圍內 - 如果是則減掉 $2^{k-1}$ 再繼續檢查 > Runtime: 48 ms, faster than **58.02%** of Python online submissions for Bitwise AND of Numbers Range. Memory Usage: 11.8 MB, less than **50.00%** of Python online submissions for Bitwise AND of Numbers Range. ## 211. Add and Search Word - Data structure design - 找單字在不在字典裡,若字為`.` 則可用任何字替代 - **Attempt 1:** - 用`a-z`替換`.`,再搜尋是否在$\text{dictionary}$ 中 - 遞迴 - input 為 `(pre, post)` - 找 `pre+post` 是否在字典中 - $pre'=pre+post[:i]+alpha(a-z)$ $post'=post[i+1:]$ > **TLE** > 每個字都替換的時間複雜度是 $O(26^m)$,$m$ 是 `.` 個數 - **Attempt 2:** - 建立字典時用`.` 替換所有字母 - 類似前面遞迴法 - input 為 `(pre, post)` - $pre'_1=pre+"."$ $post'_1=post[1:]$ $pre'_2=pre+post[0]$ $post'_2=post[1:]$ > **MLE** > 字母長度 $m$ 就有 $2^m$ 個單字 (每個字母替換成`.`與否) - **Solution 1:** - 用 $len(\text{word})$ 當作字典 $\text{key}$ - 從長度一樣的字找匹配的單字 - 若有字母不同且 $\text{word}$ 不為`.`則檢查下個長度相同的字 > Runtime: 144 ms, faster than **95.63%** of Python online submissions for Add and Search Word - Data structure design. Memory Usage: 22.3 MB, less than **92.86%** of Python online submissions for Add and Search Word - Data structure design. ## 279. Perfect Squares - 找到整數 $n$ 最少可以用多少平方數相加而成 - **Attempt 1:** - $DP$ - $dp[n] = \sum_{k=0}^{\frac{n-1}{2}} dp[k]+dp[n-1-k]$ > **TLE** > $O(n^2)$ - **Solution 1:** - $DP$ - $dp[n]=min(dp[n], dp[n-k^2]+1)$ $k$ 是比 $n$ 小的平方數的根 - **Solution 2:** - $Lagrange's\ four-square\ theorem$ - 任何數都可由四個數的平方和組成 - $n=a^2+b^2+c^2+d^2$ - **Solution 3:** - $BFS$ - 起始 $queue=[(n,1)]$ (目前要平方的數字,目前的平方數) - 每次 $(num, k)=queue.pop(0)$ - 若 $num$ 為平方數,則 return $k$ - 測試為平方數 - `if (num ** 0.5) == int(num ** 0.5)` - 否則 $for\ i\in[1,\sqrt{num}]$ $queue$ 加入 $(num-i^2,k+1)$ ## 300. Longest Increasing Subsequence - 用1維list儲存每個元素目前為止最長的subsequence長度 - 若第i個元素$nums[i] > nums[j]$,則記錄下來,且紀錄為 $list[j]+1$,檢查所有 $j<i$ 的元素中 $list[j]+1$ 的最大值 - return $list$ 中的最大值 - $O(n^2)$ - $Robinson-Schensted-Knuth\ Algorithm$ - 用一個遞增$S$儲存 - 如果$S$中有元素比目前的$nums[i]$還大,則更新index最小的$k$,其中$S[k]> nums[i]$ 1. 初始化: $s=[nums[0]]$ 2. $for\ i \in [1,n]$ $k = binarySearch(s)\ \ //\ k\ is\ the\ smallest\ index\ such\ that\ s[k] > nums[i]$ $if\ k\ doesn't\ exist:$ $\ \ \ \ length=length+ 1$ $\ \ \ \ s.push(nums[i])$ $else:$ $\ \ \ \ s[k]=nums[i]$ $return\ length$ - $O(nlogn)$ - example: [0, 8, 4, 12, 2] - i = 1: [0,8] - i = 2: [0,<font color=red>4</font>] - i = 3: [0,4,<font color=red>12</font>] - i = 4: [0,<font color=red>2</font>,12] ## 304. Range Sum Query 2D - Immutable - 求矩陣 $(x_1,y_1)$ 到 $(x_2,y_2)$ 的和 - **Solution 1:** - 用矩陣紀錄 $x_1,...,x_n$ 累積的和 - 如果要求 $x_i$ 到 $x_j$ 的和,則計算 $m[j]-m[i]$ - 二維: $m[i,j]=m[i-1,j]+m[i,j-1]-m[i-1,j-1]$ - 集合相加減掉交集 > $O(nm)$ > Time: 79.77% > Memory: 14.29% ## 337. House Robber III - 找出不相鄰的node和最大 - **Solution 1:** - 遞迴 - $f$ return [不含node最大值, 含node最大值] - 不含node最大值:左子樹最大+右子樹最大 - 含node最大值:`node.val`+左子樹不含`node.left`最大+右子樹不含`node.right`最大 - $max(f(root))$ > Runtime: 32 ms, faster than **94.93%** of Python online submissions for House Robber III. Memory Usage: 16 MB, less than **42.86%** of Python online submissions for House Robber III. ## 382. Linked List Random Node - [Reservoir sampling](https://zh.wikipedia.org/wiki/%E6%B0%B4%E5%A1%98%E6%8A%BD%E6%A8%A3) - $\frac{1}{i}\frac{i}{i+1}\frac{i+1}{i+2}...\frac{n-1}{n} = \frac{1}{n}$ random ```python= # random: return random number in [0,1] random.random() ``` ## 395. Longest Substring with At Least K Repeating Characters - 子字串中每個字母都出現至少 $k$ 次 - **Attemp 1:** - $i\in [1,n]$ - $j\in[i,1]$ - 檢查第 $[j:i]$ 個子字串 - $O(n^2)$ > TLE > - **Solution 1:** - 若某個字出現 $k$ 次才檢查 $j\in[i,1]$ > runtime: **5.31%** - **Solution 2:** - 若某個字出現次數小於 $k$ - 則用此字母 $split$ - 遞迴直到不能 $split$ ## 416. Partition Equal Subset Sum - $target = \frac{sum(nums)}{2}$ - 令 $S[1,target]$ 為 $nums[1:i]$ 所有可能組合出的$sum$ 若$S_j$ 為 $True$ 則表示可以組合出, $False$ 表不能,$\forall j \in[1:target]$ - $for\ i\ \in\ [1,len(nums)]$ $\ \ for\ element \in\ S$ $\ \ \ \ S_{element+nums[i]} = True$ - Example: | i | nums | S | | -------- | -------- | -------- | | 1 | 1 | {0,<font color=red>1(0+1)</font>} | | 2 | 5 | {0,1,<font color=red>5(0+5)</font>, <font color=red>6(1+5)</font>} | | 3 | 11 | {0,1,5,6,<font color=red>**11**~~, 12, 16, 17~~</font>} | | 4 | 5 | {0,1,5,6,**11**~~,12,16,17,~~<font color=red>~~10,21,22~~</font>} | > ~~deleted numbers~~: more than $target$ - **Time Complexity:**$O(n\times target)$ ## 450. Delete Node in a BST - 搜尋BST是否有 $key$ - 若有則刪除 - **Solution 1:** ```graphviz graph graphname { 3 -- 1; 3 -- 5; 1 -- null1; 1 -- 2; 5 -- 4; 5 -- null2; } ``` - 若 $key$ 為 3 (`node = 3`) - 則讓右子樹變成 `newRoot` - `newRoot.left = node.left` ($3$ 的左子樹直接當 $5$ 的左子樹) - $4$ 為孤兒 - <font color=red>孤兒必比 $3$ 的左子樹都大且比 $5$ 小</font> - 孤兒接在 $3$ 的左子樹最右邊 > 因為是 BST 所以只要 $O(\text{log }n)$ 的搜尋時間 (找比 $key$ 大或小的子樹) > 取代左子樹也是最多為 tree 的高度的搜尋時間 > 時間 (80.23%) > 用遞迴:記憶體空間耗費大 (6.67%) - **Solution 2:** - 找到右子樹的最小值替換成刪掉的節點 ## 454. 4Sum II naive: $O(n^4)$ D as dict: $O(n^3)$ AB as dict: $O(n^2)$ - binary search不只要找到,要計算次數,所以用dict較佳 binarySearch: ```python= s = [1,2,3,4,5,6] current = 2 l = 0 r = len(s) - 1 found = False while l <= r and not found: mid = (l+r) // 2 if s[mid] == current: found = True elif s[mid] < current: l = mid + 1 else: r = mid - 1 print(found) ``` ## 486. Predict the Winner - 2 個 player,每 round 每個 player 可以從陣列頭或尾選擇數 - 選到數的總額最多的勝 - naive: $O(2^n)$ ($n$ 為陣列長度) DP: $O(n^2)$ - DP做法 1. 建立 $n\times n$ 矩陣 其中 $[i][j]$ 為計算陣列 $i$ 到 $j$ 的兩個 player 的 payoff 2. $\text{first player payoff [i][j]=}\begin{cases} \text{nums}[i] + \text{second player payoff [i+1][j]}\\ \text{nums}[j] + \text{second player payoff [i][j-1]} \end{cases}$ 3. 決定 $\text{first player}$ 的策略後 算出 $\text{second player}$ 的 $\text{payoff}$ $\text{second player payoff [i][j]=}\begin{cases} \text{first player payoff [i+1][j]}\\ \text{first player payoff [i][j-1]} \end{cases}$ > $i,j$ 是矩陣 index - 因為 iterater 是 $(0,1), (1,2),(2,3),...,(0,3)$計算 將 $i,j$ 轉為 $i =start \\ j = start+offset$ iterate $start, offset$ ## 520. Detect Capital - 偵測合法大小寫 - **Solution 1:** - $if$ 判斷 - **Solution 2:** - 列出合法大小寫 - 全大寫 - 全小寫 - 首大寫 - 看 `word` 是否在其中 ## 664. Strange Printer - 一次只能印一個字母 (起始和結束位置可變),最少需要印幾次 - **Attempt 1:** - 印出橫跨最大範圍的字母 - 例外:`babcabac` - 印出 `b`: - `bbbbbb..` - `baaaab..` - `babbab..` - `babcab..` - `babcaba.` - `babcabac` - 正解: - `bbb.....` - `bab.....` - `babccccc` - `babcaaac` - `babcabac` - **Attempt 2:** - $DP$ - $matrix(i,j)$ 為 $s$ 從 $i$ 到 $j$ 的最小列印次數 - 如果 $s(i) == s(j)$ 則 $matrix(i,j)=matrix(i,j-1)$ eg. `aba` - 如果 $s(i) != s(j)$ $min_k(matrix(i,k)+matrix(k+1,j))$ > **WA** > `"dddccbdbababaddcbcaabdbdddcccddbbaabddb"` - **Solution 1:** - $DP$ - 如果 $s(i) == s(j)$ $matrix(i,j)=min_k(matrix(i,k-1)+matrix(k+1,j))$ > Runtime: 376 ms, faster than **87.50%** of Python online submissions for Strange Printer. Memory Usage: 16 MB, less than **12.50%** of Python online submissions for Strange Printer. > $O(n^3)$ ## 670. Maximum Swap - $num[i]$ 只跟 $num[i+1:len(num)-1]$ 中最大的數交換 確保較大的數在越高位 1. 計算 $maxIndex[i]$ 定義為在 $i$ 到 $len(num)-1$ 中最大值的index,從 $len(num)-1$ 到 $0$,時間複雜度為 $O(n)$ (若最大值有多個,選最後出現那個) 3. 從 $i=0$ 開始,與其 $maxIndex[i]$ 交換,比較何者較大。 時間複雜度為 $O(n)$ ## 698. Partition to K Equal Sum Subsets - 每個subset的總和是 `sum(nums)/k` - ## 729. My Calendar I - 給定多個 $[start, end]$,判斷此區間是否已被佔用 - **Solution 1:** - 用list儲存所有 $start, end$ - 如果有重複的就刪掉 - 初始:$[0,10^9]$ - 判斷:$[0,d_1, d_2, ...,d_{n-1}, d_n,10^9]$ - 判斷兩條線是否重合:一條end是否比另一條start小 - 重複比較是否重合 - $(d_1,d_n)$ - $(d_2,d_{n-1})$ - 但會輪流是合法/非法範圍 - 更新: - 如果有一樣的數字則更新為新的範圍 - 否則新增到list中 - $set$ 概念 > Runtime: 1628 ms, faster than **7.22%** of Python online submissions for My Calendar I. Memory Usage: 12.2 MB, less than **100.00%** of Python online submissions for My Calendar I. - **Solution 2:** - $\text{binary search}$ ## 752. Open the Lock - 四位數密碼一次只能上下調整一位數 - 給定不能調到的密碼 $deadends$ (若遇到則不能繼續調整) - 最少要多少步才能調到 $target$ - **Solution 1:** - 用 $BFS$ - 兩個 $queue$ - 一個儲存密碼 - 一個儲存用了幾步 - 每次調整一位數的可能存進 $queue$ - 且額外用一個 $\text{dictionary}$ 儲存已經調整過的可能的密碼 - 每次 $pop\ queue$ - 若遇到 $deadends$ 則 $continue$ > Runtime: **50%** > 不用 $DFS$ 的原因: 數字越小越好,但 $DFS$ 會讓調整步數越來越大 ## 804. Unique Morse Code Words 1. 用 **dictionary** 檢查 code pattern 是否出現過 2. 將 list 轉為 **set** ## 826. Most Profit Assigning Work - 用zip將difficulty及profit綁在一起,根據difficulty排序(sorted) - 將worker也排序,從最小能力值的worker開始找 - 紀錄目前difficulty中最大的profit值,即是該worker的profit sorted: 根據a排序pairs`[a,b]` ```python= jobs = sorted([a, b] for a, b in zip(difficulty, profit)) ``` ## 828. Count Unique Characters of All Substrings of a Given String - 每個子字串其中字母只出現一次的和 - $\text{ABA}=1, \text{only B}$ - $\text{ABBB}=1, \text{only A}$ - **Attempt 1:** - $\text{DP and dictionary}$ - 算出 $s[i:j]$ 中的 $\text{dictionary}$ - 若某個字母出現兩次以上,則減掉此字母的長度 > **MLE** - **Attempt 2:** - $\text{DP}$ 的矩陣不用 $n\times n$,改用 $n$ 即可 - 因為每多一個字母只取 $matrix[i,j-1]$ 的資料 > **TLE** - **Attempt 3:** - 每檢查到一個字母,減掉因為此字母而產生兩個以上的字母的長度 - eg. - `index[B]=[0,2,3]` | 0 | 1 | 2 | 3 |minus| | --- | --- | --- | --- | --- | | | | | B |0| | | | B | B |2| | | A | B | B |2| | B | A | B | B |3| - 長度要乘上兩個 `index` 之間的差 > **TLE** - **Solution 1:** - | 0 | 1 | 2 | minus| | --- | --- | --- | --- | | | | | 0| | | | B | 0| | | A | B | 0| | B | A | B | 2| - 比較此矩陣與上個矩陣 - 減掉的數可以累加 - 檢查字母長度是否大於 $2$ - 且每次只要檢查 $s[i]$,不用每個字母都檢查 > Runtime: 184 ms, faster than **6.67%** of Python online submissions for Count Unique Characters of All Substrings of a Given String. Memory Usage: 12.1 MB, less than **100.00%** of Python online submissions for Count Unique Characters of All Substrings of a Given String. ## 919. Complete Binary Tree Inserter - insert 數字到 complete binary tree 中 - ```python class CBTInserter(object): def __init__(self, root): """ :type root: TreeNode """ self.queue = [] # 定義 ... def insert(self, v): """ :type v: int :rtype: int """ self.queue # 可直接用 ... ``` - **Attemp 1:** - $heap + queue$ - 只取 parent 的 index 值 (沒有插入node) > **WA** (但console test可以(!?)) - **Solution 1:** - $queue$ - 紀錄最後一個 parent - 判斷插入parent的左/右邊 - 回傳parent在 $queue$ 中的index > Runtime: 48 ms, faster than **94.94%** of Python online submissions for Complete Binary Tree Inserter. > Memory Usage: 13.2 MB, less than **100.00%** of Python online submissions for Complete Binary Tree Inserter. ## 923. 3Sum With Multiplicity - 2Sum with $O(n)$ solution: 兩個pointer $i$, $j$, $i<j$ $if A[i]+A[j] > target: j = j-1$ $if A[i]+A[j] < target: i = i+1$ $if A[i]+A[j] == target: j = j-1, i=i+1, count= count+1$ - 3Sum: $for\ i\ in\ length(A):$ $target = A[i]$ $find\ target\ at\ A[i+1,len(A)-1]$ - 但在$A[j]+A[k] == target-A[i]$時有兩種情況: 1. $A[j] != A[k]:$ 若陣列為$A=[2,2,3,4,5,5]$,$j=0,\ k=5$ :::warning 若立刻執行$j=j+1$及$k=k-1$會少算 $j=0,\ k=4$及$j=1,\ k=5$的組合 ::: class: ```python= class indexAndSum(): def __init__(self, sum, index): self.sum = sum self.index = index ``` enumerate: ```python= for i, x in enumerate(A): # i: index # x: A[i] ``` ## 973. K Closest Points to Origin - 找 K 與原點最接近的數字 - **Solution 1:** - $\text{sort}$ - 根據 $key=x^2+y^2$ - 取前 $k$ 個數字 > Runtime: 592 ms, faster than **83.24%** of Python online submissions for K Closest Points to Origin. Memory Usage: 17.5 MB, less than **73.58%** of Python online submissions for K Closest Points to Origin. ## 1019. Next Greater Node In Linked List - 用一個stack儲存沒有找到next greater node的index - $nodeList_i,i\ \in [1,\ n]$ ,若找到更大的值則更新answer,若無則push $i$ - for-loop $nodeList:\ O(n)$ stack push/pop 攤銷 $O(n)$ (因為每個元素最多push一次pop一次) total time complexity $O(n)$ List最末元素: ```python= > stack = [1,2,3,4] > stack[-1] 4 ``` ## 1054. Distant Barcodes - 找出鄰近不相同的字串排列(必存在) - **Attemp 1:** - 用 count 排序 - 每次間隔輸出 $[0,2,4,...,1,3,5,...]$ > TLET - **Solution 1:** - 用 `from collections import Counter` - ```python from collections import Counter for k,v in Counter(barcodes).most_common(): # k: 數字 # v: 幾次 ``` > Time: 70% > Memory: 100% ## 1123. Lowest Common Ancestor of Deepest Leaves - 找最深的葉子們的共同祖先,return該點 - 比較左右兩子樹,深度較深的那邊則$LCA(Lowest\ \ Common\ \ Ancestor)$為該子樹,若相等則return該root - 用一helper函數遞迴求左右兩子樹的子問題 - time complexity $O(N)$ - space complexity $O(H)$ ```python= def lcaDeepestLeaves(self, root): def helper(root): if not root: return 0, None h1, lca1 = helper(root.left) h2, lca2 = helper(root.right) if h1 > h2: return h1 + 1, lca1 if h1 < h2: return h2 + 1, lca2 return h1 + 1, root return helper(root)[1] ``` ## 1129. Shortest Path with Alternating Colors - 給定$[0,n-1]$共$n$個點,並給定紅藍線段,找出0到所有點的最短路徑長,且需紅藍相間 - 從0開始做BFS,若0到[1,2]有紅色線段,則設[1,2]長度為1,且顏色為藍(下一個需接藍色) - 最大值為$n\times2-3$ (unknown) ```python= def shortestAlternatingPaths(self, n, red_edges, blue_edges): G = [[[], []] for i in xrange(n)] for i, j in red_edges: G[i][0].append(j) for i, j in blue_edges: G[i][1].append(j) res = [[0, 0]] + [[n * 2, n * 2] for i in xrange(n - 1)] bfs = [[0, 0], [0, 1]] for i, c in bfs: for j in G[i][c]: if res[j][c] == n * 2: res[j][c] = res[i][1 - c] + 1 bfs.append([j, 1 - c]) return [x if x < n * 2 else -1 for x in map(min, res)] ``` - $map(function,\ list):$ return [function(element) for element in list] ## 1137. N-th Tribonacci Number - $T_0=0,T_1=1,T_2=1,求T_n$ - 用 $a,b,c$ 存目前的三個值,用 $d$ 存三數總和 - 下一輪:$a = b, b=c,c=d$ - return最後一輪的 $d$ ## 1138. Alphabet Board Path - 一board存 $a$~$z$ 字母,給定 $target$ 陣列。 - 從 $a$ 出發,往上則輸出 $U$ ,往右 $R$,往左 $L$,往下 $D$,印出字 $!$ - 輸出路徑並印出字 - <font color=red>注意不能超過board的長寬</font> - 解法:找出目標字母的 $(ascii\ code-97)$ ,求出**商**和**餘數**,若商大於目前位置,則 $D$,反之 $U$;若餘數大於目前位置,則 $R$,反之 $L$ - 超過board長寬則先往 $L$ 或 $U$ - 字母ascii code: ```ord("a")```,return ```97``` ## 1139. Largest 1-Bordered Square - 有多大的正方形邊長都是 1 - eg. 1 1 1 1 0 1 1 1 1 - **Solution 1:** - 參考 [304. Range Sum Query 2D](https://hackmd.io/OzKKg2EWRemnUzOum6rRwQ?both#304-Range-Sum-Query-2D---Immutable) - 正方形減掉中間小正方形的和 - 要等於 $n^2-(n-2)^2=4n-4, \forall n > 2$ - 檢查所有長度 $k$ 的正方形 > Runtime: 2060 ms, faster than **5.71%** of Python online submissions for Largest 1-Bordered Square. Memory Usage: 12 MB, less than **100.00%** of Python online submissions for Largest 1-Bordered Square. > $O(n^3)$ - **Solution 2:** - DP 矩陣儲存 $\text{row, col}$ 的連續 $1$ 長度 (需要2個矩陣) - 在點 $(i,j)$ 時,檢查 - $\text{col}(i-len,j) \geq len$ - $\text{row}(i,j-len) \geq len$ - [圖解](https://leetcode.com/problems/largest-1-bordered-square/discuss/345265/c%2B%2B-beats-100-(both-time-and-memory)-concise-with-algorithm-and-image) > Time: $O(n^2)$ > Space: $O(n^2)$ ## 1144. Decrease Elements To Make Array Zigzag - 給定一陣列,找到最小的 $move數$,使得數列呈偶數(或基數)元素較左右兩邊元素小 - **Greedy**的方法,掃過陣列,若要偶數元素較小則減去能使得較左右元素小的值 - 因為若要使偶數元素較小,再減去基數元素的值,會使得偶數元素需要減的值更多 - eg. $[3,5,4]$,要使得 $5$ 較左右小,再減掉 $3$ 會使得 $5$ 需要減去的值更多, $move數$ 增加,減掉 $4$ 也會使 $move數$ 增加,且無助於讓 $5$ 小於 $3$ - 注意邊界值, $index$ 為零時不能檢查左邊, $index$ 大於 `len(nums)` 時不能檢查右邊。 - 不用設`if index == 0: 檢查右邊` - 而是設`if index != 0: 檢查左邊` - 否則當`if index < len(nums)/2`時仍要再做`檢查右邊`,程式碼重複 - Time complexity $O(N)$ ## Google Former Coding Interview Question: Compression and Decompression - [Former Coding Interview Question: Compression and Decompression](https://techdevguide.withgoogle.com/resources/compress-decompression/?types=coding-interview-question#!) isalpha ```python= > "3".isalpha() False > "a".isalpha() True ``` ## 1209. Remove All Adjacent Duplicates in String II - 移除最多 $k$ 個相連的字母,直到沒有 $k$ 個相連的字母為止 - **Attempt 1:** - 每次檢查前 $k$ 個字母,如果都相同則移除 - $O(nk)$ - worse case: $k=2$ "aaaaaaaaaa" - 如果只能移除 $k$ 個則會重複移除很多次 > TLE - **Attempt 2:** - 若字不同時,才移除前面 $q$ 個,$q$ 必為 $k$ 的倍數 > TLE - **Solution 1:** - 遞迴 - 用 **Attempt 2** 的方式每次移除 $>k$ 的字母 - 直到字串沒有再發生變化為止 > Runtime: 52 ms, faster than **87.18%** of Python online submissions for Remove All Adjacent Duplicates in String II. Memory Usage: **17.1 MB**, less than 100.00% of Python online submissions for Remove All Adjacent Duplicates in String II. - **Solution 2:** - 一直replace字串直到沒有發生變化為止 - `s.replace(pattern,"")` ## 1218. Longest Arithmetic Subsequence of Given Difference - 找出最長的遞增/遞減子序列 - **Attempt 1:** - 用 $\text{dictionary}$ 紀錄出現過的數字的出現位置 - 找 `arr[i]+difference` 是否在 $\text{dictionary}$ 中 - 若有則繼續搜尋下一個 `arr[i]+difference+difference` > TLE - **Attempt 2:** - 從數列最後端開始用 $\text{dictionary}$ 紀錄 - 若 `arr[i]+difference` 在 $\text{dictionary}$ 中 - $\text{dictionary}[arr[i]]=1+\text{dictionary}[arr[i]+\text{difference}]$ - 因為選到越右邊的數,越有可能在左邊找到此等差 - eg. `[7,5,...,5,3,1]` - 最好是選到最右邊的 `5` > WA - **Solution 1:** - case: `[1,2,3,4,1,2,3]` - **Attempt 2** 因為越右邊的數字越好,所以左邊的就不理會 - 可是左邊的數字也有機會使得長度越長 - 出現相同數字時,仍檢查 `arr[i]+difference` 是否在 $\text{dictionary}$ 中 > Runtime: 532 ms, faster than **57.66%** of Python online submissions for Longest Arithmetic Subsequence of Given Difference. Memory Usage: 23 MB, less than **100.00%** of Python online submissions for Longest Arithmetic Subsequence of Given Difference. ## 1325. Delete Leaves With a Given Value - 若 leaf 是 target value 則刪除,刪到最少為止 - **Attempt 1:** - $heap$ 解 - 每次檢查 $\frac{index-1}{2}$ 的值 (parent) 是否為target,是則往上刪除 - 由 $TreeNode$ 轉成 $heap$ 需要用 <font color=red>$queue$</font> 而不是 $stack$ 才會是 level order 的輸出 node $dequeue:$ `queue.pop(0)` - $heap$ 最好只存 $value$ 不存 $TreeNode$ 不然會耗費空間 > 空間耗費大 > 因為需要存取 $complete\ tree$ > 會 **TLE** - **Solution 1:** - $TreeNode$ 遞迴解 - 定義 `searchTree(node)` 為: 若 `searchTree(node.left)` 為空 且 `searchTree(node.right)` 為空 且 `node.val == target` 則 `return None` 否則 `return node` > $DFS$ 時間複雜度 > Runtime: 40 ms, faster than **86.46%** of Python online submissions for Delete Leaves With a Given Value. > Memory Usage: 12.7 MB, less than **100.00%** of Python online submissions for Delete Leaves With a Given Value. ## 1357. Apply Discount Every n Orders - 每 $n$ 個客人有 $discount$ 的折扣 > 83.76% ## 1358. Number of Substrings Containing All Three Characters - 含有 $\text{abc}$ 字串的子字串個數 - **Solution 1:** - 用 $Flag$ 紀錄 $\text{a, b, c}$ 出現的位址 - 紀錄最後一次更新的位址 - 若無更新過則為 $-1$ - 若更新過則為 $min(Flag_a,Flag_b,Flag_c)$ - 紀錄 $min(Flag_a,Flag_b,Flag_c)$ - 若 $\text{a, b, c}$ 都有出現過且 $min$ 有變動,則計算 - $(min(Flag_a,Flag_b,Flag_c)-lastUpdate)\times (len(s)-max(Flag_a,Flag_b,Flag_c))$ - | lastUpdate | ... | i | ... | j | ... | len(s) | | ---------- | --- | --- | --- | --- | --- | ------ | | c | ... | a | b | c | ... | a | - 算出含有 $i$ 到 $j$ 的所有子字串可能 - 從左到右計算 $O(n)$ - $lastUpdate$ 用來排除已經計算過的字串可能 - 如 - | 0 | 1 | 2 | 3 | 4 | 5 | | --- | --- | --- | --- | --- | --- | | b | b | c | c | a | b | - 在 $i=4$ 時,$Flag_a,Flag_b,Flag_c=(4,1,3)$, $lastUpdate=-1$ - 含有 $\text{bcca}$ 的字串有 $\text{bbcca, bbccab, bcca, bccab}$ - $lastUpdate$ 紀錄為 $1$ - 在 $i=5$ 時,$Flag_a,Flag_b,Flag_c=(4,5,3)$, $lastUpdate=1$ - 含有 $\text{cab}$ 的字串有 $\text{ccab, cab}$ (不包含到 index 為 1 的 $\text{b}$) > 71.63% ## 1359. Count All Valid Pickup and Delivery Options - 給定 $n$ 個包裹,計算所有可能的 $\text{Pickup/Dilivery}$ 個數 - 如 $n=2$ - 可能的組合有 - $(P1,P2,D1,D2), (P1,P2,D2,D1), (P1,D1,P2,D2), (P2,P1,D1,D2), (P2,P1,D2,D1), (P2,D2,P1,D1)$ - **Solution 1:** - 因必須 $P$ 再 $D$ - 等同於 **$PD$ 無順序** - $n=2$ 的例子可視為 - $(ABAB, ABBA, AABB, BAAB, BABA, BBAA)$ - $n=3$ - $(AABBCC)$ 的排列組合 - 公式: $$\frac{(2n)!}{(2!)^n}$$ > 83.89% ## 1361. Validate Binary Tree Nodes - 給定 $n, lchild, rchild$,判斷是否為 binary tree - **Solution 1:** - 用 tree definition - $edges = n-1$ - $inward = 1, outward = [0-2]$ > 47.24% ## 1362. Closest Divisors - 給定 $num$ 找到 $num+1$ 或 $num+2$ 中兩個乘積最接近者 - $\text{return [a,b], where }a\cdot b=num+1\text{ or }a\cdot b=num+2$ - `sqrt(num)` 也可用 $i^2==num$ 判斷 - **Solution 1:** - $\text{for }i\in[1,\sqrt{num}]$ > 11.54% - **Solution 2:** - $\text{for }i\in[\sqrt{num},1]$ ## 1363. Largest Multiple of Three - 給定 $digits$ 選出能組成最大的 $3$ 的倍數的數字 - **Solution 1:** - $Greedy:$ 越多位數越好 - 每次減少一個非三的倍數 (從最小的開始) - 從 $9 ~ 0$ 輸出結果 ## 1366. Rank Teams by Votes - 找出哪個team得到最多votes - 若前面位置的票的權重 **無限大於** 後面位置的票的權重 - 若票相同則按字母序輸出 team - **Solution 1:** - 建立26個字母的表 - 計算每個vote - ex. ["WXYZ","XYZW"] - list[W] = [1001] - list[X] = [1100] - list[Y] = [0110] - list[Z] = [0011] - 比較兩個list: - 若第 $0-i$ 位數大於另一個list,則較大 - 若第 $0-i$ 有較小的數,則較小 - 若 $0-n$ 都相同,則相同 > Time 7.56% ## 1367. Linked List in Binary Tree - 找出tree中有沒有linked list的字串 - **Attemp 1:** - $DFS$ - 若`node.val == target.val` - 則遞迴搜尋 `node.right` `node.left` `target.next` - 如果 `target == None return True` > 如果 `target.val` 非 `head`,直接找`node.left(right)` 會忽略 `node.val == head.val` 的可能 - **Solution 1:** - $DFS$ 如上 - 最後 `return search(node, head) or self.isSubPath(head, root.left) or self.isSubPath(head, root.right)` > Time 23.11% ## 1371. Find the Longest Substring Containing Vowels in Even Counts - 找到最長 substring 裡面有偶數個母音(aeiou) - **Attemp 1:** - 找 $i$ 到 $j$ 中母音數量是不是為零 - $aCount[j] - aCount[i]\ \%2==0$ - $O(n^2)$ > **TLE** - **Solution 1:** - 用 $hash\ table$ 紀錄出現過的母音pattern - $aeiou=01010$ $1$ 表示母音出現過奇數次 $0$ 表示母音出現過偶數次 - 若 pattern 沒有出現過,則紀錄 index - 若 pattern 出現過,則搜尋第一次出現的 index - 兩個 index 相減則是可以造出的合法字串長度 - $\text{Time: }O(n)$ $\text{Space: }O(2^5)=O(1)$ ## 1372. Longest ZigZag Path in a Binary Tree - 找到最長 ZigZag 路徑 (左子樹,右子樹,左子樹...) - 用遞迴時要注意子樹中最長 ZigZag 路徑不一定能和 root 相加 - 可能沒有連續 - `return [left, right, max]` ## 1375. Bulb Switcher III - 每次開一盞燈,算出幾個 phase 前面的燈會都開過 - **Solution 1:** - 儲存目前開到的最大的燈泡值 - 如果 $max==(i+1)$ 則 $count+1$ > Time: 98.52% > $O(n)$ ## 1376. Time Needed to Inform All Employees - 算出通知樹狀結構的每個下屬的時間 - **Attemp 1:** - 每次往上尋找 manager 直到 root - 更新每個 manager 最大的通知下屬的時間 `max(informTime[all child node])` - $timeSum$ 儲存每個**下到上**的 `informTime` (會因 children 而有不同) > **TLE** - **Solution 1:** - $timeSum$ 儲存**上到下**的 `informTime` (上到下的時間不會變) - $timeSum$ 儲存後可供之後要用的 child 的點檢索 - 只找 `informTime[i] == 0` 的點(下屬) - 用 $stack$ 儲存往 header 搜尋時經過的 node 之後 $pop$ 出這些 node 更新 $timeSum$ - `return max(timeSum)` > 攤銷 $O(n)$ > 跑過的 manager 的點不用再跑一次 > Time : 99.13% ## 1382. Balance a Binary Search Tree - 平衡二元搜尋樹 - **Attemp 1:** - AVL tree > WA - **Solution 1:** - 先建立 Tree 中有哪些數字 - 用這些數字建立 Tree > good in time and space ## 1383. Maximum Performance of a Team - 從 $n$ 個工程師裡面挑最多 $k$ 個使得 performance 越好 - $max\{(\sum\text{speed}_i)\times min(\text{efficiency}_i)\}, i<k$ - **Attemp 1:** - $i\in[1,n]$ - 檢查 $\text{perfomance}[1:i-1],\text{perfomance}[i], \text{perfomance}[1:i]$ 哪個較好 - (假設可以求出在 $i$ 前的最好結果) > WA > 若相同 performance,但再加入工程師時結果會不同 - **Solution 1:** - `bisect.insort(array, element)` - 在 `array` 中插入 `element` 使得 `array` 仍排序過 - 按照 $\text{efficiency}$ 排序,但仍存 $\text{speed}$ 的排序結果 - 若結果數大於 $k$ 則減掉此 $\text{efficiency}$ 前最小的 $\text{speed}$ > $O(n^2)$ > 用 $\text{priority queue}$ 為 $O(nlogk+nlogn)$ > ## 1392. Longest Happy Prefix - 找最長的 $\text{prefix = suffix}$ - **Solution 1:** - $\text{KMP}$ 的 $\text{prefix table}$ - | A | B | A | B | C | A | B | A | A | | --- | --- | --- | --- | --- | --- | --- | --- | --- | | A | | | | | | | | | | A | B | | | | | | | | |**A** | B | **A** | | | | | | | |**A** | **B** | **A** | **B** | | | | | | | A | B | A | B | C | | | | | | **A** | B | A | B | C | **A** | | | | | **A** | **B** | A | B | C | **A** | **B** | | | | **A** | **B** | **A** | B | C | **A** | **B** | **A** | | | **A** | B | A | B | C | A | B | A | **A** | | 0 | 0 | 1 | 2 | 0 | 1 | 2 | 3 | 1 | - [KMP演算法](https://youtu.be/3IFxpozBs2I) ## 1395. Count Number of Teams - 給定一個數列(unique),計算有幾種可能的隊伍組合 $\text{rating}[i]<\text{rating}[j]<\text{rating}[k]$ $\text{rating}[i]>\text{rating}[j]>\text{rating}[k]$ - **Solution 1:** - 暴力法 - 三個 $for$ 迴圈找到合適的 $i,j,k$ > $O(n^3)$ > Runtime: **50.33%** - **Solution 2:** - 以 <font color=red>$j$</font> 為 $iterator$ - 找 $j$ 前有幾個比 $j$ 大 <font color=#ff9e12>(小)</font> 的數字 - 找 $j$ 後有幾個比 $j$ 小 <font color=#ff9e12>(大)</font> 的數字 - $out := \sum_{j=1}^{n-2}less_{left}\times greater_{right}+less_{right}\times greater_{left}$ - example: - `[13, 3, 4, 10, 7, 8]` - $j=2, \text{ rating[2]}=4$ - 在 $4$ 左邊比 $4$ 小:$3$ 在 $4$ 右邊比 $4$ 大: $10,7,8$ - 可能的組合: $(3,4,10),(3,4,7),(3,4,8)$ - $less_{left}\times greater_{right}=3$ > $O(n^2)$ ## Line筆試 - 輸出`abc`的排列組合(可重複字母) - 共有 $n^n$ 種組合 ```python def permute(pre,s,n): if n == 0: print(pre) return for i in range(len(s)): permute(pre+s[i], s, n-1) permute("","abc",3) ``` ## Google New Grads phone interview - ```python def path(matrix, effort): passed = [[0 for i in range(len(matrix))]for i in range(len(matrix))] i = 0 j = 0 stack = [(i,j)] while stack: (x,y) = stack.pop() if x == len(matrix)-1 and y == len(matrix)-1: return True if y < len(matrix)-1: # right if abs(matrix[x,y]-matrix[x,y+1]) <= effort and not passed[x][y+1]: stack.append((x,y+1)) if x < len(matrix)-1: # down if abs(matrix[x,y]-matrix[x+1,y]) <= effort and not passed[x+1][y]: stack.append((x+1,y)) if y > 0: # left if abs(matrix[x,y]-matrix[x, y-1]) <= effort and not passed[x][y-1]: stack.append(x, y-1) if x > 0: # up if abs(matrix[x,y]-matrix[x-1,y]) <= effort and not passed[x-1][y]: stack.append(x-1,y) passed[x][y] = True return False ```