首页 > 其他分享 >189. 轮转数组

189. 轮转数组

时间:2023-06-19 15:37:03浏览次数:36  
标签:count 轮转 nums int 复杂度 start length 数组 189

题目:

思路:

【1】如果采用辅助空间(这种是最简单的,因为需要遍历一遍,然后放入指定位置)

【2】对于进阶的处理,即只用空间复杂度为O(1)

【2.1】利用环的思维

其实这里需要理解一个比较绕的逻辑
就是从X位置开始循环,到回到X位置到底遍历了多少个元素
已知数组的元素个数是n,偏移量为k
(这个k < n,如果k>n,则k = k%n,因为n=7,而k=9的话其实不会是绕了一圈再偏移2而已,所以不如一开始就偏移2)

由于最终回到了起点,故该过程恰好走了整数数量的圈,不妨设为 a 圈;再设该过程总共遍历了 b 个元素。
因此,我们有 an=bk,即 an 一定为 n,k 的公倍数(且是最小公倍数)。
又因为我们在第一次回到起点时就结束,因此 aaa 要尽可能小,
故 an 就是 n,k 的最小公倍数 lcm(n,k),
因此 b 就为 lcm(n,k)/k。
即假设n=7,k=3,你就会发现圈数刚好是3,而遍历的个数恰好也是7。
为什么是最小公倍数呢,你往大了增,就是21的两倍三倍都没什么意义,不过是多饶了几圈
而既然有了b那么 n/b 就是表示应该要有几个数循环
如n=6,k=2,就要循环0和1
而n=7,k=3,只需要循环0
即 n/b = n*k/lcm(n,k) = 最大公约数 gcd(n,k)

【2.2】数组的翻转

代码展示:

采用辅助空间:

//时间1 ms 击败 62.57%
//内存54.2 MB 击败 77.43%
//时间复杂度: O(n),其中 n 为数组的长度。
//空间复杂度: O(n)。
class Solution {
    public void rotate(int[] nums, int k) {
        int count = nums.length;
        // 这里之所以这样处理是因为K可能大于nums.length,
        // 如果K=9,而nums.length = 7,那么不过是转了一圈后再偏移2
        int drift = k % count;
        //生成要借助的辅助空间且拷贝数据
        int[] result = Arrays.copyOf(nums,count);

        int i = 0;
        //先将数据从前部分偏移固定位置向后放置
        for (; i < count - drift; i++){
            nums[i + drift] = result[i];
        }
        //然后将需要前置的数据放入前置的位置
        int index = 0;
        for (; i < count; i++){
            nums[index++] = result[i];
        }
    }
}

//时间1 ms 击败 62.57%
//内存54.1 MB 击败 89.25%
class Solution {
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        int[] newArr = new int[n];
        for (int i = 0; i < n; ++i) {
            newArr[(i + k) % n] = nums[i];
        }
        System.arraycopy(newArr, 0, nums, 0, n);
    }
}

 

 

 

利用环的思维:

//时间1 ms 击败 62.57%
//内存54.1 MB 击败 85.81%
class Solution {
    public void rotate(int[] nums, int k) {
        int n = nums.length;
        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;
                int temp = nums[next];
                nums[next] = prev;
                prev = temp;
                current = next;
            } while (start != current);
        }
    }

    /**
     * 根据用欧几里得算法获取最大公约数
     * 如需要求 1255 和 840 两个正整数的最大公约数,是这样进行的:
     * 1255 ÷ 840 余 415
     * 840 ÷ 415 余 10
     * 415 ÷ 10 余 5
     * 10 ÷ 5 余 0
     * 至此,最大公约数为5
     * @return 最大公约数
     */
    public int gcd(int x, int y) {
        return y > 0 ? gcd(y, x % y) : x;
    }
}

 

 

 

数组的翻转:

//时间0 ms 击败 100%
//内存54.2 MB 击败 82.93%
//时间复杂度:O(n),其中 n 为数组的长度。
//每个元素被翻转两次,一共 n 个元素,因此总时间复杂度为 O(2n)=O(n)。
//空间复杂度:O(1)。
class Solution {
    public void rotate(int[] nums, int k) {
        int n=nums.length;
        k=k%n;
        reverse(nums,0,n-1);
        reverse(nums,0,k-1);
        reverse(nums,k,n-1);
    }

