Every day a Leetcode
题目来源:2826. 将三个组排序
解法1:贪心 + 二分查找
最长递增子序列的变种题。
利用 Leetcode300. 最长递增子序列 的方法,求出数组 nums 的最长递增子序列 g,最后答案为 nums.size() - g.size()。
代码:
// 最长递增子序列,贪心 + 二分查找
class Solution
{
public:
int minimumOperations(vector<int> &nums)
{
// 特判
if (nums.empty())
return 0;
int n = nums.size();
vector<int> g; // 最长递增子序列
for (int i = 0; i < n; i++)
{
int j = upper_bound(g.begin(), g.end(), nums[i]) - g.begin();
if (j == g.size())
g.push_back(nums[i]);
else
g[j] = nums[i];
}
return n - g.size();
}
};
结果:
复杂度分析:
时间复杂度:O(nlogn),其中 n 是数组 nums 的元素个数。
空间复杂度:O(n),其中 n 是数组 nums 的元素个数。
解法2:状态机 DP
代码:
class Solution
{
public:
int minimumOperations(vector<int> &nums)
{
// 特判
if (nums.empty())
return 0;
int n = nums.size();
// dp[i+1][j]: 考虑 nums[0] 到 nums[i],且 nums[i] 变成 j 的最小修改次数
vector<vector<int>> dp(n + 1, vector<int>(4, 0));
// 状态转移
for (int i = 0; i < n; i++)
for (int j = 1; j <= 3; j++)
{
dp[i + 1][j] = INT_MAX;
for (int k = 1; k <= j; k++)
dp[i + 1][j] = min(dp[i + 1][j], dp[i][k]);
dp[i + 1][j] += nums[i] != j;
}
return *min_element(dp[n].begin() + 1, dp[n].end());
}
};
结果:
复杂度分析:
时间复杂度:O(n),其中 n 是数组 nums 的元素个数。
空间复杂度:O(n),其中 n 是数组 nums 的元素个数。