|
| 1 | +# LeetCode 讀書會第 19 次聚會 2021/01/12 |
| 2 | + |
| 3 | +leetcode 讀書會通知 |
| 4 | +1. 項目: 第 19 次聚會 |
| 5 | +2. 目的: 線上一起寫題目, 由有想法的人帶領, 先解題, 再看該題有趣的解法 |
| 6 | +3. 時間: 01/12 (二) 20:00 ~ 21:00 |
| 7 | +4. 地點: google meet 線上 (前 10 分鐘預備鏈接) |
| 8 | +5. 解題項目: [Linked list - classic problem 的最後一題 Remove Nth Node From End Of List](https://leetcode.com/explore/learn/card/linked-list/219/classic-problems/) |
| 9 | + |
| 10 | +6. 共筆: GitHub https://github.com/programmingbookclub/Leetcode-club |
| 11 | + |
| 12 | +通知 9 人: @游諭, @turtle, @james, @Louis, @TzuHsuan |
| 13 | + |
| 14 | +備註: 這次的題目是: |
| 15 | + |
| 16 | + |
| 17 | +1. 203 - easy: Remove Linked List Elements |
| 18 | +2. 328 - Medium: Odd Even Linked List |
| 19 | +3. 234 - easy:Palindrome Linked List |
| 20 | + |
| 21 | + |
| 22 | +請在 issue 回報一下,我會把你加入 contribution |
| 23 | + |
| 24 | +https://zh.wikipedia.org/wiki/差一错误 |
| 25 | + |
| 26 | +# Remove Linked List Elements |
| 27 | + |
| 28 | +```swift |
| 29 | +// swift |
| 30 | + func removeElements(_ head: ListNode?, _ val: Int) -> ListNode? { |
| 31 | + let dummy = ListNode(0, head) |
| 32 | + var prev: ListNode? = dummy |
| 33 | + var current: ListNode? = head |
| 34 | + |
| 35 | + while(current != nil) { |
| 36 | + if current?.val == val { // 檢查 val |
| 37 | + prev?.next = current?.next |
| 38 | + } else { |
| 39 | + prev = current // 更新 prev |
| 40 | + } |
| 41 | + current = current?.next // 往後走 |
| 42 | + } |
| 43 | + return dummy.next |
| 44 | +} |
| 45 | +``` |
| 46 | + |
| 47 | +```swift |
| 48 | +// swift |
| 49 | +/** |
| 50 | + * Definition for singly-linked list. |
| 51 | + * public class ListNode { |
| 52 | + * public var val: Int |
| 53 | + * public var next: ListNode? |
| 54 | + * public init() { self.val = 0; self.next = nil; } |
| 55 | + * public init(_ val: Int) { self.val = val; self.next = nil; } |
| 56 | + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } |
| 57 | + * } |
| 58 | + */ |
| 59 | +class Solution { |
| 60 | + func removeElements(_ head: ListNode?, _ val: Int) -> ListNode? { |
| 61 | + let dummy = ListNode(val &+ 1, head) |
| 62 | + var current: ListNode? = dummy |
| 63 | + |
| 64 | + while(current != nil) { |
| 65 | + |
| 66 | + if current?.next?.val == val { // 檢查 val |
| 67 | + current?.next = current?.next?.next |
| 68 | + } else { |
| 69 | + current = current?.next // 往後走 |
| 70 | + } |
| 71 | + } |
| 72 | + return dummy.next |
| 73 | + } |
| 74 | +} |
| 75 | +``` |
| 76 | + |
| 77 | +# Odd Even Linked List |
| 78 | + |
| 79 | + |
| 80 | +# Palindrome Linked List |
| 81 | + |
| 82 | +## Recursive |
| 83 | + |
| 84 | +```swift= |
| 85 | +// swift |
| 86 | +/** |
| 87 | + * Definition for singly-linked list. |
| 88 | + * public class ListNode { |
| 89 | + * public var val: Int |
| 90 | + * public var next: ListNode? |
| 91 | + * public init() { self.val = 0; self.next = nil; } |
| 92 | + * public init(_ val: Int) { self.val = val; self.next = nil; } |
| 93 | + * public init(_ val: Int, _ next: ListNode?) { self.val = val; self.next = next; } |
| 94 | + * } |
| 95 | + */ |
| 96 | +class Solution { |
| 97 | + /* |
| 98 | + |
| 99 | + 1 |
| 100 | + 11 |
| 101 | + 121 2 11 |
| 102 | + 1221 22 11 |
| 103 | + 1231 23 11 |
| 104 | + */ |
| 105 | + func isPalindrome(_ head: ListNode?) -> Bool { |
| 106 | + var ptr: ListNode? = head |
| 107 | + func helper(_ head: ListNode?) -> Bool { |
| 108 | + if head == nil {return true} |
| 109 | + if helper(head?.next) == false {return false} |
| 110 | + if (head?.val != ptr?.val) {return false} |
| 111 | + ptr = ptr?.next |
| 112 | + return true |
| 113 | + } |
| 114 | +
|
| 115 | + return helper(head) |
| 116 | + } |
| 117 | +} |
| 118 | +``` |
| 119 | + |
| 120 | +## Iterative & in-place |
| 121 | + |
| 122 | +遍歷整個 List 3 次 |
| 123 | +1. 計算長度 |
| 124 | +2. 反轉後半段 |
| 125 | +3. Two pointer 從兩端檢查是否相同 |
| 126 | + |
| 127 | +```typescript= |
| 128 | +// TypeScript |
| 129 | +
|
| 130 | +/** |
| 131 | + Iterative & in-place |
| 132 | + time: O(3n) = O(n), space: O(1) |
| 133 | +*/ |
| 134 | +function isPalindrome(head: ListNode | null): boolean { |
| 135 | + // 算出長度 |
| 136 | + const length = getListLength(head); |
| 137 | + if (length <= 1) return true; |
| 138 | + // 反轉後半段,並額外考慮長度為偶數的情況 |
| 139 | + const middleNode = getNthNode(head, Math.ceil(length / 2)); |
| 140 | + const anotherHead = length % 2 === 0 ? reverseList(middleNode.next) : reverseList(middleNode); |
| 141 | + middleNode.next = null; |
| 142 | + // Two pointer 從兩端檢查是否相同 |
| 143 | + return isSameList(head, anotherHead); |
| 144 | +}; |
| 145 | +
|
| 146 | +// 以下為輔助函式 |
| 147 | +function isSameList(headA: ListNode, headB: ListNode): boolean { |
| 148 | + let currA = headA; |
| 149 | + let currB = headB; |
| 150 | + while(currA != null) { |
| 151 | + if (currA.val !== currB.val) return false; |
| 152 | + currA = currA.next; |
| 153 | + currB = currB.next; |
| 154 | + } |
| 155 | + if (currB == null) return true; |
| 156 | + else return false; |
| 157 | +} |
| 158 | +
|
| 159 | +function getListLength(head: ListNode): number { |
| 160 | + let count = 0; |
| 161 | + let curr = head; |
| 162 | + while(curr != null) { |
| 163 | + count++; |
| 164 | + curr = curr.next; |
| 165 | + } |
| 166 | + return count; |
| 167 | +} |
| 168 | +
|
| 169 | +function getNthNode(head: ListNode, n: number): ListNode { |
| 170 | + if (head == null || !Number.isInteger(n) || n < 1) return null; |
| 171 | + let count = 1; |
| 172 | + let curr = head; |
| 173 | + while(count < n) { |
| 174 | + curr = curr?.next; |
| 175 | + count++; |
| 176 | + } |
| 177 | + return curr; |
| 178 | +} |
| 179 | +
|
| 180 | +/** Iteratively */ |
| 181 | +function reverseList(head: ListNode | null): ListNode | null { |
| 182 | + if (!head) return null; |
| 183 | + let curr = head; |
| 184 | + let prev: ListNode = null; |
| 185 | + let next: ListNode = null; |
| 186 | + while(curr) { |
| 187 | + next = curr.next ?? null; |
| 188 | + curr.next = prev; |
| 189 | + prev = curr; |
| 190 | + curr = next; |
| 191 | + } |
| 192 | + return prev; |
| 193 | +}; |
| 194 | +``` |
| 195 | + |
| 196 | + |
| 197 | + |
| 198 | + |
| 199 | + |
| 200 | +比較了 Recursive vs Iterative |
| 201 | + |
| 202 | +Runtime: 92 vs 100 ms |
| 203 | + |
| 204 | +Memory: 45.7 vs 42.3 MB |
| 205 | + |
0 commit comments