开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第26天,点击查看活动详情
一、题目描述:
1046. 最后一块石头的重量 - 力扣(LeetCode) (leetcode-cn.com)
有一堆石头,每块石头的重量都是正整数。
每一回合,从中选出两块 最重的 石头,然后将它们一起粉碎。假设石头的重量分别为 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
二、思路分析:
自己手写的一个大根堆
- 一开始push,维护一个大根堆,插入元素放在尾部,如果>父节点,就sift up
- 每次删除最大的元素,然后对小的元素进行 sift down
- 将新的元素进行插入,用push
三、AC 代码:
class Dui(object):
def __init__(self):
self.heap = []
self.size = 0
def push(self, num):
self.size += 1
self.heap.append(num)
self.sift_up(self.size-1) # 对末尾元素进行上浮
def pop(self): # 删除最大的两个元素
self.swap(0, self.size-1)
tmp = self.heap.pop()
self.size -= 1
self.sift_down(0)
return tmp
def sift_up(self, p):
while p>0:
if self.heap[(p-1)//2] < self.heap[p]:
self.swap((p-1)//2, p)
p = (p-1)//2
else: break
def sift_down(self, p):
while 2*p + 1 < self.size:
if 2*p+2 < self.size:
index = self.compare(2*p+1, 2*p+2)
if self.heap[p] < self.heap[index]:
self.swap(p, index)
p = index
else: p = self.size
else:
if self.heap[p] < self.heap[2*p+1]:
self.swap(p, 2*p+1)
p = 2*p+1
else: p = self.size
def compare(self, p1, p2):
if self.heap[p1] >= self.heap[p2]: return p1
else: return p2
def swap(self, index1, index2):
self.heap[index1], self.heap[index2] = self.heap[index2], self.heap[index1]
def get_size(self):
return self.size
class Solution(object):
def lastStoneWeight(self, stones):
"""
:type stones: List[int]
:rtype: int
"""
Heap = Dui()
for i in stones:
Heap.push(i)
print(Heap.heap)
while Heap.get_size() > 1:
s1 = Heap.pop()
s2 = Heap.pop()
tmp = s1 - s2
if tmp:
Heap.push(tmp)
return Heap.heap[0] if Heap.get_size()>=1 else 0