当前位置: 首页 > news >正文

力扣热题100道之189轮转数组

解法

这道题我用了四个半点的时间做出来。最开始找的那种方法,不到一个点就做出来了,后面的思路有些难以理清。从这道题目中我受益匪浅,没有掌握的知识点有dowhile的用法,还有找到两个数的最大公约数的方法。

class Solution {public void rotate(int[] nums, int k) {int n = nums.length;k=k%n;int c=gcd(n,k);for(int i=0;i<c;i++){int curr=i;int pre=nums[i];                    do{int next=(curr+k)%n;int tmp=nums[next];nums[next]=pre;pre=tmp;      curr=next;                             }while(curr!=i);}}public int gcd(int x,int y){return y>0?gcd(y,x%y):x;}}
找到两个数的最大公约数的方法

代码如下,之后可以直接定义这个方法,然后直接用就可以,后面有解释的地方,可以帮助理解

public int gcd(int x,int y){return y>0?gcd(y,x%y):x;
}
1. 算法历史与基本思想

欧几里得算法是历史上最古老的算法之一,出现在欧几里得的《几何原本》(公元前300年左右)。它的目的是求两个整数的最大公约数

最大公约数​:能同时整除两个数的最大正整数。
例如:gcd(12, 18) = 6,因为6是能整除12和18的最大整数。


2. 算法核心原理

关键定理​:

如果 a = b * q + r(其中 q 是商,r 是余数,且 0 ≤ r < b),那么:

gcd(a, b) = gcd(b, r)

为什么成立?​

  • 设 d = gcd(a, b),那么 d 能整除 a 和 b
  • 因为 r = a - b * q,所以 d 也能整除 r
  • 因此 d 是 b 和 r 的公约数
  • 同理,任何能整除 b 和 r 的数也能整除 a
  • 所以 gcd(a, b) = gcd(b, r)
3. 数学推导示例

手动计算​ gcd(48, 18)

48 ÷ 18 = 2 余 12  → gcd(48, 18) = gcd(18, 12)
18 ÷ 12 = 1 余 6   → gcd(18, 12) = gcd(12, 6)
12 ÷ 6  = 2 余 0   → gcd(12, 6) = 6

另一个例子​ gcd(1071, 462)

1071 ÷ 462 = 2 余 147 → gcd(1071, 462) = gcd(462, 147)
462 ÷ 147 = 3 余 21   → gcd(462, 147) = gcd(147, 21)
147 ÷ 21 = 7 余 0     → gcd(147, 21) = 21
历史解法
分别开辟了两个总长为n的空间的解法

首先,关于这道题的理解,当k<n的时候,也就是题目描述中给出的那些情况,将后半段和前半段分别存储到一个第三方空间中,再分别复制到nums数组中。当k>n的时候,k=k%n,他是这么算的,这个题目中也没有明说,感觉要是这点他明说的话,可以省去好多时间。

class Solution {public void rotate(int[] nums, int k) {int  n=nums.length;if(n!=1&&n>=k){int []tmp=new int[k];int[]t=new int[n-k];for(int i=n-k;i<n;i++){tmp[i-n+k]=nums[i];}for(int i=0;i<n-k;i++){t[i]=nums[i];}for(int i=0;i<k;i++){nums[i]=tmp[i];}for(int i=0;i<n-k;i++){nums[i+k]=t[i];}}else{k=k%n;int []tmp=new int[k];int[]t=new int[n-k];for(int i=n-k;i<n;i++){tmp[i-n+k]=nums[i];}for(int i=0;i<n-k;i++){t[i]=nums[i];}for(int i=0;i<k;i++){nums[i]=tmp[i];}for(int i=0;i<n-k;i++){nums[i+k]=t[i];}}}
}
优化上面的那个方法

我发现那个条件判断语句可以单独列在前面。

class Solution {public void rotate(int[] nums, int k) {int  n=nums.length;if(n!=1&&n>=k){k=k;}else{k=k%n;}int []tmp=new int[k];int[]t=new int[n-k];for(int i=n-k;i<n;i++){tmp[i-n+k]=nums[i];}for(int i=0;i<n-k;i++){t[i]=nums[i];}for(int i=0;i<k;i++){nums[i]=tmp[i];}for(int i=0;i<n-k;i++){nums[i+k]=t[i];}}
}
目标空间复杂度为O(1)但失败的方法

