6285. 执行 K 次操作后的最大分数

110 阅读1分钟

题目:
给你一个下标从 0 开始的整数数组 nums 和一个整数 k 。你的 起始分数 为 0 。

在一步 操作 中:

  1. 选出一个满足 0 <= i < nums.length 的下标 i ,
  2. 将你的 分数 增加 nums[i] ,并且
  3. 将 nums[i] 替换为 ceil(nums[i] / 3) 。

返回在 恰好 执行 k 次操作后,你可能获得的最大分数。

向上取整函数 ceil(val) 的结果是大于或等于 val 的最小整数。
算法:
方法一:大顶堆

func maxKelements(nums []int, k int) int64 {
    heap := NewHeap(nums)
    ans := int64(0)
    for i := 0; i < k; i ++ {
        n := heap.Pop()
        ans = ans + int64(n)
        heap.Push(ceil(n))
    }
    return ans
}

func ceil(n int) int {
    if n % 3 == 0 {
        return n / 3
    }
    return n / 3 + 1
}

type Heap struct {
	heap []int
}

func NewHeap(nums []int) *Heap {
	h := Heap{make([]int, 1)}
	for i := range nums {
		h.Push(nums[i])
	}
	return &h
}

func (h *Heap) Length() int {
	// fmt.Println(h.heap)
	return len(h.heap) - 1
}

func (h *Heap) Push(x int) {
	h.heap = append(h.heap, x)
	h.up(len(h.heap) - 1)
}

func (h *Heap) Pop() int {
	n := len(h.heap)
	x := h.heap[1]
	h.heap[1], h.heap[n - 1] = h.heap[n - 1], h.heap[1]
	h.heap = h.heap[:n - 1]
	h.sink(1)
	// fmt.Println("after pop", h.heap)
	return x
}

func (h *Heap) sink(i int) {
	child := 2 * i
	// 先找到两个儿子中较大的,再和父亲比较,如果比父亲大,则交换位置
	if child + 1 < len(h.heap) && h.heap[child + 1] > h.heap[child] {
		child ++	
	}
	if child < len(h.heap) && h.heap[i] < h.heap[child] {
		h.heap[child], h.heap[i] = h.heap[i], h.heap[child]
		h.sink(child)
	}

}

func (h *Heap) up(i int)  {
	father := i / 2
	if 0 < father && h.heap[father] < h.heap[i] {
		h.heap[father], h.heap[i] = h.heap[i], h.heap[father]
		h.up(father)
	}
}