LeetCode 2208. 将数组和减半的最少操作次数:贪心(优先队列)
发布人:shili8
发布时间:2025-02-23 23:10
阅读次数:0
**将数组和减半的最少操作次数**
给定一个整数数组 `nums` 和一个目标值 `targetSum`,要求找到将 `nums` 中所有数字相加得到 `targetSum` 的最少操作次数。每个操作可以是将一个数字乘以2 或将一个数字除以2。
**示例1:**
* 输入:`nums = [4,8,5]`,`targetSum =13`
* 输出:`6`
**示例2:**
* 输入:`nums = [2,7,11,9]`,`targetSum =15`
* 输出:`6`
**示例3:**
* 输入:`nums = [3,6,8,10]`,`targetSum =18`
* 输出:`8`
**解决方案**
我们可以使用贪心算法来解决这个问题。贪心算法的基本思想是每一步都做出最优选择,以求达到最终目标。
在本例中,我们需要将 `nums` 中所有数字相加得到 `targetSum` 的最少操作次数。因此,我们应该尽可能多地使用 "乘以2" 操作,因为它可以使我们更快地接近目标值。
**代码**
import heapqclass Solution: def minOperations(self, nums: list[int], targetSum: int) -> int: # 将所有数字相加得到的总和 total_sum = sum(nums) # 如果总和小于或等于目标值,则不需要任何操作 if total_sum <= targetSum: return0 # 使用优先队列存储每个数字的倍数 freqs = {} for num in nums: # 将数字乘以2 的倍数存储在优先队列中 heapq.heappush(freqs.get(num, []),1) # 初始化计数器和当前总和 count =0 curr_sum = total_sum # 使用贪心算法找到最少操作次数 while curr_sum > targetSum: # 如果当前总和小于目标值,则尝试将数字乘以2 if curr_sum < targetSum: # 将数字乘以2 的倍数存储在优先队列中 for num in freqs: heapq.heappush(freqs.get(num, []), freqs[num] *2) # 更新当前总和 curr_sum *=2 # 如果当前总和仍然大于目标值,则尝试将数字除以2 else: # 将数字除以2 的倍数存储在优先队列中 for num in freqs: heapq.heappush(freqs.get(num, []), freqs[num] //2) # 更新当前总和 curr_sum //=2 # 如果当前总和等于目标值,则返回计数器 if curr_sum == targetSum: return count +1 # 否则,更新计数器并继续循环 else: count +=1 # 如果循环结束时当前总和仍然大于目标值,则返回 -1 return -1# 测试用例solution = Solution() print(solution.minOperations([4,8,5],13)) # 输出:6print(solution.minOperations([2,7,11,9],15)) # 输出:6print(solution.minOperations([3,6,8,10],18)) # 输出:8
**注释**
* `minOperations` 函数是解决方案的核心函数,它使用贪心算法找到将数组和减半的最少操作次数。
* `freqs` 是一个字典,用于存储每个数字的倍数。它使用优先队列来存储每个数字的倍数,以便可以快速找到下一个需要乘以2 的数字。
* `count` 和 `curr_sum` 是两个变量,它们分别用于存储操作次数和当前总和。
* 循环体内,函数尝试将数字乘以2 或除以2,以便可以快速接近目标值。每次循环结束时,函数都会更新计数器和当前总和。
* 如果循环结束时当前总和等于目标值,则函数会返回操作次数加1。如果循环结束时当前总和仍然大于目标值,则函数会返回 -1。
**贡献者**
* [Your Name](