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;elsereturn -1;}}return k == -1 ? 0 : n - k - 1;}
};
// @lc code=end
结果:
复杂度分析:
时间复杂度:O(n),其中 n 是数组 nums 的元素个数。
空间复杂度:O(1)。