leetcode初级———旋转数组的多种算法总结

题目描述:

给你一个数组,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

(来源:leetcode)

1.数组拆分

//经观察发现:将数组元素全部后移k单位即将后 k%length 个元素前置,为此我们可以借助一个新数组存储这些 需要前置的元素,然后整体迁移。

void rotate(int* nums, int numsSize, int k){
    k = k % numsSize;
    if(!nums || numsSize < 2 || k <= 0) return;
    int maxInd = numsSize - 1;
    int oriInd = maxInd - k;
    int opInd = oriInd + 1;
    int i, j = 0;
    int temp[k];
    for(i = 0;i < k; i++){
        temp[i] = nums[opInd++];
    } //存储需要前置的元素
    for(i = oriInd; i >= 0; i--){
        nums[maxInd--] = nums[i];
    } //剩余元素后置
    for(i = 0; i < k; i++){
        nums[i] = temp[i];
    } //元素前置
}

2.暴力解法

//新创建一个数组,按原数组旋转后的正确顺序到新数组中,再放回。

void rotate(int* nums, int numsSize, int k){
    if(!nums || numsSize == 0 || k == 0) return;
    int i, temp[numsSize];
    for(i = 0; i < numsSize; i++){
        temp[(i+k)%numsSize] = nums[i];
    } //在新数组的元素移动后位置摆放各个元素
    for(i = 0; i < numsSize; i++){
        nums[i] = temp[i];
    } //拷贝回原数组
}

3.三次原地反转

//思路同一,需要把后 K 个元素前置,可以先将整个数组翻转,再把前 k 个元素翻转,最后剩余元素翻转。这种方法空间复杂度低。

void rotate(int* nums, int numsSize, int k){
    if(!nums || numsSize < 2 || k == 0) return;
    k = k % numsSize;
    int i;
    for(i = 0; i < numsSize / 2; i++){
        nums[i] = nums[i] + nums[numsSize-i-1];
        nums[numsSize-i-1] = nums[i] - nums[numsSize-i-1];
        nums[i] = nums[i] - nums[numsSize-i-1];
    } // 整个数组翻转
    for(i = 0; i < k / 2; i++){
        nums[i] = nums[i] + nums[k-i-1];
        nums[k-i-1] = nums[i] - nums[k-i-1];
        nums[i] = nums[i] - nums[k-i-1];
    } // 前 k 个元素翻转
    for(i = k; i < (numsSize + k) / 2; i++){
        nums[i] = nums[i] + nums[numsSize-1-i+k];
        nums[numsSize-1-i+k] = nums[i] - nums[numsSize-1-i+k];
        nums[i] = nums[i] - nums[numsSize-1-i+k];
    } // 剩余元素翻转
}

4.临时变量

// 借助一个临时变量持续元素向后迁移。但需要注意当 length%k = 0 时,这一特殊条件。

void rotate(int* nums, int numsSize, int k){
    if(!nums || numsSize < 2 || k == 0) return;
    k = k % numsSize;
    int temp = nums[0], i = 0, j = k, t, count = 0; 
    while(i++ < numsSize){ //持续对每一个元素都摆放到正确位置
        t = nums[j];
        nums[j] = temp;
        temp = t;
        if(j == count){ //当 j 又回到出发点时说明发生了原地打转
            count = (count + 1) % numsSize; //从下一个开始
            j = count;
            temp = nums[j];
        }
        j = (j + k) % numsSize; //j用来寻找当前元素的移动后落脚点
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值