您的位置:首页 > 文旅 > 美景 > 中企动力科技股份有限公司贵阳分公司_qq浏览器官网主页网址_媒体资源网官网_网站推广怎么做

中企动力科技股份有限公司贵阳分公司_qq浏览器官网主页网址_媒体资源网官网_网站推广怎么做

2025/4/28 15:53:08 来源:https://blog.csdn.net/2403_83543687/article/details/147522552  浏览:    关键词:中企动力科技股份有限公司贵阳分公司_qq浏览器官网主页网址_媒体资源网官网_网站推广怎么做
中企动力科技股份有限公司贵阳分公司_qq浏览器官网主页网址_媒体资源网官网_网站推广怎么做

每日算法打卡 - 2025年4月25日

记录今天完成的几道 LeetCode 算法题,分享解题思路和代码。


2178. 拆分成最多数目的正偶数之和

题目
题目截图 2178

解题思路

贪心算法

解题过程

题目要求我们将一个偶数 finalSum 拆分成尽可能多的 不同 正偶数之和。

为了使拆分出的数字数量最多,我们应该尽可能选择小的偶数。因此,可以采用贪心策略:从最小的正偶数 2 开始,依次尝试添加 4, 6, 8, …,并不断更新剩余的 finalSum

具体步骤如下:

  1. 初始化一个空列表 ret 用于存放结果。
  2. 首先判断 finalSum 是否为偶数,如果不是,无法拆分,直接返回空列表。
  3. 使用一个变量 i 从 2 开始,表示当前尝试添加的偶数。
  4. 进入循环,只要 finalSum 大于 0:
    a. 尝试从 finalSum 中减去当前的偶数 i
    b. 关键一步:检查减去 i 后的 finalSum。如果 finalSum <= i,这意味着剩余的 finalSum 不足以让我们在下一步添加 i+2(因为需要不同的偶数,且 i+2 > i >= finalSum),或者刚好等于 i(如果加上 i 会导致重复)。为了用尽 finalSum 并保证得到最多数量的偶数,我们将这个剩余的 finalSum 加到当前的 i 上,形成 i + finalSum_remaining。这个合并后的值将是最后一个加入列表的数。然后将 finalSum 设为 0,表示总和已完全分配。
    c. 将(可能被调整过的)i 添加到结果列表 ret 中。
    d. 将 i 增加 2,准备处理下一个偶数。
  5. finalSum 变为 0 时,循环结束,返回列表 ret

这种方法确保了每次都取最小的可用偶数,从而最大化了偶数的数量,并且通过最后一步的合并操作保证了所有数都是不同的正偶数且总和恰好为 finalSum

复杂度分析

  • 时间复杂度: O ( f i n a l S u m ) O(\sqrt{finalSum}) O(finalSum )。 我们依次添加 2, 4, 6, …, k。这些数的和大约是 k 2 / 2 k^2 / 2 k2/2。当和达到 finalSum 时停止,所以 k 2 ≈ 2 × f i n a l S u m k^2 \approx 2 \times finalSum k22×finalSum, 即 k ≈ 2 × f i n a l S u m k \approx \sqrt{2 \times finalSum} k2×finalSum 。循环的次数与 k k k 成正比,因此时间复杂度为 O ( f i n a l S u m ) O(\sqrt{finalSum}) O(finalSum )
  • 空间复杂度: O ( f i n a l S u m ) O(\sqrt{finalSum}) O(finalSum )。 结果列表 ret 最多存储约 f i n a l S u m \sqrt{finalSum} finalSum 个数。

Code

class Solution {public List<Long> maximumEvenSplit(long finalSum) {List<Long> ret = new ArrayList<>();if (finalSum % 2 != 0) {return ret;}long i = 2;while (finalSum > 0) {finalSum -= i;if (finalSum <= i) {i += finalSum;finalSum = 0;}ret.add(i);i += 2;}return ret;}
}

2567. 修改两个元素的最小分数

题目
题目截图 2567

解题思路

贪心

解题过程

题目要求我们通过修改数组中的两个元素,使得数组的“分数”(最大值与最小值的差)最小。我们有两次修改机会。

