一、题目描述:
有一堆石头,每块石头的重量都是正整数。 每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x <= y。那么粉碎的可能结果如下: 如果 x == y,那么两块石头都会被完全粉碎; 如果 x != y,那么重量为 x 的石头将会完全粉碎,而重量为 y 的石头新重量为 y-x。 最后,最多只会剩下一块石头。返回此石头的重量。如果没有石头剩下,就返回 0。 示例: 输入:[2,7,4,1,8,1] 输出:1 解释: 先选出 7 和 8,得到 1,所以数组转换为 [2,4,1,1,1], 再选出 2 和 4,得到 2,所以数组转换为 [2,1,1,1], 接着是 2 和 1,得到 1,所以数组转换为 [1,1,1], 最后选出 1 和 1,得到 0,最终数组转换为 [1],这就是最后剩下那块石头的重量。 提示: 1 <= stones.length <= 30 1 <= stones[i] <= 1000
二、思路分析:
刚开始,我的思路是这样的。每次从石头中取出两个最重的(可以排序再取),然后将轻的移出队列,将重的减去轻的质量,然后再从石头中取出两个最重的(可以继续排序后再取)…
直到队列长度为1,然后取这个元素即可。
但是我忽略了一个问题,就是Go语言使用for range遍历切片时,操作的是副本,移出队列的操作并不会影响实际队列,因此这样就会导致失败,但是我们可以采用一种取巧的方式,我们将要去除的元素值设置为0,然后每次进行排序,仅操作排序后的两个最大值,当这两个最大值中较小的那个为0时,表示找到了最终值,即可退出循环。
我的这种方法还不够简洁,下面有优化方法:
func lastStoneWeight(stones []int) int {
sort.Ints(stones)
for i:=len(stones)-1;i>0;i--{
stones[i-1]=stones[i]-stones[i-1]//两个最大的相减
sort.Ints(stones[:i])//剩下的排序
}
return stones[0]
}
作者:1725762388
链接:https://leetcode.cn/problems/last-stone-weight/solution/pai-xu-liang-ge-zui-da-xiang-jian-wan-sh-zvcu/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
还有使用最大堆的方法: 使用堆容器,创建大根堆,pop出最大值两次比较,满足第一次大于第二次,把差值重新放回大根堆,直到堆内至多一个元素后返回。
type hp struct{ sort.IntSlice }
func (h hp) Less(i, j int) bool { return h.IntSlice[i] > h.IntSlice[j] }
func (h *hp) Push(v interface{}) { h.IntSlice = append(h.IntSlice, v.(int)) }
func (h *hp) Pop() interface{} { a := h.IntSlice; v := a[len(a)-1]; h.IntSlice = a[:len(a)-1]; return v }
func (h *hp) push(v int) { heap.Push(h, v) }
func (h *hp) pop() int { return heap.Pop(h).(int) }
func lastStoneWeight(stones []int) int {
q := &hp{stones}
heap.Init(q)
for q.Len() > 1 {
x, y := q.pop(), q.pop()
if x > y {
q.push(x - y)
}
}
if q.Len() > 0 {
return q.IntSlice[0]
}
return 0
}
作者:LeetCode-Solution
链接:https://leetcode.cn/problems/last-stone-weight/solution/zui-hou-yi-kuai-shi-tou-de-zhong-liang-b-xgsx/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
三、AC 代码:
func lastStoneWeight(stones []int) int {
if len(stones) == 1 {
return stones[0]
}
sort.Ints(stones)
length := len(stones)
fmt.Println(stones)
for stones[length-2] != 0{
stones[length-1] -= stones[length-2]
stones[length-2] = 0
sort.Ints(stones)
}
return stones[length-1]
}
四、总结:
这题虽然是简单题目,但是如果用Go语言写,不能使用简单暴力的方法,只能取巧和使用最大堆。