801. 使序列递增的最小交换次数(状态机dp)
dp的本质就是图论
状态机dp就是包含多个待选状态,个人感觉就是分层图,每一层是一个状态,不同状态之间有可以相互转化的方法。通过状态和状态之间的关系,来实现状态转移。
本题f[i][j]表示只从前i项中选,f[i][0]表示第i项不进行交换,f[i][1]表示第i项进行交换,达到严格递增情况下所需要的最小操作次数。
状态转移:
若nums1[i] > nums1[i - 1] && nums2[i] > nums2[i - 1]则可以将两个数字一起交换,要么一起交换,要么一起都不换,有 f[i][0] = f[i - 1][0], f[i][1] = f[i - 1][1] + 1;
若nums1[i] > nums2[i - 1] && nums2[i] > nums1[i - 1]则可以交换第i项或第i - 1项, 有f[i][0] = min(f[i][0], f[i - 1][1]), f[i][1] = min(f[i][1], f[i - 1][0] + 1);
class Solution { public: int minSwap(vector<int>& nums1, vector<int>& nums2) { int n = nums1.size(); vector<vector<int>> f(n, vector<int>(2)); f[0][0] = 0, f[0][1] = 1; for(int i = 1; i < n; i ++ ) f[i][0] = f[i][1] = 0x3f3f3f3f; for(int i = 1; i < n; i ++ ) { 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; } if(nums1[i] > nums2[i - 1] && nums2[i] > nums1[i - 1]) { f[i][0] = min(f[i][0], f[i - 1][1]); f[i][1] = min(f[i][1], f[i - 1][0] + 1); } } return min(f[n - 1][0], f[n - 1][1]); } };