|
| 1 | +module.exports = { |
| 2 | + logo: require("../imgs/hand-writing.svg"), |
| 3 | + title: "手撕算法", |
| 4 | + list: [ |
| 5 | + { |
| 6 | + text: "数组排序", |
| 7 | + problems: [ |
| 8 | + { |
| 9 | + id: "sort-an-array", |
| 10 | + title: "912. 排序数组", |
| 11 | + }, |
| 12 | + ], |
| 13 | + codes: [ |
| 14 | + { |
| 15 | + language: "py", |
| 16 | + text: ` |
| 17 | +# 1. 归并排序(推荐!其他排序方法都不推荐在竞赛中使用) |
| 18 | +# 归并排序乞丐版 |
| 19 | +class Solution: |
| 20 | + def sortArray(self, nums: List[int]) -> List[int]: |
| 21 | + def mergeSort(l, r): |
| 22 | + if l >= r: |
| 23 | + return |
| 24 | + mid = (l + r) // 2 |
| 25 | + mergeSort(l, mid) |
| 26 | + mergeSort(mid + 1, r) |
| 27 | + temp = [] |
| 28 | + i, j = l, mid + 1 |
| 29 | + while i <= mid and j <= r: |
| 30 | + if nums[i] < nums[j]: |
| 31 | + temp.append(nums[i]) |
| 32 | + i += 1 |
| 33 | + else: |
| 34 | + temp.append(nums[j]) |
| 35 | + j += 1 |
| 36 | + while i <= mid: |
| 37 | + temp.append(nums[i]) |
| 38 | + i += 1 |
| 39 | + while j <= r: |
| 40 | + temp.append(nums[j]) |
| 41 | + j += 1 |
| 42 | + nums[l : r + 1] = temp |
| 43 | +
|
| 44 | + mergeSort(0, len(nums) - 1) |
| 45 | + return nums |
| 46 | +# 归并排序优化版 |
| 47 | +class Solution: |
| 48 | + def sortArray(self, nums: List[int]) -> List[int]: |
| 49 | + temp = [0] * len(nums) |
| 50 | +
|
| 51 | + def mergeSort(l, r): |
| 52 | + if l >= r: |
| 53 | + return |
| 54 | + mid = (l + r) // 2 |
| 55 | + mergeSort(l, mid) |
| 56 | + mergeSort(mid + 1, r) |
| 57 | + i, j = l, mid + 1 |
| 58 | + k = 0 |
| 59 | + while i <= mid and j <= r: |
| 60 | + if nums[i] < nums[j]: |
| 61 | + temp[k] = nums[i] |
| 62 | + i += 1 |
| 63 | + else: |
| 64 | + temp[k] = nums[j] |
| 65 | + j += 1 |
| 66 | + k += 1 |
| 67 | + while i <= mid: |
| 68 | + temp[k] = nums[i] |
| 69 | + i += 1 |
| 70 | + k += 1 |
| 71 | + while j <= r: |
| 72 | + temp[k] = nums[j] |
| 73 | + j += 1 |
| 74 | + k += 1 |
| 75 | + nums[l : r + 1] = temp[: r - l + 1] |
| 76 | +
|
| 77 | + mergeSort(0, len(nums) - 1) |
| 78 | + return nums |
| 79 | +
|
| 80 | +# 2. 快速排序 |
| 81 | +# 快速排序乞丐版 |
| 82 | +class Solution: |
| 83 | + def sortArray(self, nums: List[int]) -> List[int]: |
| 84 | + temp = [0] * len(nums) |
| 85 | +
|
| 86 | + def quickSort(nums): |
| 87 | + if not nums: return [] |
| 88 | + pivot = nums[0] |
| 89 | + nums = nums[1:] |
| 90 | + l = quickSort([num for num in nums if num <= pivot]) |
| 91 | + r = quickSort([num for num in nums if num > pivot]) |
| 92 | + return l + [pivot] + r |
| 93 | +
|
| 94 | + return quickSort(nums) |
| 95 | +# 快速排序优化版 |
| 96 | +class Solution: |
| 97 | + def sortArray(self, nums: List[int]) -> List[int]: |
| 98 | + temp = [0] * len(nums) |
| 99 | +
|
| 100 | + def partition(l, r): |
| 101 | + pivot = nums[l] |
| 102 | +
|
| 103 | + while l < r: |
| 104 | + while l < r and nums[r] >= pivot: |
| 105 | + r -= 1 |
| 106 | + nums[l] = nums[r] |
| 107 | + while l < r and nums[l] <= pivot: |
| 108 | + l += 1 |
| 109 | + nums[r] = nums[l] |
| 110 | + nums[l] = pivot |
| 111 | + return l |
| 112 | +
|
| 113 | + def quickSort(l, r): |
| 114 | + if l >= r: |
| 115 | + return |
| 116 | + pivot = partition(l, r) |
| 117 | + quickSort(l, pivot - 1) |
| 118 | + quickSort(pivot + 1, r) |
| 119 | +
|
| 120 | + quickSort(0, len(nums) - 1) |
| 121 | + return nums |
| 122 | +
|
| 123 | +# 3. 插入排序 |
| 124 | +class Solution: |
| 125 | + def sortArray(self, nums: List[int]) -> List[int]: |
| 126 | + n = len(nums) |
| 127 | + for i in range(1, n): |
| 128 | + t = nums[i] |
| 129 | + j = i - 1 |
| 130 | + while j > -1 and nums[j] > t: |
| 131 | + nums[j + 1] = nums[j] |
| 132 | + j -= 1 |
| 133 | + nums[j + 1] = t |
| 134 | + return nums |
| 135 | +
|
| 136 | +# 4. 选择排序 |
| 137 | +class Solution: |
| 138 | + def sortArray(self, nums: List[int]) -> List[int]: |
| 139 | + n = len(nums) |
| 140 | + for i in range(n - 1): |
| 141 | + k = i |
| 142 | + for j in range(i + 1, n): |
| 143 | + if nums[j] < nums[k]: |
| 144 | + k = j |
| 145 | + nums[i], nums[k] = nums[k], nums[i] |
| 146 | + return nums |
| 147 | +
|
| 148 | +# 5. 冒泡排序 |
| 149 | +class Solution: |
| 150 | + def sortArray(self, nums: List[int]) -> List[int]: |
| 151 | + n = len(nums) |
| 152 | + for i in range(n): |
| 153 | + for j in range(i + 1, n): |
| 154 | + if nums[j] < nums[i]: |
| 155 | + nums[i], nums[j] = nums[j], nums[i] |
| 156 | + return nums |
| 157 | +
|
| 158 | + `, |
| 159 | + }, |
| 160 | + ], |
| 161 | + }, |
| 162 | + { |
| 163 | + text: "链表排序", |
| 164 | + problems: [ |
| 165 | + { |
| 166 | + id: "sort-list", |
| 167 | + title: "148. 排序链表", |
| 168 | + }, |
| 169 | + ], |
| 170 | + codes: [ |
| 171 | + { |
| 172 | + language: "py", |
| 173 | + text: ` |
| 174 | +# 1. 归并排序(推荐!其他排序方法都不推荐在竞赛中使用) |
| 175 | +class Solution: |
| 176 | + def sortList(self, head: ListNode) -> ListNode: |
| 177 | + def mergeSort(head: ListNode) -> ListNode: |
| 178 | + if not head or not head.next: |
| 179 | + return head |
| 180 | + dummyHead = ListNode(-1) |
| 181 | + dummyHead.next = head |
| 182 | + slow, fast = dummyHead, head |
| 183 | + while fast and fast.next: |
| 184 | + slow = slow.next |
| 185 | + fast = fast.next.next |
| 186 | + nxt = slow.next |
| 187 | + slow.next = None |
| 188 | + return merge(mergeSort(head), mergeSort(nxt)) |
| 189 | +
|
| 190 | + def merge(head1: ListNode, head2: ListNode) -> ListNode: |
| 191 | + dummyHead = ListNode(-1) |
| 192 | + temp, l1, l2 = dummyHead, head1, head2 |
| 193 | + while l1 and l2: |
| 194 | + if l1.val <= l2.val: |
| 195 | + temp.next = l1 |
| 196 | + l1 = l1.next |
| 197 | + else: |
| 198 | + temp.next = l2 |
| 199 | + l2 = l2.next |
| 200 | + temp = temp.next |
| 201 | + if l1: |
| 202 | + temp.next = l1 |
| 203 | + elif l2: |
| 204 | + temp.next = l2 |
| 205 | + return dummyHead.next |
| 206 | +
|
| 207 | + return mergeSort(head) |
| 208 | +# 2. 快速排序 |
| 209 | +class Solution: |
| 210 | + def sortList(self, head): |
| 211 | + # 最坏情况也是 n ^ 2 ,因此面试或者竞赛不建议使用 |
| 212 | + def quickSort(head, end): |
| 213 | + |
| 214 | + if head != end: |
| 215 | + pivot = partition(head, end) |
| 216 | + quickSort(head, pivot) |
| 217 | + quickSort(pivot.next, end) |
| 218 | +
|
| 219 | + def partition(head, end): |
| 220 | + # p1是写指针,p2是读指针 |
| 221 | + # 最终 p1 是大的链表的头, head 是小的链表的头 |
| 222 | + pivot_val = head.val |
| 223 | + p1, p2 = head, head.next |
| 224 | +
|
| 225 | + while p2 != end: |
| 226 | + if p2.val < pivot_val: |
| 227 | + # 相当于数组的 append 方法 |
| 228 | + p1 = p1.next |
| 229 | + p1.val, p2.val = p2.val, p1.val |
| 230 | + p2 = p2.next |
| 231 | + head.val, p1.val = p1.val, pivot_val |
| 232 | + return p1 |
| 233 | +
|
| 234 | + quickSort(head, None) |
| 235 | + return head |
| 236 | +# 3. 插入排序 |
| 237 | +class Solution: |
| 238 | + def sortList(self, head): |
| 239 | + if head == None or head.next == None: |
| 240 | + return head |
| 241 | +
|
| 242 | + dummy = ListNode(-1) |
| 243 | + dummy.next = head |
| 244 | + pre = dummy |
| 245 | + cur = head |
| 246 | + while cur: |
| 247 | + # 准备将 last 插入到合适位置 |
| 248 | + last = cur.next |
| 249 | + if last and last.val < cur.val: |
| 250 | + # 从 dummy 到 cur 线性遍历找第一个满足条件的位置并插入 |
| 251 | + while pre.next and pre.next.val < last.val: |
| 252 | + pre = pre.next |
| 253 | + tmp = pre.next |
| 254 | + pre.next = last |
| 255 | + cur.next = last.next # 别忘了这个,否则成环 |
| 256 | + last.next = tmp |
| 257 | + pre = dummy |
| 258 | + else: |
| 259 | + cur = last |
| 260 | +
|
| 261 | + return dummy.next |
| 262 | +# 4. 选择排序 |
| 263 | +class Solution: |
| 264 | + def sortList(self, head): |
| 265 | + temp = head |
| 266 | +
|
| 267 | + while temp: |
| 268 | + min_node = temp |
| 269 | + r = temp.next |
| 270 | + while r: |
| 271 | + if min_node.val > r.val: |
| 272 | + min_node = r |
| 273 | + r = r.next |
| 274 | + temp.val, min_node.val = min_node.val, temp.val |
| 275 | + temp = temp.next |
| 276 | + return head |
| 277 | +# 5. 冒泡排序 |
| 278 | +class Solution: |
| 279 | + def sortList(self, head): |
| 280 | + if not head: |
| 281 | + return None |
| 282 | + swaped = True |
| 283 | + while swaped: |
| 284 | + swaped = False |
| 285 | + temp = head |
| 286 | + while temp.next: |
| 287 | + if temp.val > temp.next.val: |
| 288 | + swaped = True |
| 289 | + temp.val, temp.next.val = temp.next.val, temp.val |
| 290 | + temp = temp.next |
| 291 | + return head |
| 292 | +
|
| 293 | + `, |
| 294 | + }, |
| 295 | + ], |
| 296 | + }, |
| 297 | + ], |
| 298 | + // link: "", |
| 299 | +}; |
0 commit comments