Minimum Swaps To Make Sequences Increasing

Minimum Swaps To Make Sequences Increasing

You are given two integer arrays of the same length nums1 and nums2 . In one operation, you are allowed to swap nums1[i] with nums2[i] .

  • For example, if nums1 = [1,2,3,8] , and nums2 = [5,6,7,4] , you can swap the element at i = 3 to obtain nums1 = [1,2,3,4] and nums2 = [5,6,7,8] .

Return the minimum number of needed operations to make nums1 and nums2 strictly increasing. The test cases are generated so that the given input always makes it possible.

An array arr is strictly increasing if and only if arr[0] < arr[1] < arr[2] < ... < arr[arr.length - 1] .

Example 1:

Input: nums1 = [1,3,5,4], nums2 = [1,2,3,7]
Output: 1
Explanation: 
Swap nums1[3] and nums2[3]. Then the sequences are:
nums1 = [1, 3, 5, 7] and nums2 = [1, 2, 3, 4]
which are both strictly increasing.

Example 2:

Input: nums1 = [0,3,5,8,9], nums2 = [2,1,4,6,9]
Output: 1

Constraints:

$2 \leq nums1.length \leq {10}^{5}$
$nums2.length == nums1.length$
$0 \leq nums1[i], nums2[i] \leq 2 \times {10}^{5}$

 

解题思路

  写的时候一直以为是贪心那一类的思维题,结果想了半天都没想到怎么写,看题解才知道正解是dp,都傻掉了。其实一开始有想到爆搜,因为每个位置有换和不换两种选择,所以可以爆搜每个位置的选择,最后判断交换后的序列是否严格升序就可以了。其实想到这里就可以用dp了啊!先尝试定义一个一维状态$f(i)$表示将区间$[0,i]$变成升序的所有方案的集合。在状态转移的时候发现无法转移,因为不知道第$i-1$个位置是否有交换过,所以不知道跟哪个数比较,因此还需要额外加多一个状态用来表示是否交换过。

  定义状态$f(i,0)$和$f(i,1)$,其中$f(i,0)$表示将区间$[0,i]$变成升序且第$i$个位置没有交换的所有方案的集合,$f(i,1)$表示将区间$[0,i]$变成升序且第$i$个位置有交换的所有方案的集合。属性就是最小值。状态转移如下:

  • 如果第$i-1$个位置没有交换:
    • 如果$n1[i-1] < n1[i]$并且$n2[i-1] < n2[i]$,那么$f[i][0] = min(f[i][0],f[i-1][0])$。
    • 如果$n1[i-1] < n2[i]$并且$n2[i-1] < n1[i]$,那么$f[i][1] = min(f[i][1],f[i-1][0] + 1)$。
  • 如果第$i-1$个位置有交换:
    • 如果$n2[i-1] < n1[i]$并且$n1[i-1] < n2[i]$,那么$f[i][0] = min(f[i][0],f[i-1][1])$。
    • 如果$n2[i-1] < n2[i]$并且$n1[i-1] < n1[i]$,那么$f[i][1] = min(f[i][1],f[i-1][1] + 1)$。

  AC代码如下:

 1 class Solution {
 2 public:
 3     int minSwap(vector<int>& nums1, vector<int>& nums2) {
 4         int n = nums1.size();
 5         vector<vector<int>> f(n, vector<int>(2, n));
 6         f[0][0] = 0, f[0][1] = 1;
 7         for (int i = 1; i < n; i++) {
 8             if (nums1[i - 1] < nums1[i] && nums2[i - 1] < nums2[i]) f[i][0] = f[i - 1][0], f[i][1] = f[i - 1][1] + 1;
 9             if (nums2[i - 1] < nums1[i] && nums1[i - 1] < nums2[i]) f[i][0] = min(f[i][0], f[i - 1][1]), f[i][1] = min(f[i][1], f[i - 1][0] + 1);
10         }
11         return min(f[n - 1][0], f[n - 1][1]);
12     }
13 };

 

参考资料

  【宫水三叶】状态机 DP 运用题:https://leetcode.cn/problems/minimum-swaps-to-make-sequences-increasing/solution/by-ac_oier-fjhp/

posted @ 2022-10-10 21:08  onlyblues  阅读(52)  评论(0编辑  收藏  举报
Web Analytics