LeetCode.189(轮转数组)

对于轮转数组这个题,文章一共提供三种思路,对于每种思路均提供其对应代码的时间、空间复杂度。

目录

1. 创建变量来保存最后一个数,并将其余数组向前挪动一位 :

1.1 原理解析:

1.2 代码实现:

 2.创建一个数组,用于存放需要旋转的元素,并放到相应位置:

2.1 原理解析:

2.2 代码实现:

3. 先左部分右旋,再右部分右旋,最后整体逆序(三段逆序法):

3.1 原理解析:

 3.2 代码实现:


题目要求如图所示:

 

1. 创建变量来保存最后一个数,并将其余数组向前挪动一位 :

(注:第一种思路虽然可以解决问题,但是代码的时间复杂度为O(N^2),空间复杂度为O(1),时间复杂度不符合LeetCode的提交标准,所以,第一种思路仅供参考与扩展。)

1.1 原理解析:

 假设一个数组为:

nums[7] = {1,2,3,4,5,6,7};

为了方便表示,用下图来代表数组及数组中的元素:

第一步:先将数组种最后一位元素,即:7,用一个临时变量保存。

 

第二步:将其他剩余元素全部向右移动一位。

 

第三步: 把临时变量保存的7,放到数组的首元素的位置。

 

 至此,完成一次交换。

1.2 代码实现:

用代码表示上述过程,即:

#include<stdio.h>
#include<assert.h>
void rotata(int* nums,int numsize)
{assert(nums);int tmp = nums[numsize - 1];//用临时变量保存数组最后一个元素int i = 0;for (i = 6 ; i > 0; i--){nums[i] = nums[i - 1];//将其余元素向右移动一位}nums[0] = tmp;//将临时变量保存的元素放在数组首个元素的位置
}
int main()
{int nums[7] = { 1,2,3,4,5,6,7 };int sz = sizeof(nums) / sizeof(nums[0]);rotata(nums, sz );return 0;
}

打印结果如下:

 

上面的代码,只能实现右移一位。对于移动多个元素,可以将上面移动一个元素的过程用循环来进行。例如,用变量k来代表旋转的次数,代码为:

