leetcode
leetcode 1901 ~ 1950
拿出最少数目的魔法豆

拿出最少数目的魔法豆

难度:

标签:

题目描述

代码结果

运行时间: 172 ms, 内存: 28.0 MB


/*
 * 思路:
 * 1. 首先对数组进行排序。
 * 2. 对于每个可能的剩余豆子数量(排序后数组的每个元素),计算将其他袋子中豆子数量减少到该数量需要移除的豆子数量。
 * 3. 取最小的移除豆子数量作为结果。
 */

import java.util.Arrays;
import java.util.stream.IntStream;

public class Solution {
    public int minBeansToRemove(int[] beans) {
        // 对数组进行排序
        Arrays.sort(beans);
        int total = Arrays.stream(beans).sum();
        int n = beans.length;
        
        // 使用流计算最小的移除豆子数量
        return IntStream.range(0, n)
                .map(i -> total - beans[i] * (n - i))
                .min()
                .orElse(total);
    }

    public static void main(String[] args) {
        Solution solution = new Solution();
        int[] beans = {4, 1, 6, 5};
        System.out.println(solution.minBeansToRemove(beans)); // 输出: 4
    }
}

解释

方法:

这个解决方案首先计算了beans数组中魔法豆的总数。然后,它对beans数组进行排序以方便后续操作。接着,遍历排序后的beans数组,计算如果所有非空袋子的魔法豆数为当前值时,需要移除的魔法豆总数。这个计算通过从总数中减去当前值乘以剩余袋子的数量来实现。算法记录下遍历过程中的最小移除数量。因为数组是排序后的,所以它确保只计算每个不同的豆子数量一次,避免重复计算。最后,返回记录的最小移除数量。

时间复杂度:

O(n log n)

空间复杂度:

O(1)

代码细节讲解

🦆
在算法中,你是如何确定哪些豆子数量应该作为最终目标豆子数,以便进行比较和计算的?
在算法中,通过对 beans 数组进行排序,并遍历每个不同的豆子数作为最终目标的可能性来确定。排序后,对于数组中的每个元素(豆子数),算法考虑如果所有非空袋子都有相同的豆子数(即当前遍历到的豆子数),需要移除的豆子总数。通过这种方式,可以确保考虑每种可能的豆子数,并找到导致最小移除总数的最优豆子数。
🦆
为什么在计算最少移除豆子数时,需要将总豆子数减去`当前值乘以剩余袋子的数量`?这样的计算逻辑是基于什么考量?
这种计算逻辑是基于将所有非空袋子的豆子数调整到当前考虑的豆子数(当前值)。通过计算`当前值乘以剩余袋子的数量`,我们得到如果将所有非空袋子调整到当前值所应有的总豆子数。将这个数从总豆子数中减去,得到的就是为了达到这个状态需要移除的豆子总数。这样的计算可以帮助我们找到移除豆子数最少的情况,即使所有非空袋子的豆子数一致。
🦆
在遍历过程中,你是如何处理豆子数量相同的情况,即为什么要检查`val == last_val`,并跳过这些值?这样做的目的是什么?
检查`val == last_val`并跳过这些值的目的是为了避免重复计算。因为数组已经排序,相同的豆子数量会连续出现。如果不跳过重复的豆子数量,那么对于相同的豆子数,算法会重复计算相同的移除数量,这是不必要的。通过跳过已经计算过的豆子数量,可以提高算法的效率和执行速度。
🦆
算法最后返回的`min_beans`是在哪些情况下更新的?请解释这个更新逻辑。
在算法执行过程中,`min_beans`是在找到更小的移除豆子总数时更新的。具体来说,每次计算得到当前豆子数作为目标时需要移除的豆子总数后,都会与当前记录的`min_beans`(最小移除数量)进行比较。如果当前计算的移除数量小于`min_beans`,则更新`min_beans`为当前计算的值。这确保了算法能够持续跟踪并返回遍历过程中遇到的最小移除数量。

相关问题