    private void reverse(int[] nums,int start,int end){
        while (start<end){
            int tmp=nums[start];
            nums[start]=nums[end];
            nums[end]=tmp;
            start++;
            end--;
        }
    }
}

标签:count,轮转,nums,int,复杂度,start,length,数组,189
From: https://www.cnblogs.com/chafry/p/17490545.html

相关文章

  • 数组的动态内存分配
     假设我们要为一个字符数组(一个有20个字符的字符串)分配内存,我们可以使用上面实例中的语法来为数组动态地分配内存,如下所示:char*pvalue=NULL;//初始化为null的指针pvalue=newchar[20];//为变量请求内存要删除我们刚才创建的数组,语句如下:delete[]pvalue;//......
  • js数组常用的方法
    在JavaScript中,数组是一种非常重要的数据类型。数组提供了一系列常用的方法,可以方便地对数组进行操作和处理。本文将介绍JavaScript中几种常用的数组方法的含义、返回值以及是否改变原数组。一、push()push()方法可以将一个或多个元素添加到数组的末尾,并返回数组的新长度。例如:......
  • 2023-06-18:给定一个长度为N的一维数组scores, 代表0~N-1号员工的初始得分, scores[i] =
    2023-06-18:给定一个长度为N的一维数组scores,代表0~N-1号员工的初始得分,scores[i]=a,表示i号员工一开始得分是a,给定一个长度为M的二维数组operations,operations[i]={a,b,c}。表示第i号操作为:如果a==1,表示将目前分数<b的所有员工,分数改成b,c这个值无用,如果a==2,表示将......
  • 微信小程序更改刷新data 数组结构里的某一项数据
    如果每次setData 中list整个数组,感觉会消耗性能,所以只需要setData刷新对应的item  只需要通过以下方式解决    this.setData({'array[0].text':'updatedata'})//如果索引是动态的则使用下方方式varmMessage='array['+index+'].text';this.set......
  • 【numpy基础】--数组简介
    NumPy(NumericalPython)是一个Python库,主要用于高效地处理多维数组和矩阵计算。它是科学计算领域中使用最广泛的一个库。在NumPy中,数组是最核心的概念,用于存储和操作数据。NumPy数组是一种多维数组对象,可以存储相同类型的元素,它支持高效的数学运算和线性代数操作。1.数据类型n......
  • C# 获取数组排序后的下标
    usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Text;usingSystem.Threading.Tasks;namespaceConsoleApp9{classProgram{staticvoidMain(string[]args){int[]src=newint[]{2,1......
  • 前端学习C语言 - 数组和字节序
    数组本篇主要介绍:一维二维数组、字符数组、数组名和初始化注意点以及字节序。一维数组初始化有以下几种方式对数组初始化://定义一个有5个元素的数组,未初始化inta[5];//定义一个有5个元素的数组,将第一个初始化0,后面几个元素默认初始化为0inta[5]={0};//定义一个有5个元......
  • 101 显示数组中的大写字母 小写字母 数字
    packagecom.fqs.demo001;importjava.util.Scanner;publicclassCompare{publicstaticvoidmain(String[]args){//键盘录入一个字符串,统计该字符串大写字母字符,小写字母字符,数字字符出现的次数//比如ABCabc123Scannersc=newScanner(......
  • 前端学习C语言 - 数组和字节序
    数组本篇主要介绍:一维二维数组、字符数组、数组名和初始化注意点以及字节序。一维数组初始化有以下几种方式对数组初始化://定义一个有5个元素的数组,未初始化inta[5];//定义一个有5个元素的数组,将第一个初始化0,后面几个元素默认初始化为0inta[5]={0};//定义一个......
  • 字符串数组不能转化对象数组,jsonArray也转化报错
    刚开始写法------错误JSONArrayjsonArray=(JSONArray)this.getJsonFilter().get("ids");PltPayDuesModel[]payDuesModels=(PltPayDuesModel[])jsonArray.toArray();报这个[Ljava.lang.Object;cannotbecastto[Ljava.lang.String;由于无法直接,因此需要曲线救国......