leetcode
leetcode 2501 ~ 2550
最大化数组末位元素的最少操作次数

最大化数组末位元素的最少操作次数

难度:

标签:

题目描述

You are given two 0-indexed integer arrays, nums1 and nums2, both having length n.

You are allowed to perform a series of operations (possibly none).

In an operation, you select an index i in the range [0, n - 1] and swap the values of nums1[i] and nums2[i].

Your task is to find the minimum number of operations required to satisfy the following conditions:

  • nums1[n - 1] is equal to the maximum value among all elements of nums1, i.e., nums1[n - 1] = max(nums1[0], nums1[1], ..., nums1[n - 1]).
  • nums2[n - 1] is equal to the maximum value among all elements of nums2, i.e., nums2[n - 1] = max(nums2[0], nums2[1], ..., nums2[n - 1]).

Return an integer denoting the minimum number of operations needed to meet both conditions, or -1 if it is impossible to satisfy both conditions.

 

Example 1:

Input: nums1 = [1,2,7], nums2 = [4,5,3]
Output: 1
Explanation: In this example, an operation can be performed using index i = 2.
When nums1[2] and nums2[2] are swapped, nums1 becomes [1,2,3] and nums2 becomes [4,5,7].
Both conditions are now satisfied.
It can be shown that the minimum number of operations needed to be performed is 1.
So, the answer is 1.

Example 2:

Input: nums1 = [2,3,4,5,9], nums2 = [8,8,4,4,4]
Output: 2
Explanation: In this example, the following operations can be performed:
First operation using index i = 4.
When nums1[4] and nums2[4] are swapped, nums1 becomes [2,3,4,5,4], and nums2 becomes [8,8,4,4,9].
Another operation using index i = 3.
When nums1[3] and nums2[3] are swapped, nums1 becomes [2,3,4,4,4], and nums2 becomes [8,8,4,5,9].
Both conditions are now satisfied.
It can be shown that the minimum number of operations needed to be performed is 2.
So, the answer is 2.   

Example 3:

Input: nums1 = [1,5,4], nums2 = [2,5,3]
Output: -1
Explanation: In this example, it is not possible to satisfy both conditions. 
So, the answer is -1.

 

Constraints:

  • 1 <= n == nums1.length == nums2.length <= 1000
  • 1 <= nums1[i] <= 109
  • 1 <= nums2[i] <= 109

代码结果

运行时间: 35 ms, 内存: 16.4 MB


/*
 * 思路:
 * 1. 使用 Stream 来查找 nums1 和 nums2 的最大值及其下标。
 * 2. 检查 nums1 和 nums2 最后的元素是否是各自的最大值。
 * 3. 如果不是,则需要进行交换操作使其满足条件。
 * 4. 使用一个计数器记录最少的交换次数。
 */

import java.util.stream.IntStream;

public class Solution {
    public int minSwaps(int[] nums1, int[] nums2) {
        int n = nums1.length;

        // 找出 nums1 和 nums2 的最大值及其下标
        int max1 = IntStream.of(nums1).max().orElse(Integer.MIN_VALUE);
        int max2 = IntStream.of(nums2).max().orElse(Integer.MIN_VALUE);
        int idx1 = IntStream.range(0, n).filter(i -> nums1[i] == max1).findFirst().orElse(-1);
        int idx2 = IntStream.range(0, n).filter(i -> nums2[i] == max2).findFirst().orElse(-1);

        // 检查最后一个元素是否是最大值
        if (nums1[n - 1] == max1 && nums2[n - 1] == max2) {
            return 0;
        }

        int swaps = 0;
        boolean swapped1 = false;
        boolean swapped2 = false;

        // 尝试交换以满足条件
        if (nums1[n - 1] != max1) {
            swaps++;
            nums1[idx1] = nums1[n - 1];
            nums1[n - 1] = max1;
            swapped1 = true;
        }

        if (nums2[n - 1] != max2) {
            swaps++;
            nums2[idx2] = nums2[n - 1];
            nums2[n - 1] = max2;
            swapped2 = true;
        }

        // 如果已经交换过最大值,检查是否满足条件
        if (swapped1 && nums1[n - 1] == max1 && nums2[n - 1] == max2) {
            return swaps;
        }

        // 如果不能同时满足条件,返回 -1
        return -1;
    }
}

解释

方法:

这道题目的核心在于确保数组 nums1 的最后一个元素 nums1[n-1] 是整个 nums1 中的最大值。为此,我们可以选择交换 nums1[i] 和 nums2[i] (0 <= i < n-1)。题解的方法是定义一个辅助函数 f(last1, last2),该函数用来计算若 nums1[n-1] 设为 last1,nums2[n-1] 设为 last2 时,使得 nums1[n-1] 是 nums1 中的最大值所需的最小交换次数。函数 f 遍历数组,对于每一对 nums1[i] 和 nums2[i],若 nums1[i] 或 nums2[i] 大于 last1 或 last2,则可能需要进行交换。如果交换后仍无法满足条件,则返回无穷大(表示不可能通过交换达成条件)。最后,比较 f(nums1[-1], nums2[-1])(保持最后一对元素不变)和 f(nums2[-1], nums1[-1])(交换最后一对元素)的结果,取较小值。若结果为无穷大,则说明无法通过交换使 nums1[n-1] 成为最大值,返回 -1。

时间复杂度:

O(n)

空间复杂度:

O(1)

代码细节讲解

🦆
为什么选择在函数`f`中比较`nums1[i]`和`nums2[i]`与`last1`和`last2`而不是直接确保`nums1[i] < last1`?
在函数`f`中,我们需要确保最终`nums1[n-1]`成为`nums1`数组中的最大值。这意味着,在任何位置`i`,`nums1[i]`或`nums2[i]`的值如果大于`last1`或`last2`,可能需要通过交换来避免这种情况,确保`last1`仍然是`nums1`中的最大值。直接确保`nums1[i] < last1`可能不足以处理所有情况,因为它忽略了`nums2[i]`可能成为`nums1[i]`的情况(通过交换),这样就可能需要更复杂的处理来维持`last1`作为最大值。因此,我们比较两个值对(`nums1[i]`与`last1`,`nums2[i]`与`last2`)来全面评估是否需要交换以维持最大值条件。
🦆
函数`f`中返回无穷大的条件`if x > last1 or y > last2`具体是基于什么考虑?在什么情况下无法通过交换满足条件?
在函数`f`中,`if x > last1 or y > last2`条件用于检查在不进行交换的情况下,`nums1[i]`或`nums2[i]`是否有超过`last1`或`last2`的情况,这会威胁到`last1`成为`nums1`中的最大值的目标。如果在该条件成立的情况下,即使考虑交换后(`y > last1`或`x > last2`),这些值仍然大于`last1`或`last2`,则无论如何交换,都无法确保`last1`是`nums1`中的最大值。此时,返回无穷大表示这种情况下通过交换是无法达到使`last1`成为`nums1`中最大值的目标。
🦆
题解中提到的无穷大(inf)在Python中如何表示,且如何确保比较操作的正确性?
在Python中,无穷大可以通过`float('inf')`来表示,这是一个特殊的浮点数,表示正无穷大。使用`float('inf')`可以在比较操作中正常使用,如`inf > any real number`总是返回`True`,这保证了在涉及无穷大的比较时逻辑的正确性。在题解中,使用无穷大来标示无法通过交换达到条件的情况,同时在最后比较时,任何实数操作次数和无穷大比较,都会优先选择实数操作次数(如果存在的话)。

相关问题