为了最小化最大值与最小值的差,最优的修改策略总是将待修改的元素值改为与数组中某个“目标”元素相等。由于我们可以修改两个数,我们可以考虑以下几种情况来消除极端值对分数的影响:

  1. 修改两个最大值: 将数组中最大的两个元素修改成与最小值 nums[0] 相等(或者修改成任何小于等于 nums[n-3] 的值)。修改后,数组的实际最大值为 nums[n-3],最小值为 nums[0]。分数是 nums[n-3] - nums[0]
  2. 修改两个最小值: 将数组中最小的两个元素修改成与最大值 nums[n-1] 相等(或者修改成任何大于等于 nums[2] 的值)。修改后,数组的实际最小值为 nums[2],最大值为 nums[n-1]。分数是 nums[n-1] - nums[2]
  3. 修改一个最大值和一个最小值: 将最小值 nums[0] 修改成 nums[1](或更大),并将最大值 nums[n-1] 修改成 nums[n-2](或更小)。修改后,数组的实际最小值为 nums[1],最大值为 nums[n-2]。分数是 nums[n-2] - nums[1]

这三种情况涵盖了通过两次修改来最小化 max - min 的所有有效策略。因为我们总是希望消除最大的数或最小的数对分数的影响。

因此,我们首先对数组进行排序,然后计算上述三种情况对应的分数,取其中的最小值即为答案。

复杂度分析

  • 时间复杂度: O ( N log ⁡ N ) O(N \log N) O(NlogN),主要是数组排序所需的时间。
  • 空间复杂度: O ( log ⁡ N ) O(\log N) O(logN) O ( 1 ) O(1) O(1),取决于排序算法使用的额外空间。

Code

class Solution {public int minimizeSum(int[] nums) {Arrays.sort(nums);int n = nums.length;int maxToMin = nums[n - 3] - nums[0];int minToMax = nums[n - 1] - nums[2];int maxToMinANDminToMax = nums[n - 2] - nums[1];return Math.min(maxToMinANDminToMax, Math.min(maxToMin, minToMax));}
}

1509. 三次操作后最大值与最小值的最小差

题目
题目截图 1509

解题思路

贪心

解题过程

这道题与上一题类似,但我们有三次修改机会。目标仍然是最小化修改后数组的最大值与最小值的差。

同样,最优策略是修改数组中的极端值(最大或最小的那些)。有三次修改机会,意味着我们可以“消除”数组排序后两端的最多三个元素对最终 max - min 差值的影响。考虑以下四种消除极端值的情况:

  1. 修改最大的三个数: 将 nums[n-1], nums[n-2], nums[n-3] 修改掉。剩下的元素范围是 [nums[0], nums[n-4]]。最小差值为 nums[n-4] - nums[0]
  2. 修改最小的三个数: 将 nums[0], nums[1], nums[2] 修改掉。剩下的元素范围是 [nums[3], nums[n-1]]。最小差值为 nums[n-1] - nums[3]
  3. 修改最小的两个数和最大的一个数: 将 nums[0], nums[1]nums[n-1] 修改掉。剩下的元素范围是 [nums[2], nums[n-2]]。最小差值为 nums[n-2] - nums[2]
  4. 修改最小的一个数和最大的两个数: 将 nums[0], nums[n-1]nums[n-2] 修改掉。剩下的元素范围是 [nums[1], nums[n-3]]。最小差值为 nums[n-3] - nums[1]

这四种情况覆盖了所有最优的可能。因为要最小化差值,我们总是改变最大或最小端的元素。改变中间的元素不会比改变两端的元素更优。

所以,先对数组排序。如果数组长度 n 小于或等于 4,我们总能通过三次修改使得所有元素相等,差值为 0。否则,计算上述四种情况的差值,返回其中的最小值。

复杂度分析

  • 时间复杂度: O ( N log ⁡ N ) O(N \log N) O(NlogN), 瓶颈在于排序。
  • 空间复杂度: O ( log ⁡ N ) O(\log N) O(logN) O ( 1 ) O(1) O(1), 取决于排序算法。

Code

class Solution {public int minDifference(int[] nums) {int n = nums.length;if (n <= 4) {return 0;}Arrays.sort(nums);int maxToMin = nums[n - 4] - nums[0];int minToMax = nums[n - 1] - nums[3];int firstTwo = nums[n - 2] - nums[2];int lastTwo = nums[n - 3] - nums[1];int one = Math.min(maxToMin, minToMax);int two = Math.min(firstTwo, lastTwo);return Math.min(one, two);}
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com