经典题型---旋转数组

经典题型---旋转数组

文章目录

一、题目

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

示例 1:

复制代码
输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]
解释:
向右轮转 1 步: [7,1,2,3,4,5,6]
向右轮转 2 步: [6,7,1,2,3,4,5]
向右轮转 3 步: [5,6,7,1,2,3,4]

示例 2:

复制代码
输入:nums = [-1,-100,3,99], k = 2
输出:[3,99,-1,-100]
解释: 
向右轮转 1 步: [99,-1,-100,3]
向右轮转 2 步: [3,99,-1,-100]

提示:

1 <= nums.length <= 105

-231 <= nums[i] <= 231 - 1

0 <= k <= 105

题目理解

右旋可以理解成数组里的元素向右挪动k个单位,而出界的元素再按照正序补到前面的空位。

但是如果当k > numsSize的时候,那就需要使用到余数了,k % numsSize,直到k小于numsSize就可以进行程序操作了。

二、代码实现

法一:数组翻转法

c 复制代码
void rotate(int* nums, int numsSize, int k) {
    int i = 0, j = 0;
    for (i = 0, j = numsSize - k - 1; i <= j; i++, j--)
    {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
    for (i = numsSize - k, j = numsSize - 1; i <= j; i++, j--)
    {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
    for (i = 0; i < numsSize; i++)
    {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}

优化

c 复制代码
void Reverse(int* nums, int begin, int end)
{
    int i = 0, j = 0;
    for (i = begin, j = end; i <= j; i++, j--)
    {
        int tmp = nums[i];
        nums[i] = nums[j];
        nums[j] = tmp;
    }
}
void rotate(int* nums, int numsSize, int k)
{
    int i = 0, j = 0;
    Reverse(nums, 0, numsSize - k - 1);
    Reverse(nums, numsSize - k, numsSize - 1);
    Reverse(nums, 0, numsSize - 1);
}

不难看出时间复杂度是O(2n),即O(n)

法二:临时数组法

c 复制代码
void rotate(int* nums, int numsSize, int k) 
{
    int arr[100000] = { 0 };
    if (0 == k)
    {
        ;
    }
    else
    {
        k %= numsSize;
        while (k >= numsSize)
        {
            k %= numsSize;
        }
        int i = 0, j = 0;
        for (i = 0, j = numsSize - k; i < k, j <= numsSize - 1; i++, j++)
        {
            arr[i] = nums[j];
        }
        for (i = k, j = 0; i <= numsSize - 1, j < numsSize - k; i++, j++)
        {
            arr[i] = nums[j];
        }
        for (i = 0, j = 0; i < numsSize, j < numsSize; i++, j++)
        {
            nums[i] = arr[j];
        }
    }
}

优化

c 复制代码
void rotate(int* nums, int numsSize, int k) {
    int newArr[numsSize];//变长数组不能初始化
    for (int i = 0; i < numsSize; ++i) {
        newArr[(i + k) % numsSize] = nums[i];
    }
    for (int i = 0; i < numsSize; ++i) {
        nums[i] = newArr[i];
    }
}

这个方法在使用时,笔者掉入了一个很危险的错误,和大家分享出来,希望大家在以后的编程上避开这个坑。**

错误示范:

c 复制代码
void rotate(int* nums, int numsSize, int k) {//返回栈空间地址的问题
    int arr1[100000] = { 0 };
    if (0 == k)
    {
        ;
    }
    else
    {
        k %= numsSize;
        while (k >= numsSize)
        {
            k %= numsSize;
        }
        int i = 0, j = 0;
        for (i = 0, j = numsSize - k; i < k, j <= numsSize - 1; i++, j++)
        {
            arr1[i] = nums[j];
        }
        for (i = k, j = 0; i <= numsSize - 1, j < numsSize - k; i++, j++)
        {
            arr1[i] = nums[j];
        }
    }
    nums = arr1;
}

这是一个非常典型的返回栈空间(临时变量地址)的错误,在执行函数过程中,创建了一个临时数组,这个数组存储的就是满足输出形式的数组,但是当函数调用结束后,这块空间就被销毁了,nums反而成了野指针,所以这样的问题一定要避免。

在返回地址的时候要十分小心

相关推荐
九.九3 分钟前
CANN HCOMM 底层机制深度解析:集合通信算法实现、RoCE 网络协议栈优化与多级同步原语
网络·网络协议·算法
摇滚侠8 分钟前
macbook shell 客户端推荐 Electerm macbook 版本下载链接
java·开发语言
程序员布吉岛10 分钟前
Java 后端定时任务怎么选:@Scheduled、Quartz 还是 XXL-Job?(对比 + 避坑 + 选型)
java·开发语言
C++ 老炮儿的技术栈12 分钟前
Qt Creator中不写代如何设置 QLabel的颜色
c语言·开发语言·c++·qt·算法
知无不研14 分钟前
lambda表达式的原理和由来
java·开发语言·c++·lambda表达式
艾莉丝努力练剑16 分钟前
【Linux:文件】基础IO
linux·运维·c语言·c++·人工智能·io·文件
lili-felicity17 分钟前
CANN多模型并发部署与资源隔离
开发语言·人工智能
you-_ling18 分钟前
IO编程相关知识
c语言·vscode
小龙报21 分钟前
【51单片机】深度解析 51 串口 UART:原理、配置、收发实现与工程化应用全总结
c语言·开发语言·c++·stm32·单片机·嵌入式硬件·51单片机
子春一22 分钟前
Flutter for OpenHarmony:构建一个 Flutter 数字消消乐游戏,深入解析网格状态管理、合并算法与重力系统
算法·flutter·游戏