• 经典题型---旋转数组


    经典题型—旋转数组

    一、题目

    给定一个整数数组 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]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    示例 2:

    输入:nums = [-1,-100,3,99], k = 2
    输出:[3,99,-1,-100]
    解释: 
    向右轮转 1 步: [99,-1,-100,3]
    向右轮转 2 步: [3,99,-1,-100]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    提示:

    1 <= nums.length <= 105

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

    0 <= k <= 105

    题目理解

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

    在这里插入图片描述
    但是如果当k > numsSize的时候,那就需要使用到余数了,k % numsSize,直到k小于numsSize就可以进行程序操作了。

    二、代码实现

    法一:数组翻转法

    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;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    优化

    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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

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

    法二:临时数组法

    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];
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    优化

    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];
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

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

    错误示范:

    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;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

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

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

  • 相关阅读:
    著名童星刘佳琪深圳市中心举办个人Live音乐汇专辑发布会圆满成功
    Bit.Store:熊市漫漫,稳定Staking产品或成主旋律
    从技术角度看城市停车难问题
    AI小程序——文本绘图
    十三、函数式编程(3)
    设计模式-抽象工厂模式
    SLAM从入门到精通(用python实现机器人运动控制)
    通过jmap、jstack分析问题,以及分析方法
    网络规划设计师之OSI七层模型之应用层
    webrtc一对一视频通话功能实现
  • 原文地址:https://blog.csdn.net/xxrxxulj/article/details/133966800