这个方法,我想通过每次直接找到一个数据的准确位置,下一次直接找到被替换的数据的正确位置,这样就可以直接找到所有值的正确位置了。但是最后我发现有一个问题,我没有解决,就是当满足一些条件比如n==2k再比如n=6,k=2(可能是当n可以整除k)的时候,会来回就更新那几个数字,跑不到别的数字上面,就搞得很难受。我觉得再有一些时间我肯定能解决这个问题,但是,这道题我已经看了两个半点了,再看有些不划算了。所以,我准备直接看答案。看这种最优解法。

class Solution {public void rotate(int[] nums, int k) {int n = nums.length;if (n != 1 && n >= k) {k = k;} else {k = k % n;}int count = 0;int i = 0;int tmp;int t = nums[0];if (n != 2 * k) {while (count < n) {if (n == 2 && k == 2) {break;}int l=n-k-1;if (i <= l) {tmp = nums[i + k];nums[i + k] = t;t = tmp;i = i + k;} else {tmp = nums[i - n + k];nums[i - n + k] = t;t = tmp;i = i - n + k;}count++;}} else {for (int j = 0; j < k; j++) {tmp = nums[j];nums[j] = nums[j + k];nums[j + k] = tmp;}}}}
对上面方法的优化

我看题解,看到了找下一个的一个好方法(i+k)%n。这个方法可以直接少了很多条件判断的语句,代码量少了一半,效果还差不多,但是那个陷入局部走不出来的方法还是没有解决。

class Solution {public void rotate(int[] nums, int k) {int n = nums.length;if (n != 1 && n >= k) {k = k;} else {k = k % n;}int count = 0;int i = 0;int tmp;int t = nums[0];if(n!=2*k){while (count < n) {tmp = nums[(i + k)%n];nums[(i + k)%n] = t;t = tmp;i = (i + k)%n;         count++;         }}else{for (int j = 0; j < k; j++) {tmp = nums[j];nums[j] = nums[j + k];nums[j + k] = tmp;}                }}}
因为while()和do...while()的区别而报错的方法

我看了题解,但是一直做不出来,我总是想如果我完全理解了题解中的方法,那么我不要跟他的方法完全一样。

class Solution {public void rotate(int[] nums, int k) {int n = nums.length;k=k%n;int c=gcd(n,k);for(int i=0;i<c;i++){int curr=i;int pre=nums[i];                    while(curr!=i){int next=(curr+k)%n;int tmp=nums[next];nums[next]=pre;pre=tmp;      curr=next;                             }}}public int gcd(int x,int y){return y>0?gcd(y,x%y):x;}}

http://www.dtcms.com/a/516992.html

相关文章:

  • AutoGen框架入门:5个核心概念搭建智能体协作系统
  • MySQL 慢查询诊断与 SQL 优化实战指南(适配 MySQL 8.4 LTS)
  • wordpress 上传svg南通seo网站推广费用
  • 蓝桥杯-16955 岁月流转
  • 每日一个网络知识点:应用层WWW与HTTP
  • 个人网站建设实验心得投资公司取名字大全
  • 欧美网站建设公司东莞专业的网站制作有哪些
  • xtuoj Candy
  • 襄阳大摩网站建设网站开发者所有权归属
  • 一条龙网站建设价格编程应用
  • StarsNote 1.1.0测试版
  • Java--网络原理
  • 2025-10-21 XiaoQuQu 的 2025 CSP-S 第二轮模拟 ROUND2 补题
  • react中的受控组件与非受控组件
  • iOS的动态库和静态库的差异区别以及静态库的好处
  • Word文档中打勾和打叉的三种方法
  • 基于微信小程序的高校班务管理系统【2026最新】
  • 编程教学网站推荐网络营销广告策划
  • 网站建设开票属于哪个名称锦州网站建设品牌
  • 基于SAM2的眼动数据跟踪6——SAM2跟踪
  • Factory Boy:Python测试数据生成的优雅方案
  • 网站icp备案团购网站模板下载
  • 肾脏癌症图像分类数据集
  • 亚马逊云渠道商:AWS Lake Formation是什么?
  • 动画网站源码网站搭建 保定
  • 甘肃做网站工信部查网站备案
  • matlab的map函数怎么使用
  • 郴州网站seo外包wordpress+分页静态
  • 网站做的好坏主要看discuz论坛源码
  • 【展厅多媒体】飞屏互动技术如何增强展厅的科技氛围?