LeetCode每日一题(2366. Minimum Replacements to Sort the Array)

You are given a 0-indexed integer array nums. In one operation you can replace any element of the array with any two elements that sum to it.

For example, consider nums = [5,6,7]. In one operation, we can replace nums[1] with 2 and 4 and convert nums to [5,2,4,7].
Return the minimum number of operations to make an array that is sorted in non-decreasing order.

Example 1:

Input: nums = [3,9,3]
Output: 2

Explanation: Here are the steps to sort the array in non-decreasing order:

  • From [3,9,3], replace the 9 with 3 and 6 so the array becomes [3,3,6,3]
  • From [3,3,6,3], replace the 6 with 3 and 3 so the array becomes [3,3,3,3,3]
    There are 2 steps to sort the array in non-decreasing order. Therefore, we return 2.

Example 2:

Input: nums = [1,2,3,4,5]
Output: 0

Explanation: The array is already in non-decreasing order. Therefore, we return 0.

Constraints:

  • 1 <= nums.length <= 105
  • 1 <= nums[i] <= 109

听说是 google 的面试题

首先想到的应该是倒序处理这个题, 因为如果采用正序, 我们遇到任何一个 nums[i] < nums[i-1], 我们都要把前面 nums[…i]检查处理一遍, 会非常耗时。使用倒序每一步我们都可以确定当前最大的最小值, 我们只要把当前值拆分成小于等于当前最小值的数字就可以了, 然后从拆分出来的数字中找到最小值继续向下传递。

自己做的时候就想到这了, 然后下面就是要考虑拆分数字的策略了, 看下面的例子

[2, 2, 2, 2, 2, 2, 2, 10, 3]

因为 10 在 3 前面,又大于 3, 所以要进行拆分,因为拆分后的最大值不能大于 3, 所以理所当然的, 我们会想用 10 / 3, 拆分成[3, 3, 3, 1], 但是如果按这种拆分方法, 此时的最小值是 1, 继续向前走的话, 前面所有的 2 都需要拆分成[1, 1], 这显然不是最好的解。看到这, 我们肯定可以看出, 我们可以将 10 拆分成[3, 3, 2, 2], 这样的话前面所有 2 就都不用进行拆分了。

答案出来了, 但是过程怎么表达呢?

假设 prev 是上一步得出的最小值, 也就是需要将当前数字拆分成小于或等于 prev 的数字, num_of_pieces = (nums[i] / prev) + 1, 这里 num_of_pieces 就是要将当前数字拆分成不大于 prev 的数字时所能拆分的最少份数, 如果 nums[i]能被 prev 整除, 那末尾的+1 就要去掉, 然后我们将 nums[i] / num_of_pieces 就可以得到拆分成 num_of_pieces 份后最大化的最小值。

还是看上面的例子, num_of_pieces = (10 / 3) + 1, num_of_pieces = 4, next = 10 / 4, next = 2

num_of_pieces = 4 意味着我们要想将 10 拆分成都不大于 3 的数字, 最少要分 4 份

开始:
remain = 10
pieces = [0, 0, 0, 0]

第一步:
remain = 2
pieces = [2, 2, 2, 2]

第二步:
remain = 0
pieces = [3, 3, 2, 2]



impl Solution {
    pub fn minimum_replacement(nums: Vec<i32>) -> i64 {
        let mut prev = nums[nums.len() - 1] as i64;
        let mut ans = 0;
        for i in (0..nums.len() - 1).rev() {
            let num_of_pieces =
                nums[i] as i64 / prev + if nums[i] as i64 % prev == 0 { 0 } else { 1 };
            ans += num_of_pieces - 1;
            prev = nums[i] as i64 / num_of_pieces;
        }
        ans
    }
}

你可能感兴趣的:(leetcode,算法,数据结构)