215. 数组中的第K个最大元素

105 阅读1分钟

题目:
给定整数数组 nums 和整数 k,请返回数组中第 k 个最大的元素。

请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。
解法:
方法一:快速排序 理解了就不难,注意pivot要随机选择,不然容易超时

func findKthLargest(nums []int, k int) int {
	return find(nums, 0, len(nums) - 1, k)
}

func find(nums []int, left, right int, k int) int {
	pivot := partion(nums, left, right)
	// fmt.Println(nums, pivot)
	if pivot + 1 == k {
		return nums[pivot]
	} else if k < pivot + 1  {
		return find(nums, left, pivot - 1, k)
	} 
	return find(nums, pivot + 1, right, k)
}

func partion(nums []int, left, right int) int {
	randomPivot(nums, left, right)
	pivotVal := nums[right]
	pivot := left
	for j := left; j < right; j ++ {
		if nums[j] > pivotVal {
			nums[pivot], nums[j] = nums[j], nums[pivot]
			pivot ++
		}
	}
	nums[pivot], nums[right] = nums[right], nums[pivot]
	return pivot
}

func randomPivot(nums []int, left, right int) {
	n := rand.Intn(right - left + 1) + left
	nums[n], nums[right] = nums[right], nums[n]
}

方法二:构造heap(尤其适合大数据量的场景)

func findKthLargest(nums []int, k int) int {
	heap := NewHeap(k)
	for i := range nums{
		heap.insert(nums[i])
	}
	return heap.Array[1]
}


// root节点最小
// Array的第0位不存数据,索引k的父节点位置为k/2,子节点位置为2k,2k+1
type Heap struct{
	Array []int
	N int
	Capacity int
}

func NewHeap(n int) *Heap{
	return &Heap{
		Array: make([]int, 1),
		Capacity: n,
	}
}

func (h *Heap)insert(v int){
	if h.N < h.Capacity {
		h.Array = append(h.Array, v)
		h.N ++
		h.swim(h.N)	
	} else {
		if v > h.Array[1] {
			h.Array[1] = v
			h.sink(1)
		}
	}
	
}

// 删除根节点的值
func (h *Heap)deleteRoot() int{
	ret := h.Array[1]
	h.swap(1, h.N)
	h.Array = h.Array[:h.N]
	h.N --
	h.sink(1)
	return ret
}

// 节点i的父节点比它小时,执行swim,节点i上浮,
func (h *Heap)sink(i int){
	current := i
	child := 2 * current
	for child <= h.N {
		// 右子节点一定比左子节点大,交换右子节点和根节点一定满足堆的条件
		if child + 1 <= h.N && h.less(child, child + 1) {
			child = child + 1
		}
		if !h.less(current, child){
			break
		}
		h.swap(current, child)
		current = child
		child = 2 * current
	}
}

// 节点i的子节点比它大时,执行sink,节点i下沉
func (h *Heap)swim(i int){
	current := i
	parent := current / 2
	for parent > 0 {
		if !h.less(parent, current) {
			break
		}
		h.swap(current, parent)

		current = parent
		parent = current / 2
	}
}

func (h *Heap)less(i int, j int) bool {
	return h.Array[i] > h.Array[j]
}

func (h *Heap)swap(i int, j int)  {
	h.Array[i], h.Array[j] = h.Array[j], h.Array[i]
}