[Go version] Algorithmic Clearance Village 14th Level Silver—Classic problems solved efficiently by heaps (find the Kth largest element in an array, heap sort, merge K sorted linked lists)

Topic: Find the Kth largest element in an array

Topic link: LeetCode-215. The Kth largest element in an array
insert image description here

Solution 1: Maintain a minimum heap of length k, traverse nk elements, compare with the top value of the heap one by one, exchange with the top of the heap, and finally return to the top of the heap

Complexity: Time complexity O ( k + ( n − k ) logk ) O(k+(nk)logk)O ( k+(nk ) l o g k ) , space complexityO ( 1 ) O(1)O(1)

Go code

func findKthLargest(nums []int, k int) int {
    
    
    length := len(nums)
    if k > length {
    
    
        return -1
    }
    makeMinHeap(nums, k)
    for i:=k;i<length;i++ {
    
    
        if nums[i] > nums[0] {
    
    
            nums[0], nums[i] = nums[i], nums[0]
            minHeap(nums, 0, k)
        }
    }
    return nums[0]
}

func makeMinHeap(arr []int, length int) {
    
    
    // 从最后一个非叶子节点开始
    for i:=(length/2-1); i>=0; i-- {
    
    
        minHeap(arr, i, length)
    }
}

// 最小堆化
func minHeap(arr []int, i int, length int) {
    
    
    left, right := 2*i+1, 2*i+2
    min := i
    if left < length && arr[left] < arr[min] {
    
    
        min = left
    }
    if right < length && arr[right] < arr[min] {
    
    
        min = right
    }
    if min != i {
    
    
        arr[i], arr[min] = arr[min], arr[i]
        minHeap(arr, min, length)
    }
}

Solution 2: Build a maximum heap of length n, traverse k times, delete the top of the heap each time, and the length of the heap is -1, and finally return to the top of the heap (this method is better when k is smaller)

Complexity: time complexity O ( n + klogn ) O(n+klogn)O ( n+k l o g n ) , space complexityO ( 1 ) O(1)O(1)

Go code

func findKthLargest(nums []int, k int) int {
    
    
    length := len(nums)
    if k > length {
    
    
        return -1
    }
    // 将nums构建为一个最大堆
    makeMaxHeap(nums, length)
    for i:=1; i<k; i++ {
    
    
        nums[0], nums[length-i] = nums[length-i], nums[0]
        maxHeap(nums, 0, length-i)
    }
    return nums[0]
}

// 最大堆
func makeMaxHeap(arr []int, length int) {
    
    
    // 第一个非叶子节点
    for i:=(length/2-1); i>=0; i-- {
    
    
        maxHeap(arr, i, length)
    }
}
// 最大堆化
func maxHeap(arr []int, i int, length int) {
    
    
    l, r, max := 2*i+1, 2*i+2, i
    if l<length && arr[l] > arr[max] {
    
    
        max = l
    }
    if r<length && arr[r] > arr[max] {
    
    
        max = r
    }
    if max != i {
    
    
        arr[max], arr[i] = arr[i], arr[max]
        maxHeap(arr, max, length)
    }
}

Topic: Heap sort

Topic Link: LeetCode-912. Sorting Arrays
insert image description here

Idea analysis: build a maximum heap with a length of n, delete the top of the heap in turn and put it at the end of the array in reverse order, and the heap length is -1, and the array will be in ascending order after n-1 times

Complexity: Time complexity O ( nlog ( n ) ) O(nlog(n))O ( n l o g ( n )) , space complexityO ( 1 ) O(1)O(1)

Go code

func sortArray(nums []int) []int {
    
    
    length := len(nums)
    if length == 1 {
    
    
        return nums
    }
    makeMaxHeap(nums, length)
    for i:=length-1; i>0; i-- {
    
    
        nums[0], nums[i] = nums[i], nums[0]
        maxHeap(nums, 0, i)
    }
    return nums
}
// 构建最大堆
func makeMaxHeap(nums []int, length int) {
    
    
    // 第一个非叶子结点
    for i:=length/2-1; i>=0; i-- {
    
    
        maxHeap(nums, i, length)
    }
}
// 最大堆化
func maxHeap(nums []int, i int, length int) {
    
    
    l, r, max := 2*i+1, 2*i+2, i
    if l<length && nums[l] > nums[max] {
    
    
        max = l
    }
    if r<length && nums[r] > nums[max] {
    
    
        max = r
    }
    if max != i {
    
    
        nums[max], nums[i] = nums[i], nums[max]
        maxHeap(nums, max, length)
    }
}

Topic: Merge K sorted linked lists

Topic link: LeetCode-23. Merge K ascending linked lists
insert image description here

Idea analysis: maintain the minimum heap with a length of k, delete the top of the heap one by one and connect it to the returned linked list (vertical splicing), pay attention to judging the empty linked list when taking the value

Complexity: time complexity O ( k + nlogk ) O(k+nlogk)O ( k+n l o g k ) , space complexityO ( 1 ) O(1)O(1)

Go code

/**
 * Definition for singly-linked list.
 * type ListNode struct {
 *     Val int
 *     Next *ListNode
 * }
 */
func mergeKLists(lists []*ListNode) *ListNode {
    
    
    length := len(lists)
    if length == 1 {
    
    
        return lists[0]
    }
    // 去除空数组
    for i:=0; i<length; i++ {
    
    
        if lists[i] == nil {
    
    
            lists[i], lists[length-1] = lists[length-1], lists[i]
            length--
            i--
        }
    }
    newList := &ListNode{
    
    }
    tmp := newList
    // 最小化
    makeMinHeap(lists, length)
    for length > 0 && lists[0] != nil {
    
    
        // 取出当前最小
        tmp.Next = &ListNode{
    
    Val:lists[0].Val}
        tmp = tmp.Next
        lists[0] = lists[0].Next
        if lists[0] == nil {
    
    
            lists[0], lists[length-1] = lists[length-1], lists[0]
            length--
        }
        if length > 0 && lists[0] != nil {
    
    
            minHeap(lists, 0, length)
        }
    }
    return newList.Next
}

func makeMinHeap(arr []*ListNode, length int) {
    
    
    for i:=length/2-1; i>=0; i-- {
    
    
        minHeap(arr, i, length)
    }
}

func minHeap(arr []*ListNode, i, length int) {
    
    
    left, right, min := 2*i+1, 2*i+2, i
    if left<length && arr[left].Val < arr[min].Val {
    
    
        min = left
    }
    if right<length && arr[right].Val < arr[min].Val {
    
    
        min = right
    }
    if min != i {
    
    
        arr[min], arr[i] = arr[i], arr[min]
        minHeap(arr, min, length)
    }
}

Guess you like

Origin blog.csdn.net/trinityleo5/article/details/132484125