Leetcode in Golang
Leetcode, Codility , GeekforGeeks algorithms exercises written in Golang.
https://kimi0230.github.io/LeetcodeGolang/
leetcode Content
- Leetcode in Golang
- leetcode Content
- GeeksforGeeks Content
- Codility Content
- Reference
Data Structure
Array & String
No. | Title | Solution | Difficulty | Time | Space | Topic |
---|---|---|---|---|---|---|
0001 | Two Sum | Go | Easy | O(n) | O(n) | Array |
0003 | Longest Substring Without Repeating Characters | Go | Medium | O(n) | O(1) | Array, Sliding Window |
0015 | 3 Sum | Go | Medium | O(n^2) | O(n) | Array |
0027 | Remove Element | Go | Easy | O(n) | O(1) | Array |
0035 | Search Insert Position | Go | Easy | O(n), O(logn) | O(1) | Array |
0049 | Search Insert Position | Go | Medium | O(kn) | O(kn) | Array |
0059 | Spiral Matrix II | Go | Medium | O(n) | O(n^2) | Array |
0088 | Merge Sorted Array | Go | Easy | O(n) | O(1) | Array |
0217 | 0217.Contains Duplicate | Go | Easy | O(n) | O(n) | Array |
0242 | 0242.Valid Anagram | Go | Easy | O(n) | O(n) | Array |
0409 | 409. Longest Palindrome | Go | Easy | O(n) | O(1) | Array |
0380 | 0380.Insert Delete GetRandom O(1) | Go | Medium | O(1) | O(n) | Array |
0381 | 0381.Insert Delete GetRandom O(1) Duplicates allowed | Go | Medium | O(1) | O(n) | Array |
0412 | 0412.Fizz Buzz | Go | Easy | O(n) | O(n) | Array, string |
1195 | 1195.Fizz Buzz Multithreaded | Go | Medium | O(n) | Array, string,Concurrency | |
0238 | 238. Product of Array Except Self | Go | Medium | O(n) | Array, string, Prefix Sum | |
0128 | 128. Longest Consecutive Sequence | Go | Medium | O(n) | O(n) | Array, Hash Table, Union Find |
Matrix
Linked List
No. | Title | Solution | Difficulty | Time | Space | Topic |
---|---|---|---|---|---|---|
0019 | Remove Nth Node From End of List | Go | Medium | O(n) | O(1) | Linked List, Two Pointers |
0141 | Linked List Cycle | Go | Easy | O(n) | O(1) | Linked List, Two Pointers |
0142 | Linked List Cycle II | Go | Medium | O(n) | O(1) | Linked List, Two Pointers |
0203 | Remove Linked List Elements | Go | Easy | O(n) | O(1) | Linked List |
0206 | Reverse Linked List | Go | Easy | O(n) | O(1) | Linked List |
0876 | Middle of the Linked List | Go | Easy | Linked List, Two Pointers | ||
0021 | Merge Two Sorted Lists | Go | Easy | O(log n) | O(1) | Linked List |
0002 | Add Two Number | Go | Medium | O(max(m,n)) | O(1) | Linked List |
HashSet & HashMap
Stack & Queue
No. | Title | Solution | Difficulty | Time | Space | Topic |
---|---|---|---|---|---|---|
0020 | Valid Parentheses | Go | Easy | O(n) | O(n) | Stack |
0094 | Binary Tree Inorder Traversal | Go | Medium | O(n) | O(1) | Stack |
Heap & Priority Queue
Heap 總是能讓整棵樹當中最大或最小值維持在root節點上
Heap 有幾個特色:
- 常見架構是像 binary tree 那樣
- 保持 balanced
- max heap 的 root 是最大值;min heap 的 root 則是最小值
- 雖然是 tree,卻很適合放在 array 中處理
heap sort
根據定義 heap 的 root 一定是最大(假設是 max heap),也就是說,無序數列經過 heapify 再作 n 次 root deletion 取出最大值,就可以得到排序的結果。 最後就得到 heap sort 的 worst case 時間複雜度 O(nlogn) 的結果。 可是 quick sort 的 worst case 時間複雜度是 O(n²),怎麼 quick sort 的時間複雜度比較糟糕卻比較受歡迎? google 的結果是說 heap sort 比較不利於 caching 對於 spatial locality 機制,蠻有道理的阿。
No. | Title | Solution | Difficulty | Time | Space | Topic |
---|---|---|---|---|---|---|
0703 | Kth Largest Element in a Stream | Go | Easy | O(K + (N-K)logK) | O(k) | Heap, Priority Queue |
1046 | Last Stone Weight | Go | Easy | O(nlogn) | O(n) | Heap, Priority Queue |
0347 | Top K Frequent Elements | Go | Medium | O(Nlogk) | O(n) | Heap, Priority Queue, Quick Sort |
Disjoint Set Union
Trie
Binary Indexed Tree
Design Data Structures
Algorithm
Greedy
Sort
No. | Title | Solution | Difficulty | Time | Space | Topic |
---|---|---|---|---|---|---|
0075 | Sort Colors | Go | Medium | O(n) | O(1) | Sort |
0215 | Kth Largest Element in an Array | Go | Medium | O(n) | O(logn) | Sort |
Multiple Pointers
Backtracking (回溯法). DFS
DFS. 解決一個回溯問題, 實際上就是一個決策樹的遍歷過程. 算是一個暴力的窮舉算法
- 路徑:也就是已經做出的選擇。
- 選擇列表:也就是你當前可以做的選擇。
- 結束條件:也就是到達決策樹底層,無法再做選擇的條件。
- https://www.bilibili.com/video/BV1P5411N7Xc
result = []
def backtrack(路徑, 選擇列表):
if 滿足結束條件:
result.add(路徑)
return
for 選擇 in 選擇列表:
做選擇(前序)
backtrack(路徑, 選擇列表)
撤銷選擇(後序)
No. | Title | Solution | Difficulty | Time | Space | Topic |
---|---|---|---|---|---|---|
0046 | Permutations (全排列) | Go | Medium | O(n) | O(n) | Backtracking |
0078 | Subsets | Go | Medium | O(n^2) | O(n) | Backtracking |
DFS & BFS
找最短路徑用BFS, 其他時用DFS用得多一些, 因為遞迴較好寫
假設有棵滿的二叉樹,節點數為 N. 對DFS來說空間複雜度就是遞迴, 最壞的情況就是樹的高度 O(log N) BFS算法, Queue每次都會存二叉樹一層的節點, 最壞的情況下空間複雜度應該就是樹的最下層的數量, 也就是 N/2. 空間複雜度 O(N)
DFS(深度優先搜索)通常使用堆棧(Stack)來實現。在DFS中,您首先處理一個節點,然後將其子節點按某種順序推入堆棧中,接著繼續處理堆棧頂部的節點,直到堆棧為空。 BFS(廣度優先搜索)則使用隊列(Queue)來實現。在BFS中,您首先處理一個節點,然後將其子節點按某種順序排隊,接著繼續處理隊列的前端節點,直到隊列為空。
No. | Title | Solution | Difficulty | Time | Space | Topic |
---|---|---|---|---|---|---|
0695 | Max Area of Island | Go | Medium | O(m*n) | O(m*n) | DFS & BFS |
0733 | Flood Fill | Go | Easy | O(m*n) | O(m*n) | DFS & BFS |
Dynamic Programming
動態規劃問題的一般形式就是求最值, 最長遞增子序列, 最小編輯距離等. 核心問題是窮舉
- 重疊子問題
- memory table
- DP table
- 最優子結構
- 狀態轉移方程式
- 這問題的 base case (最簡單情況) 是什麼?
- 這問題有什麼狀態
- 對於每個狀態, 可以做出什麼選擇, 使得狀態發生改變
- 如何定義 dp 數組/函數的含義來表現狀態和選擇?
替換 /跳過 dp[i-1][j-1] |
刪除 dp[i-1][j] |
---|---|
插入 dp[i][j-1] |
dp[i][j] |
# 初始化 base case
dp[0][0][...] = base
# 進行狀態轉移
for 狀態1 in 狀態1的所有取值:
for 狀態2 in 狀態2的所有取值:
for ...
dp[狀態1][狀態2][...] = 求最值(選擇1,選擇2...)
No. | Title | Solution | Difficulty | Time | Space | Topic |
---|---|---|---|---|---|---|
0053 | Maximum Subarray | Go | Easy | O(n) | O(n) | Dynamic Programming |
0072 | 0072. Edit Distance | Go | Hard | Dynamic Programming | ||
0300 | Longest-Increasing-Subsequence | Go | Medium | 方法一:O(n^2) 方法二:O(nlogn) | O(n) | Dynamic Programming |
0322 | Coin Change | Go | Medium | O(nm) | O(n) | Dynamic Programming |
0354 | Russian Doll Envelope | Go | Hard | Dynamic Programming | ||
0509 | Fibonacci Number | Go | Easy | 很多解法 | 很多解法 | Dynamic Programming |
0070 | 0070.Climbing Stairs | Go | Easy | O(n) | O(n) | Dynamic Programming |
0746 | 0746.Min Cost Climbing Stairs | Go | Easy | O(n) | O(1) | Dynamic Programming |
Sliding Window
維護一個窗口, 不斷滑動
void slidingWindow(string s, string t){
unordered mapneed, window;
for (char c:t) need[c++]
int left = 0 , right = 0
int valid = 0
// 先移動 right 再移動 left. 直到right到達 string的末端
while(right < s.size()){
// c是將移入窗口的字符
char c = s[right]
// 右移窗口
right++
// 進行窗口內數據的一系列更新
// ...
/*** 用來debug 輸出位置 ***/
printf("window: [%d, %d)\n",left,right)
/************************/
// 判斷左側窗口是否收縮
while(window needs shrink){
// d是將移出窗口的字符
// 左移窗口
left++
// 進行窗口內數據的一系列更新
// ...
}
}
}
No. | Title | Solution | Difficulty | Time | Space | Topic |
---|---|---|---|---|---|---|
0209 | Minimum Size Subarray Sum | Go | Medium | O(n^2) / O(n) / O(nlog n) | O(1) / O(1) / O(n) | Sliding Window |
0438 | Find All Anagrams in a String | Go | Medium | O(n) | O(1) | Sliding Window |
0567 | Permutation in String | Go | Medium | O(n) | O(1) | Sliding Window |
Sweep Line
Rolling Sum
Two Pointers
只要array有序, 就應該想到雙指針技巧 分為兩類 1. "快,慢指針" 2. "左,右指針"
- 快,慢指針: 主要解決 linkedlist 問題, 典型的判斷 linkedlist 是否包含環
- 左,右指針: 主要解決array(或 string)中的問題, 如二分搜尋.
https://labuladong.gitee.io/algo/2/21/57/
No. | Title | Solution | Difficulty | Time | Space | Topic |
---|---|---|---|---|---|---|
0019 | Remove Nth Node From End of List | Go | Medium | O(n) | O(1) | Linked List, Two Pointers |
0141 | Linked List Cycle | Go | Easy | O(n) | O(1) | Linked List, Two Pointers |
0283 | Move Zeroes | Go | Easy | O(n) | O(1) | Two Pointers |
0142 | Linked List Cycle II | Go | Medium | O(n) | O(1) | Linked List, Two Pointers |
0344 | Reverse String | Go | Easy | O(n) | O(1) | Two Pointers |
0876 | Middle of the Linked List | Go | Easy | Linked List, Two Pointers | ||
0011 | Container With Most Water | Go | Medium | Two Pointers | ||
0074 | Search a 2D Matrix | Go | Medium | Binary Search, Two Pointers |
Bit Manipulation∂
No. | Title | Solution | Difficulty | Time | Space | Topic |
---|---|---|---|---|---|---|
0693 | Binary Number with Alternating Bits | Go | Easy | O(n)/ O(1) | O(1) / O(1) | Bit Manipulation |
Union Find
No. | Title | Solution | Difficulty | Time | Space | Topic |
---|---|---|---|---|---|---|
0721 | Accounts Merge | Go | Easy | O(n) / O(n log n) | O(n) / O(n) | Union Find |
Breadth First Search
- DFS 算法可以被認為是回溯算法, BFS算法都是用Queue這種數據結構, 每次將一個截短周圍的所有節點加入Queue.
- BFS 找到的路徑一定是最短的, 但是代價是空間複雜度比DFS大. BFS vs DFS
- 優化: 雙向 BFS 優化, 在 while 開始時做一個判斷. 讓每次都選擇較小的集合進行擴散, 那麼佔用的空間增長速度就會慢一些, 盡可能以最小的空間代價產生 curDepth 和 nextDepth 的交集 無論單向的 BFS 或是 雙向BFS, 優化過的BFS 空間複雜度都是一樣的
// 計算從起點 start 到 終點 target 的最點距離
int BFS(Node start, Node targe){
Queue q; // 核心數據結構
Set visited; // 避免走回頭路
q.offer(start); // 將起點加入 Queue
visited.add(start);
int step = 0; // 紀錄擴散的步數
while(q not empty) {
int sz = q.size();
// 當前 Queue 中的所有節點向四周擴散
for (int i = 0 ; i < sz; i++) {
Node cur = q.poll();
// 這裡判斷是否到達終點
if (cur is target) {
return step;
}
// 將cur 的相鄰節點加入 Queue
for (Node x : cur.adj()) {
if (x not in visited) {
q.offer(x);
visited.add(x);
}
}
}
// 在這裡更新步數
step++
}
}
No. | Title | Solution | Difficulty | Time | Space | Topic |
---|---|---|---|---|---|---|
0310 | Minimum Height Trees | Go | Medium | Breadth First Search | ||
0752 | 752. Open the Lock | Go | Medium | Breadth First Search |
Binary Search
分析二分搜尋技巧: 不要出現 else, 而是把所有情況用 else if 寫清楚. 計算 mid 時需要防止溢出
int binarySearch(int[] nums, int target){
int left = 0 , right = ...;
while(...) {
int mid = left + (right - left)/2
if (nums[mid] == target){
...
} else if (nums[mid] < target){
left = ...
} else if (nums[mid] > target){
right = ...
}
}
return ...;
}
將搜尋區間全部統一成兩端都閉, 方便記憶
[letf,right]
func Search(nums []int, target int) int {
lenght := len(nums)
if lenght <= 0="" 1="" {="" return="" -1="" }="" left,="" right="" :="0," lenght-1="" for="" left="" <="right" mid="" +="" if="" nums[mid]="=" target="" else="" 找右邊=""> target {
// 找左邊
right = mid - 1
}
}
// 都沒找到
return -1
}
// 有點類似 nums 小於 target的元素有幾個
func LeftBound(nums []int, target int) (index int) {
lenght := len(nums)
if lenght <= 0="" {="" return="" -1="" }="" left,="" right="" :="0," lenght-1="" for="" left="" <="right" 除以2="" mid="" +="" (right-left)="">>1
mid := int(uint(right+left) >> 1)
if nums[mid] == target {
// 要繼續找左邊, 所以把右邊變小
right = mid - 1
} else if nums[mid] < target {
// 找右邊
left = mid + 1
} else if nums[mid] > target {
// 找左邊
right = mid - 1
}
}
// 都沒找到 注意: left越界情況
if left >= lenght || nums[left] != target {
return -1
}
return left
}
// 有點類似 nums 大於 target的元素有幾個
func RightBound(nums []int, target int) (index int) {
lenght := len(nums)
if lenght <= 0="" {="" return="" -1="" }="" left,="" right="" :="0," lenght-1="" for="" left="" <="right" 除以2="" mid="" +="" (right-left)="">>1
mid := int(uint(right+left) >> 1)
if nums[mid] == target {
// 注意:要繼續找右邊, 所以把左邊變大=mid+1
left = mid + 1
} else if nums[mid] < target {
// 找右邊
left = mid + 1
} else if nums[mid] > target {
// 找左邊
right = mid - 1
}
}
// 都沒找到 注意:right越界情況
if right < 0 || nums[right] != target {
return -1
}
return right
}
=>=>=>
for left
:
- 此方法在迭代終止時,left 和 right 指針指向同一個位置。
- 此方法會包括最後一個可能的候選解,在某些情況下可能更容易理解和實現。
- 在應對邊界情況時可能更為方便,例如當 left 和 right 指向同一位置時,這時可能需要進一步處理。
for left < right {}
:
- 此方法在迭代終止時,left 和 right 指針指向相鄰位置。
- 此方法會排除最後一個可能的候選解,當要求嚴格小於或大於某個值時可能更合適。
在一些情況下,可能會更高效,因為在每次循環中只需要比較一次 left 和 right,而不需要再處理當兩者相等時的情況。
func search(nums []int, target int) int { left, right := 0, len(nums)-1 for left < right { mid := int(uint(right+left)>>1) if nums[mid]==target{ return mid }else if (nums[mid]
No. | Title | Solution | Difficulty | Time | Space | Topic |
---|---|---|---|---|---|---|
0704 | 704. Binary Search | Go | Easy | 最差:O(long n) 最佳O(1)剛好在中間 |
迭代: O(1) 遞迴O(log n) |
Binary Search |
0875 | 875. Koko Eating Bananas | Go | Medium | O(n log m) | O(1) | Binary Search |
0153 | 153. Find Minimum in Rotated Sorted Array | Go | Medium | O(log n) | O(1) | Binary Search |
0033 | 33. Search in Rotated Sorted Array | Go | Medium | O(log n) | O(1) | Binary Search |
0034 | 34. Find First and Last Position of Element in Sorted Array | Go | Medium | O(log n) | O(1) | Binary Search |
0981 | 0981.Time Based Key-Value Store | Go | Medium | O(log n) | Binary Search |
Minimax
Graph
Graph
Topological Sort
Tree
No. | Title | Solution | Difficulty | Time | Space | Topic |
---|---|---|---|---|---|---|
0226 | Invert Binary Tree | Go | Easy | O(n) | O(1) | Tree |
0104 | Maximum Depth of Binary Tree | Go | Easy | O(n) | O(1) | Tree |
0543 | Diameter of Binary Tree | Go | Easy | O(n) | O(n), O(log(n)) | Tree, DFS |
0110 | Balanced Binary Tree | Go | Easy | O(n) | O(1) | Tree, DFS |
0100 | Same Tree | Go | Easy | O(n) | O(1) | Tree |
0105 | Construct Binary Tree from Preorder and Inorder Traversal | Go | Medium | O(n) | O(n) | Array |
Tree Traversal
Binary Search Tree
Compputational Geometry
Selected Topics
Mathematics
Random
Bitwise Manipulation
GeeksforGeeks Content
Topic | Title | No. | Solution | Difficulty | TimeComplexity | SpaceComplexity |
---|---|---|---|---|---|---|
Sorting | Find Minimum Difference Between Any Two Elements | 0031 | Go | Basic | O(n^2), O(n log n) | O(n), O(n) |
Codility Content
Topic | Title | Solution | Difficulty | TimeComplexity | SpaceComplexity | |
---|---|---|---|---|---|---|
Lesson 1 |
Iterations |
Binary Gap |
Go |
Painless | O(log n) | O(1) |
Lesson 2 |
Array |
Cyclic Rotation |
Go |
Painless | O(1) | O(1) |
Odd Occurrences In Array |
Go |
Painless | O(n), O(n) | O(n), O(1) | ||
Lesson 3 |
Time Complexity |
Frog Jmp |
Go |
Painless | O(1) | O(1) |
Perm Missing Elem |
Go |
Painless | O(n) | O(1) | ||
Tape Equilibrium |
Go |
Painless | O(n) | O(n) | ||
Lesson 4 |
Counting Elements |
Frog River One |
Go |
Painless | O(n) | O(n) |
Max Counters |
Go |
Respectable | O(n+m) | O(n) | ||
Missing Integer |
Go |
Respectable | O(n) | O(n) | ||
Perm Check |
Go |
Painless | O(n) | O(n) | ||
Lesson 5 |
Prefix Sums |
Count Div |
Go |
Respectable | O(1) | O(1) |
Genomic Range Query |
Go |
Respectable | O(n+m) | O(n) | ||
MinAvg Two Slice |
Go |
Respectable | O(n) | O(n) | ||
Passing Cars |
Go |
Painless | O(n) | O(1) | ||
Lesson 6 |
Sorting |
Distinct |
Go |
Painless | O(nlogn) | O(n) |
Max Product of Three |
Go |
Painless | O(nlogn) | O(1) | ||
Number Of Disc Intersections |
Go |
Respectable | O(nlogn) | O(n) | ||
Triangle |
Go |
Painless | O(nlogn) | O(n) | ||
Lesson 7 |
Stacks and Queues |
Brackets |
Go |
Painless | O(n) | O(n) |
Fish |
Go |
Painless | O(n) | O(n) | ||
Nesting |
Go |
Painless | O(n) | O(1) | ||
Stone Wall |
Go |
Painless | O(n) | O(n) | ||
Lesson 8 |
Leader |
Dominator |
Go |
Painless | O(n) | O(1) |
EquiLeader |
Go |
Painless | O(n) | O(n) | ||
Lesson 9 |
Maximum slice problem |
Max Profit |
Go |
Painless | O(n) | O(1) |
Max Slice Sum |
Go |
Painless | O(n) | O(n) | ||
Max Double Slice Sum |
Go |
Respectable | O(n) | O(n) | ||
Lesson 10 |
Prime and composite numbers |
Count Factors |
Go |
Painless | O(sqrt(n)) | O(1) |
Flags |
Go |
Respectable | O(n) | O(n) | ||
MinPerimeterRectangle |
Go |
Painless | O(sqrt(n))) | O(1) | ||
Peaks |
Go |
Respectable | O( n*log( log(n) )) | O(n) | ||
Lesson 11 |
Sieve of Eratosthenes (質數篩) |
Count Non Divisible |
Go |
Respectable | O(N * log(N)) | O(n) |
Count Semiprimes |
Go |
Respectable | O(N*log(log(N))+M) | O(N+M) | ||
Lesson 12 |
Euclidean algorithm (輾轉相除法 or 歐幾里得算法) |
Chocolates By Numbers |
Go |
Painless | O(log(N + M)) | O(1) |
Common Prime Divisors |
Go |
Respectable | O(Z * log(max(A) + max(B))**2) | O(1) | ||
Lesson 13 |
Fibonacci numbers |
FibFrog |
Go |
Respectable | O(N * log(N)) | O(N) |
Ladder |
|
Respectable | ||||
Lesson 14 |
Binary search algorithm |
MinMaxDivision |
|
Respectable | ||
NailingPlanks |
|
Respectable | ||||
Lesson 15 |
Caterpillar method |
AbsDistinct |
|
Painless | ||
CountDistinctSlices |
|
Painless | ||||
CountTriangles |
|
Painless | ||||
MinAbsSumOfTwo |
|
Respectable | ||||
Lesson 16 |
Greedy algorithms |
MaxNonoverlappingSegments |
|
Painless | ||
TieRopes |
|
Painless | ||||
Lesson 17 |
Dynamic programming |
MinAbsSum |
|
Ambitious | ||
NumberSolitaire |
|
Respectable |