# Leetcode with Golang
## 20230211 (Day1)
### :heavy_check_mark: 1. Two Sum 二和 [題目](https://leetcode.com/problems/two-sum/)
### a. 暴力解
1. 自己寫的第一版(時間O(n^2),空間O(n))
```
func twoSum(nums []int, target int) []int {
var sum []int
for i := 0; i < len(nums)-1 ; i++ {
for j := 1; j < len(nums); j++ {
if target != nums[i] + nums[j] || i == j {
continue
}
if len(append(sum, i ,j)) == 2 {
sum = append(sum, i ,j)
}
}
}
return sum
}
```
2. 參考別人的解答後修改的版本(時間O(n^2),空間O(n))
[參考連結](https://ithelp.ithome.com.tw/articles/10233459)
```
func twoSum(nums []int, target int) []int {
var sum []int
for i := 0; i < len(nums)-1 ; i++ {
for j := i+1 ; j < len(nums); j++ {
if target != nums[i] + nums[j] {
continue
}
sum = append(sum, i, j)
}
}
return sum
}
```
3. 降低空間複雜度(時間O(n^2),空間O(1))
```
func twoSum(nums []int, target int) []int {
for i := 0; i < len(nums) - 1; i++ {
for j := i + 1; j < len(nums); j++ {
if target == nums[i] + nums[j] {
return []int {i, j}
} else {
continue
}
}
}
return nil
}
```
### b. Hash Map
4. 參考別人解答後自己寫的(時間O(n),空間O(n))
[參考連結1](https://studygolang.com/articles/27605)
[參考連結2](https://fukubaka0825.medium.com/go-leetcode-1-two-sum-cb16490140cd)
```
func twoSum(nums []int, target int) []int {
my_map := make(map[int]int) // make(map[key]value)
for i, v := range nums {
complement := target - v
if idx, exist:= my_map[complement]; exist {
return []int{idx, i}
}
my_map[v] = i
}
return nil
}
```
### 心得
花了比預期多很多的時間在熟悉Golang語法(slice, array的差別、map的操作)上,尤其是if idx, exist:= my_map[complement]; exist {)這句,想出大概的解法倒是很快。
第一直覺就是用暴力解,但寫暴力解時要小心loop的範圍,以及需要注意一開始沒想到的edge case(一開始的寫法不小心默認了兩個解是相連的,後來又忘記一個數只能用一次,重複了)。
寫完暴力解,想了一下想到或許可用指針解,但覺得太麻煩就直接看解答(map)。覺得map的解法很直覺,但因為對map不熟悉所以花了很多時間研究實際作法及語法。
### Map參考資料
[參考資料1](https://pjchender.dev/golang/maps/)
[參考資料2](https://www.digitalocean.com/community/tutorials/understanding-maps-in-go)
[參考資料3](https://ithelp.ithome.com.tw/articles/10156167)
[參考資料4](https://hackmd.io/@action/rk8R2cuAU#map-映射)
## 20230212 (Day2)
### 20. Valid Parentheses 可靠的括號 [題目](https://leetcode.com/problems/valid-parentheses/)
### a. Stack
1. 參考別人的答案後寫出來的
[參考連結](https://blog.csdn.net/bahuan1987/article/details/102344639?spm=1001.2101.3001.6650.8&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-8-102344639-blog-126444509.pc_relevant_3mothn_strategy_recovery&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-8-102344639-blog-126444509.pc_relevant_3mothn_strategy_recovery&utm_relevant_index=11)
小技巧:建立一個以右括號為index的map
```
func isValid(s string) bool {
if len(s) == 0 {
return true
}
my_map := map[string]string {")":"(", "]":"[", "}":"{"}
var stack []string
for i := 0; i < len(s); i++ {
if len(stack) == 0 {
stack = append(stack, string(s[i]))
} else {
if stack[len(stack)-1] == my_map[string(s[i])] {
stack = stack[:len(stack)-1]
} else {
stack = append(stack, string(s[i]))
}
}
}
if len(stack) == 0 {
return true
} else {
return false
}
}
```
## 20230214 (Day3)
### 21. Merge Two Sorted Lists 混合兩鏈結 [題目](https://leetcode.com/problems/merge-two-sorted-lists/)
### a. Iterative
1. 參考
[參考連結](https://helloacm.com/merge-two-sorted-linked-list-using-golang/)
```
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
dummy := new(ListNode)
tail := dummy
for list1 != nil && list2 != nil {
if list1.Val < list2.Val {
tail.Next = list1
list1 = list1.Next
} else {
tail.Next = list2
list2 = list2.Next
}
tail = tail.Next
}
if list1 != nil { // list2 == nil
tail.Next = list1
} else if list2 != nil { // list1 == nil
tail.Next = list2
} else { // list1 == nil && list2 == nil
return nil
}
return dummy.Next
}
```
### b. Recursive
1. 參考
[參考連結(同上)](https://helloacm.com/merge-two-sorted-linked-list-using-golang/)
```
func mergeTwoLists(list1 *ListNode, list2 *ListNode) *ListNode {
if list1 == nil {
return list2
} else if list2 == nil{
return list1
} else {
if list1.Val < list2.Val {
list1.Next = mergeTwoLists(list1.Next, list2)
return list1
} else {
list2.Next = mergeTwoLists(list1, list2.Next)
return list2
}
}
}
```
### 心得
寫iterative時,誤把if當成for來用,沒遍歷所有節點,所以compile沒問題但Wrong Answer。後來又誤把 } 放錯地方,比對成功提交的扣才知道問題在哪裡。
寫recursion時,一直不太確定遞迴的邏輯該怎麼寫(知道理論上是先比較第一個數的大小,抽出小的後,被抽出一個數的數組再使用func進行比較),覺得暫時只能先背起來。
這題跟可靠的括號一樣,一看到題目就大概知道可以用iterative解(因為兩個鏈結都是排序過的,所以直接比較第一個節點的值就好了),奈何對Golang語法不熟、很多細節想不到(可能跟寫扣經驗少有關吧,像是dummy head的操作也是看了一段時間才真的百分之百會寫),還是得參考別人的答案,以致於一題都會花費非常多時間(沒認真測,感覺至少要個兩小時吧),只能說服自己這是在初期所以困難多,但累積久了一定會變快變順的。
今天看了網路上大神Guan Hui-Feng(YT: [Hua Hua](https://www.youtube.com/watch?v=qckKEYP9bBA))與[Neetcode](https://www.youtube.com/watch?v=XIdigk956u0)頻道的講解影片,發現大神們通常不只神還是很願意分享的神,覺得軟體界中這種分享的精神非常可貴,尤其對新手而言真的是值得額手稱慶了(在中文打滾四年以及念了一小段時間的物理,就知道其他領域的自學資源真的少了不知道多少。軟體業像是站在的山腳下看著頂端的大神,雖然知道頂端很遠、爬上去很辛苦,但至少手上有大神發送的地圖、半路上也有大神留下的路標。我在其他領域站在山腳下看著大神,只知道對方在山頂我在山腳,中間還有層層雲霧繚繞,連路都看不清...)。
### 121. Best Time to Buy and Sell Stock 股票最好在這些時間買賣 [題目](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/)
### a. 暴力解
1. 自己寫的,算法應該是對的,但在append profit的地方報out of memory了QQ (時間O(n^2))
```
import (
"fmt"
"sort"
)
func maxProfit(prices []int) int {
var profit []int
for i := 0; i < len(prices)-1; i++ { // O(n^2)
for j:= i+1; j < len(prices); j++ {
if prices[j] - prices[i] > 0 {
profit = append(profit, prices[j] - prices[i])
}
}
}
if profit == nil {
return 0
} else { // sort profit and return the biggest number // O(logn)
sort.Ints(profit)
ans := profit[len(profit) - 1]
// fmt.Println(profit)
return ans
}
}
```
### b. DP
1. 參考 (時間O(n))
[參考影片連結](https://www.youtube.com/watch?v=8pVhUpF1INw)
[參考連結](https://leetcode.com/problems/best-time-to-buy-and-sell-stock/solutions/385299/Go-golang-fast-and-slow-solutions/)
概念:track前k天的最小價格
```
func maxProfit(prices []int) int {
// Lowest prices up to i-th day: L[i]
// Max profit up to i-th day: P[i]
// P[i] = max(P[i-1], prices[i] - L[i-1])
// max_profit = P[n-1]
Low_P := prices[0]
Max_P := 0
for i := range prices {
if prices[i] < Low_P {
Low_P = prices[i]
}
if Max_P < prices[i] - Low_P {
Max_P = prices[i] - Low_P
}
}
return Max_P
}
```
2. 參考
[參考影片連結(同上)](https://www.youtube.com/watch?v=8pVhUpF1INw)
概念:操作price[i]-price[i-1]可得出持有(i-1)th到ith天的收益,最大收益就是收益數組中加起來最大的和,因此問題就轉化成53.Maximum Subarray。
### 心得
寫DP時,心裡想的一直是紀錄最小價格與最大收益就好,但不知道為什麼就寫了個數組(浪費空間而且還寫不出來,卡在max()的用法上。),查了其他人用Golang的解法後,頓悟其實紀錄一個數字就好,也不用max()了,直接用if比較就好了,更改後立刻過了,非常簡潔的想法與解法。
後來發現花花一開始講解的確是用數組,雖然如此,他說了數組的使用其實是不必要的,可以把空間降維至O(1),但我到第二次看影片時才看懂。其實數組&記一個數字都是正確的,只是差在空間複雜度。
## 20230215 (Day4)
### 125. Valid Palindrome 可靠的回文(不可靠啦!討厭) [題目](https://leetcode.com/problems/valid-palindrome/)
### a. 暴力解
1. 自己寫的,可complie但WA(花太多時間了先跳過,之後再找出問題在哪)
[參考連結](https://leetcode.com/problems/valid-palindrome/solutions/421055/go-golang-slow-and-fast-solutions/)
```
Example
Input: s = "race a car"
Output: false // my output: true
Explanation: "raceacar" is not a palindrome.
func isPalindrome(s string) bool {
ans := true
for _, text := range s {
var t string
if text >= 65 && text <= 90 { // A-Z
text = text + 32 // transform into lowercase
t += string(text)
}
if text >= 97 && text <= 122 { // a-z
t += string(text)
}
if text <= 48 && text <= 57 { // numbers
t += string(text)
}
if text < 65 || text > 122 { // non-alphanumeric cha
text = 32
}
if text < 90 && text < 97 { // non-alphanumeric cha
text = 32
}
for i := 0; i < len(t); i++ {
if t[i] != t[len(t)-1-i] {
ans = false
}
}
}
return ans
}
```
2. 照著解答寫還是WA,瘋了
```
import (
"fmt"
"strings"
)
func isPalindrome(s string) bool {
s = strings.ToLower(s)
str := " "
for _, c := range s {
if ('a' <= c && c <= 'z') || ('0' <= c && c<= '9') {
str += string(c)
}
}
if len(str) == 0 {
return true
}
i,j := 0, len(str)-1
for i <= j {
if str[i] != str[j] {
return false
}
i++
j--
}
return true
}
```
3. 解答
```
func isPalindrome(s string) bool {
str := ""
s = strings.ToLower(s)
for _, value := range s {
if (value >= '0' && value <= '9') || (value >= 'a' && value <= 'z') {
str += string(value)
}
}
if len(str) == 0 {
return true
}
i := 0
j := len(str)-1
for i <= j {
if str[i] != str[j] {
return false
}
i++
j--
}
return true
}
```
### b. iterative
1. 參考答案後寫出來的
[參考連結(「PDF下載」中的PDF)](https://github.com/willshang/go-leetcode)
```
import (
"fmt"
"strings"
)
func isPalindrome(s string) bool {
s = strings.ToLower(s)
i, j := 0, len(s)-1
for i < j {
for i < j && !isChar(s[i]) {
i++
}
for i < j && !isChar(s[j]) {
j--
}
if s[i] != s[j] {
return false
}
i++
j--
}
return true
}
func isChar(c byte) bool {
if ('a' <= c && c <= 'z') || ('0' <= c && c <= '9') {
return true
} else {
return false
}
}
```
## 20230216 (Day 5)
### 226. Invert Binary Tree 翻轉二元樹 [題目](https://leetcode.com/problems/invert-binary-tree/submissions/899118854/)
> 0-6M: Google, Amazon, Bloomberg, Adobe, Facebook
> 6M-1Y: Microsoft, Uber
> 1Y-2Y:LinkedIn, Baidu, eBay
### a. Recursion
1. 參考
[參考連結](https://leetcode.com/problems/invert-binary-tree/solutions/1932370/golang/)
[參考連結(「PDF下載」中的PDF)](https://github.com/willshang/go-leetcode)
```
func invertTree(root *TreeNode) *TreeNode {
if root == nil || (root.Left == nil && root.Right == nil) {
return root
}
root.Left, root.Right = invertTree(root.Right), invertTree(root.Left)
return root
}
```
2. 經過自己思考後寫出來的
[參考影片](https://www.youtube.com/watch?v=_Bx_IeZrEKg)
```
func invertTree(root *TreeNode) *TreeNode {
if root == nil || (root.Left == nil && root.Right == nil) {
return root
}
tmp := root.Left // 要嘛如前一個做法同時swap,不然就要暫存其中一個的值,否則非同時又沒有暫存的話原先的值會被蓋掉
root.Left= invertTree(root.Right)
root.Right = invertTree(tmp)
return root
}
```
### b.還沒看的另一種解法
1. 參考
[參考連結(「PDF下載」中的PDF)](https://github.com/willshang/go-leetcode)
(實際跑過,compile error)
### 心得
神奇,很神奇,一直不太知道recursion怎麼跑的,雖然寫出來了,但還要再多思考幾次。
## 20230217 (Day6)
### :heavy_check_mark: 242. Valid Anagram 可靠的異位詞 [題目](https://leetcode.com/problems/valid-anagram/)
### a.
1. 自己寫的!!!
[語法參考連結](https://stackoverflow.com/questions/22688651/golang-how-to-sort-string-or-byte)
```
import (
"fmt"
"sort"
"strings"
)
func isAnagram(s string, t string) bool {
s_sorted := SortString(s)
t_sorted := SortString(t)
if s_sorted == t_sorted {
return true
} else { return false }
}
func SortString(s string) string {
w := strings.Split(s, "") // string to []string
sort.Strings(w) // sort
return strings.Join(w, "") // []string to string
}
```
### 704. Binary Search 二元搜尋 [題目](https://leetcode.com/problems/binary-search/)
### a. 暴力解
1. 自己寫的(從中間開始搜尋,往上或往下找)(O(n))(TLE)
```
func search(nums []int, target int) int {
for i := len(nums)/2; i < len(nums); {
if target == nums[i] {
return i
} else if target < nums[i] {
i--
} else if target > nums[i] {
i++
}
}
return -1
}
```
2. 參考
很奇怪,這個做法看起來也是暴力解卻過了,沒有TLE?
```
func search(nums []int, target int) int {
if nums[0] > target || nums[len(nums)-1] < target {
return -1
}
for i := 0; i < len(nums); i++ {
if nums[i] == target {
return i
}
if nums[i] > target {
return -1
}
}
return -1
}
```
### b. Recursion
1. 參考(swith)
```
func search(nums []int, target int) int {
l, r := 0, len(nums)-1
for l <= r {
mid := (l+r)/2
switch {
case target < nums[mid]:
r = mid - 1
case target > nums[mid]:
l = mid + 1
default:
return mid
}
}
return -1
}
```
2. 自己將switch改成if-else
> 技巧:
> 1. 一定要寫l <= r而不能寫l<r,否則nums = [5], target = 5的例子中會return -1,但其實答案是0
> 2. mid一定要放在for loop裏面,以便隨著l, r的值一起變動
```
func search(nums []int, target int) int {
l := 0, r := len(nums)-1
for l <= r {
mid := (l+r)/2 // write in the for loop to be dynamic
if target < nums[mid] {
r = mid - 1
} else if target > nums[mid] {
l = mid + 1
} else {
return mid
}
}
return -1
}
```
## 20230218 (Day7)
### :heavy_check_mark: 235. Lowest Common Ancestor of a Binary Search Tree 二元樹的最小祖先 [題目](https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-search-tree/description/)
### a. Recursive
1. 自己寫的!(弄清語法後一次AC)
```
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
if p.Val < root.Val && q.Val < root.Val {
return lowestCommonAncestor(root.Left, p, q)
} else if p.Val > root.Val && q.Val > root.Val {
return lowestCommonAncestor(root.Right, p, q)
} else {
return root
}
}
```
### b. Iterative
1. 看到可以用迭代後寫的
```
func lowestCommonAncestor(root, p, q *TreeNode) *TreeNode {
for root != nil {
if p.Val < root.Val && q.Val < root.Val {
root = root.Left
} else if p.Val > root.Val && q.Val > root.Val {
root = root.Right
} else {
return root
}
}
return root
}
```
### 心得
原本以為LCA of a BST很難,畢竟我才剛重新複習BST的架構與操作,看到題目時連要寫暴力解都不知道從哪著手。但我回到BST思考,覺得應該是要利用左邊節點比右邊小的特徵,接著一點一點列出p, q之間關係的所有可能,就發現規律其實很簡單。這也是我第一次自己寫出recursive的解法(雖然這題其實只有一種東西需要return,所以寫法很簡單),之前都只是知道概念而未操作過。一開始邏輯寫對了,但是p.Val和q.Val都只寫出p, q,所以一直得到無法進行比較的error,一開始以為問題在root.Val上,後來直接看了解答才知道要寫p.Val和q.Val,更改後就過了。
AC後很開心的跑去找媽咪告訴他,順便拉著他硬講解了一番,用我們家的例子解釋,居然解釋通了!我超棒!
後來發現另一個做法也很簡單,邏輯相同,只是把寫法改成iterative而已,所以很快看完後自己也寫出來了。
一開始多寫了兩行
```
if p.Val == root.Val { return p }
if q.Val == root.Val { return q }
```
後來看到解答其他部分跟我寫的一模一樣,卻少了這兩行,思考一下才發現其實else已經包含了p,q的值與root的值相同的情況。else裡包含的情況有:1. p,q之中,一個小於root,一個大於root。2. p與root相同。3. q與root相同。
## 20230219 (Day8)
### 733. Flood Fill 填滿洪水[題目](https://leetcode.com/problems/flood-fill/)
### a.
1. (Not yet solved)
## 20230221 (Day9)
### 26. Remove Duplicates from Sorted Array 殺掉多出來的那個! [題目](https://leetcode.com/problems/remove-duplicates-from-sorted-array/description/)
### a. 指針(記數法)
1. 參考
[參考連結(「PDF下載」中的PDF)](https://github.com/willshang/go-leetcode)
概念:雙指針,數字前移
```
func removeDuplicates(nums []int) int {
count := 1
for i := 0; i < len(nums)-1; i++ {
if nums[i] != nums[i+1] {
nums[count] = nums[i+1]
count++
}
}
return count
}
```
### :heavy_check_mark: 27. Remove Element 殺掉元素 [題目](https://leetcode.com/problems/remove-element/description/)
### a. 指針
1. 自己寫的!(跟26題概念相同)
概念:雙指針,數字前移。一旦前面出現過要刪除的數字,後面的數字就算是要留下來的(跟val不相同),還是得往前挪。重點:找出要留下來的,把他們往前移。
```
func removeElement(nums []int, val int) int {
count := 0
for i := 0; i < len(nums); i++ {
if nums[i] != val {
nums[count] = nums[i]
count++
}
}
return count
}
```
2. 雙指針,最後的數字往前移(尚不太懂最後為什麼return r而非r-1)
```
func removeElement(nums []int, val int) int {
l, r := 0, len(nums)
for l < r {
if nums[l] == val {
nums[l] = nums[r-1]
r--
} else {
l++
}
}
return r // why not return r-1?
}
```
### :heavy_check_mark: 283. Move Zeros 移靈 [題目](https://leetcode.com/problems/move-zeroes/description/)
### a. 指針
1. 自己寫的!
```
func moveZeroes(nums []int) {
count := 0
for i := 0; i < len(nums); i++{
if nums[i] != 0 {
if count != i {
nums[count] = nums[i]
nums[i] = 0
count++
} else {
nums[count] = nums[i]
count++
}
}
}
}
```
2. 參考答案後的優化
[參考連結](https://books.halfrost.com/leetcode/ChapterFour/0200~0299/0283.Move-Zeroes/)
```
func moveZeroes(nums []int) {
count := 0
for i := 0; i < len(nums); i++{
if nums[i] != 0 {
if count != i {
nums[count], nums[i] = nums[i], nums[count]
}
count++
}
}
}
```
### 2460. Apply Operation to an Array 操作數組 [題目](https://leetcode.com/problems/apply-operations-to-an-array/description/)
### a. 指針
1. (Not yet solved)(感覺跟前幾題很像,但卡住了寫不出來,網路上的講解極少)
## 20230222 (Day10)
### 110. Balanced Binary Tree 平衡二叉樹 [題目](https://leetcode.com/problems/balanced-binary-tree/description/)
### a. dfs
1. 參考後寫出來,熟悉度尚不高
```
func isBalanced(root *TreeNode) bool {
return dfs(root) != -1
}
func dfs(root *TreeNode) int {
if root == nil {
return 0
}
left := dfs(root.Left)
right := dfs(root.Right)
if left != -1 && right != -1 && abs(left, right) <= 1 {
return max(left, right) + 1
} else {
return -1
}
}
func abs(a, b int) int {
if a > b {
return a - b
} else {
return b - a
}
}
func max(a, b int) int {
if a > b {
return a
} else {
return b
}
}
```
### 141. Linked List Cycle 鏈表環 [題目](https://leetcode.com/problems/linked-list-cycle/description/)
相似題目:142. Linked List Cycle 2
### a. 指針
1. 參考
[參考連結](https://books.halfrost.com/leetcode/ChapterFour/0100~0199/0141.Linked-List-Cycle/)
```
/**
* Definition for singly-linked list.
* type ListNode struct {
* Val int
* Next *ListNode
* }
*/
func hasCycle(head *ListNode) bool {
fast := head
slow := head
for fast != nil && fast.Next != nil {
fast = fast.Next.Next
slow = slow.Next
if fast == slow {
return true
}
}
return false
}
```
## 20230223 (Day11)
### 232. Implement Queue using Stacks 用堆實現棧 [題目](https://leetcode.com/problems/implement-queue-using-stacks/description/)
### a. slice
1. 參考
```
type MyQueue struct {
a []int
}
func Constructor() MyQueue {
return MyQueue{}
}
func (this *MyQueue) Push(x int) {
this.a = append(this.a, x)
}
func (this *MyQueue) Pop() int {
first := this.a[0]
this.a = this.a[1:]
return first
}
func (this *MyQueue) Peek() int {
if len(this.a) == 0 {
return 0
}
return this.a[0]
}
func (this *MyQueue) Empty() bool {
if len(this.a) == 0 {
return true
}
return false
}
```
### b. 2 stacks
1. 參考
```
type MyQueue struct {
a, b *Stack
}
func Constructor() MyQueue {
return MyQueue{
a : NewStack(),
b : NewStack(),
}
}
func (this *MyQueue) Push(x int) {
this.a.Push(x)
}
func (this *MyQueue) Pop() int {
if this.b.Len() == 0 {
for this.a.Len() > 0 {
this.b.Push(this.a.Pop())
}
}
return this.b.Pop()
}
func (this *MyQueue) Peek() int {
res := this.Pop()
this.b.Push(res)
return res
}
func (this *MyQueue) Empty() bool {
return this.a.Len() == 0 && this.b.Len() == 0
}
type Stack struct {
nums []int
}
func NewStack() *Stack {
return &Stack {
nums: []int{},
}
}
func (s *Stack) Push(n int) {
s.nums = append(s.nums, n)
}
func (s *Stack) Pop() int {
res := s.nums[len(s.nums)-1]
s.nums = s.nums[:len(s.nums)-1]
return res
}
func (s *Stack) Len() int {
return len(s.nums)
}
func (s *Stack) IsEmpty() bool {
return s.Len() == 0
}
```
## 20230227 (Day)
### 383. Ransom Note 勒索信 [題目](https://leetcode.com/problems/ransom-note/description/)
### :heavy_check_mark: a. map
1. 自己寫的!
```
import (
"fmt"
// "sort"
"strings"
)
func canConstruct(ransomNote string, magazine string) bool {
// magazine = SortString(magazine)
my_map := make(map[rune]rune)
for _, m := range magazine {
if _, exist := my_map[m]; exist {
my_map[m] = (my_map[m])+1
} else {
my_map[m] = 1
}
}
for _, r := range ransomNote {
if _, exist := my_map[r]; exist {
if my_map[r] == 1 {
delete(my_map, r)
} else {
my_map[r] = (my_map[r])-1
}
} else {
return false
}
}
return true
}
// func SortString(s string) string {
// w := strings.Split(s, "") // string to []string
// sort.Strings(w) // sort
// return strings.Join(w, "") // []string to string
// }
```
### b. array
[參考連結](https://github.com/halfrost/LeetCode-Go/tree/master/leetcode/0383.Ransom-Note)
```
func canConstruct(ransomNote string, magazine string) bool {
if len(ransomNote) > len(magazine) {
return false
}
var cnt [26]int
for _, v := range magazine {
cnt[v-'a']++
}
for _, v := range ransomNote {
cnt[v-'a']--
if cnt[v-'a'] < 0 {
return false
}
}
return true
}
```
### 心得
## 20230228 (Day)
### 70. Climbling Stairs 爬樓梯 [題目](https://leetcode.com/problems/climbing-stairs/)
### a. 動態規劃
1. 參考
[費波那契數列](https://www.csie.ntu.edu.tw/~b98902112/cpp_and_algo/cpp02/fibonacci.html)
```
// Time: O(n), Space: O(n)
func climbStairs(n int) int {
if n == 1 {
return 1
}
if n == 2 {
return 2
}
dp := make([]int, n+1)
dp[1] = 1
dp[2] = 2
for i := 3; i <= n; i++ {
dp[i] = dp[i-1] + dp[i-2]
}
return dp[n]
}
```
### :heavy_check_mark: 409. Longest Palindrome 最長回文 [題目](https://leetcode.com/problems/longest-palindrome/)
### a. 暴力解
1. 自己寫的
```
func longestPalindrome(s string) int {
if len(s) == 0 {
return 0
}
if len(s) == 1 {
return 1
}
var pal [60]int
cnt := 0
ones := 0
dup := 0
for _, s := range s {
pal[s-'A']++
}
for _, t := range pal {
if t % 2 == 0 { // t is even
cnt += t
} else if t == 1 {
ones -= 1
} else {
cnt += t - 1
dup += 1
}
}
if dup > 0 {
return cnt + 1
} else if dup == 0 && ones < 0 {
return cnt + 1
} else {
return cnt
}
}
```
### 206. Reverse Linked List 翻轉鏈表 [題目](https://leetcode.com/problems/reverse-linked-list/)
### Recursive
1. 參考(尚未理解)
[參考連結](https://algorithm.yuanbin.me/zh-tw/linked_list/reverse_linked_list.html)
[參考連結](https://ithelp.ithome.com.tw/articles/10271920)
```
func reverseList(head *ListNode) *ListNode {
if head == nil || head.Next == nil {
return head
}
result := reverseList(head.Next)
head.Next.Next = head
head.Next = nil
return result
}
```
### :heavy_check_mark: 169. Majority Element [題目](https://leetcode.com/problems/majority-element/description/)
### Array
1. 自己寫的
```
func majorityElement(nums []int) int {
var temp1 [10000]int // positives
var temp2 [10000]int // negatives
for _, i := range nums {
if i < 0 {
temp2[-i]++
} else {
temp1[i]++
}
}
for idx, i := range temp1 {
if i > len(nums)/2 {
return idx
}
}
for idx, i := range temp2 {
if i > len(nums)/2 {
return -idx
}
}
return -1
}
```
## 20230301 (Day)
### 876. Middle of the Linked List [題目](https://leetcode.com/problems/middle-of-the-linked-list/)
### a. Pointer
1.
```
func middleNode(head *ListNode) *ListNode {
slow, fast := head, head
for fast != nil && fast.Next != nil {
slow = slow.Next
fast = fast.Next.Next
}
return slow
}
```
## 20230302 (Day)
### 104. Maximun Depth of Binary Tree 二元樹的最大深度 [題目](https://leetcode.com/problems/maximum-depth-of-binary-tree/description/)
### a. Recursive
1.
```
func maxDepth(root *TreeNode) int {
if root == nil {
return 0
}
left := maxDepth(root.Left)
right := maxDepth(root.Right)
return max(left, right) + 1
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
```
## 20230303 (Day)
### :heavy_check_mark: 217. Contains Duplicate 包含重複 [題目](https://leetcode.com/problems/contains-duplicate/)
### a. Iteration
1.
```
func containsDuplicate(nums []int) bool {
sort.Ints(nums)
for i := 1; i < len(nums); i++ {
if nums[i-1] == nums[i] {
return true
} else {
continue
}
}
return false
}
```
### b. Map
1.
```
// Time: O(n), Space: O(n)
func containsDuplicate(nums []int) bool {
my_map := make(map[int]int)
for _, v := range nums{
if _, exist := my_map[v]; exist {
return true
} else {
my_map[v] = v
}
}
return false
}
```
### :heavy_check_mark: 219. Contains Duplicate 2 包含重複2 [題目](https://leetcode.com/problems/contains-duplicate-ii/description/)
### a. Map
1.
```
func containsNearbyDuplicate(nums []int, k int) bool {
my_map := make(map[int]int)
for idx, v := range nums {
if _, exist := my_map[v]; exist {
if idx - my_map[v] <= k {
return true
} else {
my_map[v] = idx
}
} else {
my_map[v] = idx
}
}
return false
}
```
## 20230304 (Day)
### 13. Roman to Integer 羅馬數字翻譯 [題目](https://leetcode.com/problems/roman-to-integer/description/)
### a. Iteration
1. Bobby陪我一起寫完的
```
func romanToInt(s string) int {
w := strings.Split(s, "") // slice to []string
cnt := 0
for i := 0; i < len(w); i++ {
if i != len(w)-1 {
if w[i] == "I" && w[i+1] == "V" {
cnt += 4
i++
continue
}
if w[i] == "I" && w[i+1] == "X" {
cnt += 9
i++
continue
}
if w[i] == "X" && w[i+1] == "L" {
cnt += 40
i++
continue
}
if w[i] == "X" && w[i+1] == "C" {
cnt += 90
i++
continue
}
if w[i] == "C" && w[i+1] == "D" {
cnt += 400
i++
continue
}
if w[i] == "C" && w[i+1] == "M" {
cnt += 900
i++
fmt.Println(cnt, i)
continue
}
}
if w[i] == "I" { cnt += 1 }
if w[i] == "V" { cnt += 5 }
if w[i] == "X" { cnt += 10}
if w[i] == "L" { cnt += 50 }
if w[i] == "C" { cnt += 100 }
if w[i] == "D" { cnt += 500 }
if w[i] == "M" { cnt += 1000 }
}
return cnt
}
```
## 20230305 (Day)
### :heavy_check_mark: 844. Backspace String Compare [題目](https://leetcode.com/problems/backspace-string-compare/description/)
### a. Stack
1.
```
import (
"fmt"
"strings"
)
func backspaceCompare(s string, t string) bool {
ss := strings.Split(s, "")
tt := strings.Split(t, "")
var stack_s []string
var stack_t []string
for i := 0; i < len(ss); i++ {
if ss[i] != "#" {
stack_s = append(stack_s, ss[i])
} else {
if len(stack_s) != 0 {
stack_s = stack_s[:len(stack_s)-1]
} else {
continue
}
}
}
for i := 0; i < len(tt); i++ {
if tt[i] != "#" {
stack_t = append(stack_t, tt[i])
} else {
if len(stack_t) != 0 {
stack_t = stack_t[:len(stack_t)-1]
} else {
continue
}
}
}
// fmt.Println(stack_s)
// fmt.Println(stack_t)
for i := 0; i < max(len(stack_t), len(stack_s)); i++ {
if len(stack_s) != len(stack_t) {
return false
} else if stack_s[i] != stack_t[i] {
return false
}
}
return true
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
```
b. 將if-else判斷式獨立寫成function
```
func backspaceCompare(s string, t string) bool {
return check(s) == check(t)
}
func check(str string) string {
res := make([]string, 0)
for _, v := range str {
if string(v) != "#" {
res = append(res, string(v))
} else if string(v) == "#" {
if len(res) != 0 {
res = res[:len(res)-1]
}
}
}
// fmt.Println(res)
return strings.Join(res, "")
}
```
### :heavy_check_mark: 338. Counting Bits 計算二進位 [題目](https://leetcode.com/problems/counting-bits/description/)
### a.
1.
```
func countBits(n int) []int {
res := make([]int, n+1)
for i := range res {
// fmt.Println(i, toBinary(i))
res[i] = toBinary(i)
}
return res
}
func toBinary(n int) int {
cnt := 0
for n >= 2 {
if n % 2 == 1 {
cnt += 1
}
n = n / 2
}
if n == 1 { cnt += 1 }
return cnt
}
```
### 心得
寫Counting Bits時一直執著的覺得應該要用recursion,但怎麼樣都想不出來,腦中有種卡住通不過去的感覺,後來決定去看看其他以前寫過題目中有使用recursion的,發現這題其實只需要用for就好(因為是要由上往下的除2),因此清醒過來寫了個能計算一個數在除2時會有多少餘數是1的function(用短除法計算二進位),再分開寫進題目要求回傳的[]int就好。一開始的邏輯對了後,答案還是錯,仔細看了一下是寫進res時多寫了一堆零,改掉append到res的方式後就好了。
## 20230306
### QUENTREND
1.
```
package main
import (
"bufio"
"fmt"
"io"
"os"
"strconv"
"strings"
)
/*
* Complete the 'getTripletCount' function below.
*
* The function is expected to return an INTEGER.
* The function accepts following parameters:
* 1. INTEGER_ARRAY a
* 2. INTEGER d
*/
func getTripletCount(a []int32, d int32) int32 {
// Write your code here
a_int := make([]int, len(a))
for i := 0; i < len(a); i++ {
a_int[i] = int(a[i])
}
d_int := int(d)
cnt := 0
for i := 0; i < len(a_int); i++ {
for j := i+1; j < len(a_int); j++ {
for k := j+1; k < len(a_int); k++ {
if (a_int[i] + a_int[j] + a_int[k]) % d_int == 0 {
if i != j && i != k && j != k {
cnt += 1
}
}
}
}
}
return int32(cnt)
}
func main() {
reader := bufio.NewReaderSize(os.Stdin, 16 * 1024 * 1024)
stdout, err := os.Create(os.Getenv("OUTPUT_PATH"))
checkError(err)
defer stdout.Close()
writer := bufio.NewWriterSize(stdout, 16 * 1024 * 1024)
aCount, err := strconv.ParseInt(strings.TrimSpace(readLine(reader)), 10, 64)
checkError(err)
var a []int32
for i := 0; i < int(aCount); i++ {
aItemTemp, err := strconv.ParseInt(strings.TrimSpace(readLine(reader)), 10, 64)
checkError(err)
aItem := int32(aItemTemp)
a = append(a, aItem)
}
dTemp, err := strconv.ParseInt(strings.TrimSpace(readLine(reader)), 10, 64)
checkError(err)
d := int32(dTemp)
result := getTripletCount(a, d)
fmt.Fprintf(writer, "%d\n", result)
writer.Flush()
}
func readLine(reader *bufio.Reader) string {
str, _, err := reader.ReadLine()
if err == io.EOF {
return ""
}
return strings.TrimRight(string(str), "\r\n")
}
func checkError(err error) {
if err != nil {
panic(err)
}
}
```
2.
```
package main
import (
"bufio"
"fmt"
"io"
"os"
"strconv"
"strings"
)
/*
* Complete the 'getMaximumSumOfHeights' function below.
*
* The function is expected to return a LONG_INTEGER.
* The function accepts INTEGER_ARRAY maxHeight as parameter.
*/
import (
"sort"
)
func getMaximumSumOfHeights(maxHeight []int32) int64 {
// Write your code here
MH := make([]int, len(maxHeight))
for i := 0; i < len(maxHeight); i++ {
MH[i] = int(maxHeight[i])
}
cmp := make([]int, len(MH))
for i := 1; i < len(MH)-1; i++ {
if MH[i] > MH[i-1] && MH[i] > MH[i+1] {
cmp[i] = MH[i]
}
}
sort.Sort(cmp)
max := cmp[len(cmp)-1]
cnt := 0
my_map := make(map[int]int)
for i := range MH {
my_map[i] = MH[i]
}
for i := 1; i < len(MH)-1; i++ {
if i, exist := my_map[i]; exist {
if i != max {
MH[i] = return_max(MH[i-1], MH[i+1])
}
}
cnt += MH[i]
}
return int64(cnt)
}
func return_max(a, b int) int {
if a > b {
return a
}
return b
}
func main() {
reader := bufio.NewReaderSize(os.Stdin, 16 * 1024 * 1024)
stdout, err := os.Create(os.Getenv("OUTPUT_PATH"))
checkError(err)
defer stdout.Close()
writer := bufio.NewWriterSize(stdout, 16 * 1024 * 1024)
maxHeightCount, err := strconv.ParseInt(strings.TrimSpace(readLine(reader)), 10, 64)
checkError(err)
var maxHeight []int32
for i := 0; i < int(maxHeightCount); i++ {
maxHeightItemTemp, err := strconv.ParseInt(strings.TrimSpace(readLine(reader)), 10, 64)
checkError(err)
maxHeightItem := int32(maxHeightItemTemp)
maxHeight = append(maxHeight, maxHeightItem)
}
result := getMaximumSumOfHeights(maxHeight)
fmt.Fprintf(writer, "%d\n", result)
writer.Flush()
}
func readLine(reader *bufio.Reader) string {
str, _, err := reader.ReadLine()
if err == io.EOF {
return ""
}
return strings.TrimRight(string(str), "\r\n")
}
func checkError(err error) {
if err != nil {
panic(err)
}
}
```
3.
```
package main
import (
"bufio"
"fmt"
"io"
"os"
"strconv"
"strings"
)
/*
* Complete the 'countInvestablePeriods' function below.
*
* The function is expected to return a LONG_INTEGER.
* The function accepts following parameters:
* 1. INTEGER_ARRAY price
* 2. INTEGER max_price
* 3. INTEGER min_price
*/
func countInvestablePeriods(price []int32, max_price int32, min_price int32) int64 {
// Write your code here
p_int := make([]int, 0)
for i := 0; i < len(price); i++ {
p_int[i] = int(price[i])
}
maxp_int := int(max_price)
minp_int := int(min_price)
res := make([]int, len(p_int))
cnt := 0
for _, v := range p_int {
if v > minp_int && v < maxp_int {
res = append(res, v)
} else if v < minp_int || v > maxp_int {
if len(res) < 2 {
res = nil
} else {
cnt += countSubarray(res, maxp_int, minp_int)
res = nil
}
}
}
cnt += countSubarray(res, maxp_int, minp_int)
return int64(cnt)
}
func countSubarray(arr []int, max int, min int) int {
max_cnt := 0
min_cnt := 0
max_map := make([]int, len(arr))
min_map := make([]int, len(arr))
cnt := 0
for idx, v := range arr {
if v == max {
max_cnt += 1
max_map = append(max_map, idx)
} else if v == min {
min_cnt += 1
min_map = append(min_map, idx)
}
}
if max_cnt == 0 || min_cnt == 0 {
return 0
}
cnt += (factorial(max_cnt) / factorial(max_cnt-1) * factorial(1)) * (factorial(min_cnt) / factorial(min_cnt-1) * factorial(1))
return cnt
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func factorial(num int) int{
if num == 1 || num == 0{
return num
}
return num * factorial(num-1)
}
func main() {
reader := bufio.NewReaderSize(os.Stdin, 16 * 1024 * 1024)
stdout, err := os.Create(os.Getenv("OUTPUT_PATH"))
checkError(err)
defer stdout.Close()
writer := bufio.NewWriterSize(stdout, 16 * 1024 * 1024)
priceCount, err := strconv.ParseInt(strings.TrimSpace(readLine(reader)), 10, 64)
checkError(err)
var price []int32
for i := 0; i < int(priceCount); i++ {
priceItemTemp, err := strconv.ParseInt(strings.TrimSpace(readLine(reader)), 10, 64)
checkError(err)
priceItem := int32(priceItemTemp)
price = append(price, priceItem)
}
max_priceTemp, err := strconv.ParseInt(strings.TrimSpace(readLine(reader)), 10, 64)
checkError(err)
max_price := int32(max_priceTemp)
min_priceTemp, err := strconv.ParseInt(strings.TrimSpace(readLine(reader)), 10, 64)
checkError(err)
min_price := int32(min_priceTemp)
result := countInvestablePeriods(price, max_price, min_price)
fmt.Fprintf(writer, "%d\n", result)
writer.Flush()
}
func readLine(reader *bufio.Reader) string {
str, _, err := reader.ReadLine()
if err == io.EOF {
return ""
}
return strings.TrimRight(string(str), "\r\n")
}
func checkError(err error) {
if err != nil {
panic(err)
}
}
```
4.
```
```
### 100. Same Tree 同樣的樹 [題目](https://leetcode.com/problems/same-tree/)
### a. recursive
1.
```
/**
* Definition for a binary tree node.
* type TreeNode struct {
* Val int
* Left *TreeNode
* Right *TreeNode
* }
*/
func isSameTree(p *TreeNode, q *TreeNode) bool {
if p == nil && q == nil {
return true
}
if p == nil || q == nil {
return false
}
return p.Val == q.Val && isSameTree(p.Left, q.Left) && isSameTree(p.Right, q.Right)
}
```
### :heavy_check_mark: 1539. Kth Missing Positive Number 第K個消失的正整數 [題目](https://leetcode.com/problems/kth-missing-positive-number/)
1.
```
func findKthPositive(arr []int, k int) int {
my_map := make(map[int]int)
res := make([]int, 0)
for _, v := range arr {
my_map[v] = v
}
for i := 1; i < 10000; i++ {
if _, exist := my_map[i]; !exist {
res = append(res, i)
}
}
// fmt.Println(res)
return res[k-1]
}
```
## 20230307 (Day1)
### 1. Number of 1 Bits [題目](https://leetcode.com/problems/number-of-1-bits/description/)
### a. / 2 (or n >> 1)
1.
```
func hammingWeight(num uint32) int {
cnt := 0
for num != 0 {
if num & 1 == 1 {
cnt++
}
num /= 2 // num = num / 2
}
return cnt
}
```
2.
```
func hammingWeight(num uint32) int {
cnt := 0
for num != 0 {
if num & 1 == 1 { // check the last digit of num
cnt++
}
num >>= 1 // num = num >> 1
}
return cnt
}
```
### b. n & (n-1)
1.
```
func hammingWeight(num uint32) int {
cnt := 0
for num != 0 {
num = num & (num-1)
cnt ++
}
return cnt
}
```
## 20230211 (Day1)
### 1. Two Sum 二和 [題目](https://leetcode.com/problems/two-sum/)
### a. 暴力解