#include<stdio.h>
#include<assert.h>
void rotata(int* nums,int numsize,int k)
{k = k % numsize + 1;//防止k过大,使k的范围在0-7assert(nums);int j = 0;for (j = 0; j < k; j++){int tmp = nums[numsize - 1];//用临时变量保存数组最后一个元素int i = 0;for (i = 6; i > 0; i--)    //0 1 2 3 4 5 6 //  1 2 3 4 5 6{nums[i] = nums[i - 1];//将其余元素向右移动一位}nums[0] = tmp;//将临时变量保存的元素放在数组首个元素的位置}}
int main()
{int nums[7] = { 1,2,3,4,5,6,7 };int sz = sizeof(nums) / sizeof(nums[0]);int k = 0;scanf("%d", &k);rotata(nums, sz,k );int i = 0;return 0;
}

因为数组每旋转7次,数组中的元素就回到不旋转的位置,所以,即使在输入旋转次数为77次时,得到的效果也和旋转一次一样

旋转一次效果:

旋转两次效果:

 

旋转77次:

 

但是,当k的值过大时,因为每右旋7次就是一个循环,所以,为了减少编译器的工作量,用k%numsize+1,让k的取值范围保持在0\rightarrow 7这个区间(闭区间)

 2.创建一个数组,用于存放需要旋转的元素,并放到相应位置:

方法二的时间复杂度为O(N),空间复杂度为O(N)

2.1 原理解析:

依旧使用上面的图来解释思路:

右旋一次:

 右旋两次:

对于上面的两种情况,不难发现,其实所谓的右旋,可理解为将需要进行右旋的元素看成一个整体,让后放到其余元素的前面,例如旋转两次时:

第一步:将元素6,7看作一个整体,其余元素看成一个整体。

 

第二步:作为整体的6,7放到剩余元素的前面进行整合:

 

2.2 代码实现:

有了解决问题的思路后,下面给出具体实现的代码:

void rotate(int* nums, int numsSize, int k){int n = numsSize;int* tmp = (int*)malloc(sizeof(int)*(n));k = k%n;memcpy(tmp,nums+n-k,sizeof(int)*(k));memcpy(tmp+k,nums,sizeof(int)*(n-k));memcpy(nums,tmp,sizeof(int)*(n));free(tmp);}

 整体代码的逻辑为: n是数组中元素的个数,k是执行右旋的次数。

1.先用malloc开辟一块空间 

2.用k%n来限制k的取值范围。

3.先利用memcpy函数将nums数组种起始地址n+k,数量为k的元素拷贝到tmp这个临时空间种。

4.再利用memcpy函数将nums剩余的元素拷贝到tmp中。

此时,tmp已经存储了旋转后的数组。

5.将tmp中的元素赋值到nums中。

执行结果如下:

 从结果中可以看到,方法二是用空间来换取速度的方法。

3. 先左部分右旋,再右部分右旋,最后整体逆序(三段逆序法):

最优解法,时间复杂度为O(N),空间复杂度因为只创建了一个额外的临时变量,为O(1)

3.1 原理解析:

对于三段逆序法,同样使用图片来解释:

假设:数组名为nums,数组中的元素个数为n,按照LeetCode中7个元素。需要旋转的位数为k。下面的代码就拿k = 3来解释。

第一步:先将左部分元素整体逆序,即:把下标从0到nums-k-1(即数组中第一个到第四个元素逆序)的元素逆序:

 

第二步:将右半部分元素整体逆序,即:把下标为nums - kn-1(即数组中第五个到第七个元素逆序):

第三步:整体逆序:即:对下标从0到nums-1的元素逆序:

通过LeetCode网站给出的样例发现,整体逆序后结果与样例相同:

 

 3.2 代码实现:

  在上面的解释中,既然每一步都需要逆序,所以,为了方便并且减少代码量,可以提前封装一个交换函数或者直接使用交换函数,这里给出提前封装交换函数的代码:

其中:变量a对应数组nums,变量left对应交换的起始位置,变量right对于交换的结束位置

void reserve( int*a,int left,int right)
{while(left < right){int tmp = a[left];a[left] = a[right];a[right] = tmp;left++;right--;}
}

再交换后,根据上面对原理的解释,对逆序函数进行三次调用并传递相应的参数即可:

void rotate(int* nums, int numsSize, int k){int n = numsSize;k = k%n;reserve(nums,0,n-k-1);reserve(nums,n-k,n-1);reserve(nums,0,n-1);}

整体函数如下:

void reserve( int*a,int left,int right)
{while(left < right){int tmp = a[left];a[left] = a[right];a[right] = tmp;left++;right--;}
}void rotate(int* nums, int numsSize, int k){int n = numsSize;k = k%n;reserve(nums,0,n-k-1);reserve(nums,n-k,n-1);reserve(nums,0,n-1);}

运行结果如下:

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/14775.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NFT和数字藏品的安全方案解析

一、NFT和数字藏品 01 NFT是什么&#xff1f; NFT 是Non-Fungible Tokens 的缩写&#xff0c;意思是不可互换的代币&#xff0c;它是相对于可互换的代币而言的。不可互换的代币也称为非同质代币。什么是可互换的代币&#xff1f;比如BTC&#xff08;比特币&#xff09;、ETH&…

前端,js , Error in created hook: TypeError ,有bug了

怎么兄弟&#xff0c;遇到bug了&#xff1f;&#xff1f;&#xff1f;你开心吗&#xff0c;哈哈哈哈

如何在MacBook上彻底删除mysql

好久以前安装过&#xff0c;但是现在配置mysql一直出错&#xff0c;索性全部删掉重新配置。 一、停止MySQL服务 首先&#xff0c;请确保 MySQL 服务器已经停止运行&#xff0c;以免影响后续的删除操作。 sudo /usr/local/mysql/support-files/mysql.server stop如果你输入之…

kotlin 编写一个简单的天气预报app(四)

编写界面来显示返回的数据 用户友好性&#xff1a;通过界面设计和用户体验优化&#xff0c;可以使天气信息更易读、易理解和易操作。有效的界面设计可以提高用户满意度并提供更好的交互体验。 增加城市名字的TextView <TextViewandroid:id"id/textViewCityName"…

Kyuubi入门简介

一、官方简介 HOME — Apache Kyuubi 二、概述 1、一个企业级数据湖探索平台 2、一个高性能的通用JDBC和SQL执行引擎 3、一个基于spark的查询引擎服务 三、优点 1、提供hiveserver2查询spark sql的能力&#xff0c;查询效率更为高效&#xff0c;首次构建连接时会持续保持连…

628. 三个数的最大乘积

628. 三个数的最大乘积 class Solution {public int maximumProduct(int[] nums) {Arrays.sort(nums); return Math.max(nums[nums.length-1]*nums[nums.length-2]*nums[nums.length-3],nums[0]*nums[1]*nums[nums.length-1]);} }

c语言位段知识详解

本篇文章带来位段相关知识详细讲解&#xff01; 如果您觉得文章不错&#xff0c;期待你的一键三连哦&#xff0c;你的鼓励是我创作的动力之源&#xff0c;让我们一起加油&#xff0c;一起奔跑&#xff0c;让我们顶峰相见&#xff01;&#xff01;&#xff01; 目录 一.什么是…

聊聊这几年的科技风口

作者&#xff1a;朱金灿 来源&#xff1a;clever101的专栏 为什么大多数人学不会人工智能编程&#xff1f;>>> 数数这几年的科技风口&#xff1a;AR&#xff08;包括什么MR、VR&#xff09;、区块链(包括后来的什么web3)、元宇宙到现在的AI&#xff0c;下面逐一谈谈…

在Ail Linux中手动配置IPv6

第一步&#xff0c;登录阿里云服务器控制台&#xff0c;在“概览”页面找到对应实例&#xff0c;然后单击实例ID。 第二步&#xff0c;在“实例详情”页面中的“网络信息”栏目中&#xff0c;可以发现“IPv6 地址”中没有数据&#xff0c;然后单击“专有网络”的专有网络ID。 第…

使用IDEA打jar包的详细图文教程

1. 点击intellij idea左上角的“File”菜单 -> Project Structure 2. 点击"Artifacts" -> 绿色的"" -> “JAR” -> Empty 3. Name栏填入自定义的名字&#xff0c;Output ditectory 选择 jar 包目标目录&#xff0c;Available Elements 里右击…

QTableWidget setSortingEnable 函数使用详解

Qt助手的解释 If enable is true, enables sorting for the table and immediately trigger a call to sortByColumn() with the current sort section and order Note: Setter function for property sortingEnabled. 如果将 enable 设置为 true 那么就会立即调用 sortByColum…

使用Appuploader工具将IPA上传到App Store的最新流程和步骤

​ 苹果官方提供的工具xcode上架ipa非常复杂麻烦。用appuploader 可以在 mac 和windows 上制作管理 证书 &#xff0c;无需钥匙串工具 条件&#xff1a;1.以Windows为例&#xff0c;创建app打包ios需要的证书和描述文件 2.准备好一个苹果开发者账号&#xff08;如果没有到苹果…

matlab使用教程(5)—矩阵定义和基本运算

本博客介绍如何在 MATLAB 中创建矩阵和执行基本矩阵计算。 MATLAB 环境使用矩阵来表示包含以二维网格排列的实数或复数的变量。更广泛而言&#xff0c;数组为向量、矩阵或更高维度的数值网格。MATLAB 中的所有数组都是矩形&#xff0c;在这种意义上沿任何维度的分量向量的长度…

C++ 类和对象篇(一) 类的引入

目录 一、类的概念 二、类的引入 三、类的定义 1.定义一个类 2.struct 和 class 的区别 3.类中成员函数的声明、实现分离 四、封装及类的访问限定符 1.封装 2.类的访问限定符 五、类的作用域和生命周期 六、类的实例化 七、类存储方法 八、计算类的大小 一、类的概念 1…

大盗阿福(记忆化搜索板子)

提供核心代码&#xff1a;&#xff08;经典的记忆化搜索套路&#xff09; int dfs(int pos){if(f[pos]!-1) return f[pos];//记忆化if(pos>n) return 0;//边界&#xff0c;越界int sum0;//模板int f10,f20;f1dfs(pos1);f2dfs(pos2)w[pos];summax(f1,f2);//模板f[pos]sum;//模…

TypeScript基础篇 - TS模块

目录 模块的概念 Export 语法&#xff08;default&#xff09; Export 语法&#xff08;non-default&#xff09; import 别名 Type Export语法【TS】 模块相关配置项&#xff1a;module【tsconfig.json】 模块相关配置项&#xff1a;moduleResolution 小节总结 模块的…

动态内存管理面试题

动态内存管理面试题 文章目录 动态内存管理面试题一、第一题此代码存在的问题运行结果分析原因修改 二、第二题此代码存在的问题运行结果分析原因修改 一、第一题 代码如下&#xff08;示例&#xff09;&#xff1a; #include<stdio.h> #include<string.h> #incl…

数据结构:顺序表详解

数据结构&#xff1a;顺序表详解 一、 线性表二、 顺序表概念及结构1. 静态顺序表&#xff1a;使用定长数组存储元素。2. 动态顺序表&#xff1a;使用动态开辟的数组存储。三、接口实现1. 创建2. 初始化3. 扩容4. 打印5. 销毁6. 尾插7. 尾删8. 头插9. 头删10. 插入任意位置数据…

《MySQL 实战 45 讲》课程学习笔记(三)

事务隔离 事务就是要保证一组数据库操作&#xff0c;要么全部成功&#xff0c;要么全部失败。 隔离性与隔离级别 事务特性&#xff1a;ACID&#xff08;Atomicity、Consistency、Isolation、Durability&#xff0c;即原子性、一致性、隔离性、持久性&#xff09;。当数据库上…

100行代码写一个简易QT点名程序

照例演示一下: 分享一个简易的Qt点名程序&#xff0c;满打满算一百行代码&#xff08;还要什么自行车&#xff09;。 UI界面比较丑&#xff0c;按钮是自己做的&#xff0c;背景是AI作画生成的&#xff0c;大家可以自行更换背景以及按钮。 内容也是非常的简单&#xff0c;就是…