Every day a Leetcode
题目来源:2855. 使数组成为递增数组的最少右移次数
解法1:暴力
由于右移 n 次就变回原数组了,所以答案至多为 n−1。
枚举右移次数(1~n-1),每次右移一个元素后判断数组是否有序,若是,则返回此时的右移次数。
代码:
// 暴力
class Solution
{
public:
int minimumRightShifts(vector<int> &nums)
{
// 特判
if (is_sorted(nums.begin(), nums.end()))
return 0;
int n = nums.size();
// 枚举右移次数
for (int i = 1; i < n; i++)
{
int x = nums.back();
nums.pop_back();
nums.insert(nums.begin(), x);
if (is_sorted(nums.begin(), nums.end()))
return i;
}
return -1;
}
};
结果:
复杂度分析:
时间复杂度:O(n2),其中 n 是数组 nums 的元素个数。
空间复杂度:O(1)。
解法2:一次遍历
问题等价于:
- 数组 nums 有至多两段递增子数组;
- 如果有两段,我们需要把第二段拼在第一段前面,所以还需要满足 nums[0]>nums[n−1],否则无法构成递增数组。
算法:
- 初始化 k = -1。
- 遍历数组 nums,两两比较相邻元素 nums[i] 和 nums[(i+1)%n],如果发现有 nums[(i + 1) % n] < nums[i],记录下标 k = i。
- 继续遍历下标,如果又发现 nums[(i + 1) % n] < nums[i],此时 k != -1,不符合数组 nums 有至多两段递增子数组的要求,返回 -1。
- 否则,右移次数 = n-k-1,返回该值。
代码:
/*
* @lc app=leetcode.cn id=2855 lang=cpp
*
* [2855] 使数组成为递增数组的最少右移次数
*/
// @lc code=start
class Solution
{
public:
int minimumRightShifts(vector<int> &nums)
{
int n = nums.size();
int k = -1;
for (int i = 0; i < n; i++)
{
if (nums[(i + 1) % n] < nums[i])
{
if (k == -1)
k = i;
else
return -1;
}
}
return k == -1 ? 0 : n - k - 1;
}
};
// @lc code=end
结果:
复杂度分析:
时间复杂度:O(n),其中 n 是数组 nums 的元素个数。
空间复杂度:O(1)。