leetcode之hot100---轮转数组(C++)

思路一:额外数组

额外分配一个数组存储轮转后的数组,然后再将轮转后的结果复制到原数组中

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        vector<int> result;
        for(int i = 0;  i < nums.size(); i++){
            if(i + k < nums.size()){
                result[i + k] = nums[i];
            }
            else{
                result[i + k - nums.size()] = nums[i];
            }
        }
        for(int i = 0;  i < nums.size(); i++){
            nums[i] = result[i];
        }
        
    }
};

最开始根据思路一写的代码是这个,但是执行时超时了,所以又改成了下述优化代码: 

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        vector<int> result(n);
        //result.reserve(n);
        for(int i = 0;  i < n; i++){
            result[(i + k) % n] = nums[i];   
        }
        nums.assign(result.begin(), result.end());
        
    }
};

在初始化result数组时,使用了reserve方法使其错误分配空间 。

原因是:

  • vector<int> result(); 是一个 空的构造函数调用,它定义了一个没有任何元素的 vector,也就是一个空的 vector<int>reserve(n) 方法会为 result 预分配内存空间,以便在将来添加最多 n 个元素时不会触发多次重新分配内存。注意,reserve(n) 只是预分配空间,并不会改变 vector 的实际元素数量。

  • vector<int> result(n);这个构造函数会创建一个大小为 nvector,并将其中每个元素初始化为 0(对于基本类型 int)。这意味着:result.size() 会返回 n,即 vector 中有 n 个元素。每个元素的初始值是 0,如果没有特别的初始化参数,vector<int> 的元素会使用默认构造函数进行初始化

也就是说,后者可以直接分配空间并初始化元素;但前者可能在动态添加元素时更灵活,但不初始化元素

  • 时间复杂度: O(n)

  • 空间复杂度: O(n)

思路二:三次翻转

先对原数组整个进行翻转,然后翻转前 k 个元素,最后翻转后 n-k 个元素。

数组的旋转 本质上是将数组的最后 k 个元素移动到数组的前面,其他元素向后移动。通过翻转,我们能将数组的顺序转换为反向的,并且逐步恢复局部顺序,最终实现整体的旋转。

三次翻转的优势:每次翻转只涉及局部区域的改变,不需要额外的空间(空间复杂度 O(1)),并且翻转操作本身的时间复杂度是线性的(O(n)),因此这个算法具有很好的时间效率和空间效率。

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        k = k % n;  // 处理k可能大于n的情况
        if (k == 0) return;  // 如果k是0,直接返回

        // 翻转整个数组
        reverse(nums.begin(), nums.end());
        
        // 翻转前k个元素
        reverse(nums.begin(), nums.begin() + k);
        
        // 翻转剩余的元素
        reverse(nums.begin() + k, nums.end());
        
    }
};
  •  时间复杂度:O(n)
  • 空间复杂度:O(1)

思路三:环状替换

这段代码暂时先放在这里,暂时还没弄懂这么做的原理是什么

class Solution {
public:
    void rotate(vector<int>& nums, int k) {
        int n = nums.size();
        k = k % n;
        int count = gcd(k, n);
        for (int start = 0; start < count; ++start) {
            int current = start;
            int prev = nums[start];
            do {
                int next = (current + k) % n;
                swap(nums[next], prev);
                current = next;
            } while (start != current);
        }
    }
};
  •  时间复杂度:O(n)
  • 空间复杂度:O(1)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值