diff --git a/Week5/23 AC.png b/Week5/23 AC.png new file mode 100644 index 0000000..b175f30 Binary files /dev/null and b/Week5/23 AC.png differ diff --git a/Week5/23 Merge k Sorted Lists.md b/Week5/23 Merge k Sorted Lists.md new file mode 100644 index 0000000..bb250d7 --- /dev/null +++ b/Week5/23 Merge k Sorted Lists.md @@ -0,0 +1,148 @@ +# 23. Merge k Sorted List + +## Intuition + +To merge k sorted linked lists efficiently, we can use a min heap (priority queue) to always get the smallest element among all lists. This approach allows us to maintain a sorted order while merging the lists. + +## Approach + +1. Create a min heap to store the head nodes of all k lists +2. Initialize the heap with the first node from each list (if not nil) +3. Create a dummy node to build the result list +4. While the heap is not empty: + - Extract the minimum node from the heap + - Add it to the result list + - If the extracted node has a next node, push it back into the heap +5. Return the merged list + +## Complexity + +- Time complexity: O(N log k) +- Space complexity: O(k) + +## Keywords + +- Linked List +- Heap/Priority Queue +- Merge Sort + +## Code + +```go +/** + * Definition for singly-linked list. + * type ListNode struct { + * Val int + * Next *ListNode + * } + */ +type Comparator func(child, parent interface{}) bool +type heap struct { + Storage []interface{} + CmpFunc Comparator +} + +func NewHeap(cmpFunc Comparator) *heap { + return &heap { + Storage: append(make([]interface{}, 0), -1), + CmpFunc: cmpFunc, + } +} + +func (h *heap) Len() int { + return len(h.Storage) - 1 +} + +func (h *heap) IsEmpty() bool { + return h.Len() == 0 +} + +func (h *heap) cmp(child, parent interface{}) bool { + return h.CmpFunc(child, parent) +} + +func (h *heap) swap(x, y int) { + h.Storage[x], h.Storage[y] = h.Storage[y], h.Storage[x] +} + +func (h *heap) Top() (interface{}, error) { + if h.IsEmpty() { + return nil, errors.New("Heap is empty.") + } + return h.Storage[1], nil +} + +func (h *heap) Push(item interface{}) { + h.Storage = append(h.Storage, item) + now := h.Len() + for now / 2 > 0 && !h.cmp(h.Storage[now], h.Storage[now / 2]) { + h.swap(now, now / 2) + now /= 2 + } +} + +func (h *heap) Pop() (interface{}, error) { + top, err := h.Top() + if err != nil { + return nil, err + } + last := h.Len() + h.swap(1, last) + h.Storage = h.Storage[: last] + now := 1 + for now < last { + left, right := 0, 0 + if now * 2 < last && !h.cmp(h.Storage[now * 2], h.Storage[now]) { + left = now * 2 + } + if now * 2 + 1 < last && !h.cmp(h.Storage[now * 2 + 1], h.Storage[now]) { + right = now * 2 + 1 + } + + if left == 0 && right == 0 { + break + } else if left != 0 && right == 0 { + h.swap(now, left) + now = left + } else if left == 0 && right != 0 { + h.swap(now, right) + now = right + } else { + if h.cmp(h.Storage[left], h.Storage[right]) { + h.swap(now, right) + now = right + } else { + h.swap(now, left) + now = left + } + } + } + return top, nil +} + +func mergeKLists(lists []*ListNode) *ListNode { + if len(lists) == 0 { + return nil + } + cmpFunc := func(child, parent interface{}) bool { + return child.(*ListNode).Val > parent.(*ListNode).Val + } + hp := NewHeap(cmpFunc) + for _, node := range lists { + if node != nil { + hp.Push(node) + } + } + prev := &ListNode{Val: 0, Next: nil} + cur := prev + for !hp.IsEmpty() { + top, _ := hp.Pop() + cur.Next = top.(*ListNode) + cur = cur.Next + if next := top.(*ListNode).Next; next != nil { + hp.Push(next) + } + } + return prev.Next +} +``` diff --git a/Week5/912 AC.png b/Week5/912 AC.png new file mode 100644 index 0000000..0d367e2 Binary files /dev/null and b/Week5/912 AC.png differ diff --git a/Week5/912 Sort an Array.md b/Week5/912 Sort an Array.md new file mode 100644 index 0000000..b1ce4e9 --- /dev/null +++ b/Week5/912 Sort an Array.md @@ -0,0 +1,41 @@ +# 912. Sort an Array + +## Intuition + +We can use a counting sort approach with bucket sort, which is efficient for this specific range of numbers. + +## Approach + +1. Create a bucket array of size 100001 (to accommodate numbers from -50000 to 50000) +2. Count the frequency of each number by adding 50000 to the index (to handle negative numbers) +3. Reconstruct the sorted array by iterating through the bucket array and placing numbers back in their original positions + +## Complexity + +- Time complexity: O(n + k) +- Space complexity: O(k) + +## Keywords + +- Sorting +- Counting Sort +- Bucket Sort + +## Code + +```go +func sortArray(nums []int) []int { + bucket := make([]int, 100001) + for _, num := range nums { + bucket[num + 50000] += 1 + } + idx := 0 + for i, cnt := range bucket { + for cnt != 0 { + nums[idx] = i - 50000 + idx, cnt = idx + 1, cnt - 1 + } + } + return nums +} +```