LeetCode初级算法之数组:189 旋转数组
旋转数组
题目地址:https://leetcode-cn.com/problems/rotate-array/
给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数。
示例 1:
输入: [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:
输入: [-1,-100,3,99] 和 k = 2
输出: [3,99,-1,-100]
解释:
向右旋转 1 步: [99,-1,-100,3]
向右旋转 2 步: [3,99,-1,-100]
说明:
- 尽可能想出更多的解决方案,至少有三种不同的方法可以解决这个问题。
- 要求使用空间复杂度为 O(1) 的 原地 算法。
题目信息
输入:数组nums、整数k
输出:修改数组(nums向右移动k位)
额外条件:空间复杂度O(1)
思考
首先想到的就是直接设置最终值,原地修改数据会丢失所以添加备份变量backup。备份值即原先值在移动时也需要与目的地数组值做交换则再需要一个中间值temp
以示例1数组演示
[1,2,3,4,5,6,7] k=3
//先原第1位移动三位到第4位
[1,2,3,1,5,6,7] backup = 4
//再移动原第4位值移动到第7位
[1,2,3,1,5,6,4] backup = 7
//再移动原第7位值移动到第3位
[1,2,7,1,5,6,4] backup = 3
//再移动原第3位值移动到第6位
[1,2,7,1,5,3,4] backup = 6
//再移动原第6位值移动到第2位
[1,6,7,1,5,3,4] backup = 2
//再移动原第2位值移动到第5位
[1,6,7,1,2,3,4] backup = 5
//再移动原第5位值移动到第1位
[5,6,7,1,2,3,4] backup = 1

最后循环到设置第一位,结束所有值移动完毕。
但这样的过程其实有个问题,并不是所有的情况都能一次循环移动所有元素。举两个例子:

示例一的情况一次循环就移动的所有元素,但上面两个例子从第一位出发到最后设置第一位完成循环但并没有设置完所有元素。一个要用两次循环一个三次。这样去使用一个中间变量去循环设值需要多少个循环取决于数组长度与k的最大公约数。
这样思路大体形成,是一个双循环。那么找到双循环的出循环条件,小循环结束条件则是下一步要移动的元素索引就是环状替换的开始索引,条件比较即使用while循环。外层循环条件两种方式都可以解决一种就是得到length与k公约数,第二种使用count计数,由于最后是数组元素全部移动所以会移动length次,小循环里每完成一次设值count累加,小循环完后来到外层循环如果count小于length则还有下一组循环。全部完成最终count是一定等于length的,出循环结束。
//这里提供一个求最大公约数的辗转相除法
int maxNumber(int m, int n) {
int temp;
if (n > m) {
temp = n;
n = m;
m = temp;
}
if (m % n == 0) {
return n;
}
return maxNumber(n, m % n);
}
public void rotate(int[] nums, int k) {
int len = nums.length;
for(int start = 0; start < maxNumber(len,k); start++){
/*
设置当前元素索引
将当前元素备份
*/
int current = start;
int backup = nums[current];
do{
//计数最终移动的索引
int next = (current + k) % len;
//当前元素原来值backup与目的地元素交换
int temp = nums[next];
nums[next] = backup;
backup = temp;
//交换完毕更新当前索引
current = next;
}while(start != current);
}
}
上面外循环以公约数为条件即已知循环次数完成,下面使用count在小循环里计数在外循环判断完成
方式一
public void rotate(int[] nums, int k) {
int count = 0;
int len = nums.length;
for(int start = 0; count < len; start++){
int current = start;
int backup = nums[current];
do{
int next = (current + k) % len;
int temp = nums[next];
nums[next] = backup;
backup = temp;
current = next;
count++;
}while(start != current);
}
}
这样环状替换的解决方式是最先想到的,还有一种方式看题目示例就可以get到这个方向。也就是解决整体移动一次的逻辑,接下来就是循环就完了。整体移动一次时间复杂度就为n然后完成n次。比上面的算法就复杂度来看差一些。完成整体移动一次使用交换法即可(用备份值方式仅仅多了变量不会影响时间复杂度)。
//每次使用最后位与i位进行交换,i++
[1,2,3,4,5] 1<==>5
[5,2,3,4,1] 2<==>1
[5,1,3,4,2] 3<==>2
[5,1,2,4,3] 4<==>3
[5,1,2,3,4]
for (int j = 0; j < len; j++) {
temp = nums[j];
nums[j] = nums[len-1];
nums[len-1] = temp;
}
那么有了这样一个移动一次的代码,再结合K外层循环
方式二
public void rotate(int[] nums, int k) {
int temp;
for (int i = 0; i < k; i++) {
for (int j = 0; j < nums.length; j++) {
temp = nums[j];
nums[j] = nums[nums.length-1];
nums[nums.length-1] = temp;
}
}
}
最后还有一个反转法,跳开设置值的思路,通过别的算法组合也能达到目标情况,在初高中数学当中也是常常有知道一个式子的值求一个很长的式子而不用把第一个式子解开而是将最终式子化成已知式子的组合最终简单求解。在这里也是一样一个反转算法这样的算法很简单
while (i < j) {
int temp = nums[i];
nums[1] = nums[j];
nums[j] = temp;
i++;
j--;
}
观察我们的要得到的一个结果
//nums = [1 2 3 4 5 6], k=3
1 2 3 4 5 6
4 5 6 1 2 3
可以通过反转的组合实现
1 2 3 4 5 6
6 5 4 3 2 1 全反转
4 5 6 3 2 1 0到k-1反转
4 5 6 1 2 3 k到len-1反转
这样就有新的方式解决,远远比直接带值要快(人脑层面),时间复杂度当然还是和方法一是相同的
方式三
public void reverse(int[] nums, int start, int end) {
while (start < end) {
int temp = nums[start];
nums[start] = nums[end];
nums[end] = temp;
start++;
end--;
}
}
public void rotate(int[] nums, int k) {
k %= nums.length;
reverse(nums, 0, nums.length - 1);
reverse(nums, 0, k - 1);
reverse(nums, k, nums.length - 1);
}
LeetCode初级算法之数组:189 旋转数组的更多相关文章
- LeetCode初级算法--数组02:旋转数组
LeetCode初级算法--数组02:旋转数组 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn.net/ ...
- 前端与算法 leetcode 189. 旋转数组
目录 # 前端与算法 leetcode 189. 旋转数组 题目描述 概要 提示 解析 算法 # 前端与算法 leetcode 189. 旋转数组 题目描述 189. 旋转数组 概要 把他当做一到简单 ...
- LeetCode初级算法的Python实现--数组
LeetCode初级算法的Python实现--数组 # -*- coding: utf-8 -*- """ @Created on 2018/6/3 17:06 @aut ...
- 【Leetcode】【简单】【189. 旋转数组】【JavaScript】
189. 旋转数组 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: [1,2,3,4,5,6,7] 和 k = 3输出: [5,6,7,1,2,3,4]解释 ...
- LeetCode 189. 旋转数组(Rotate Array)
189. 旋转数组 LeetCode189. Rotate Array 题目描述 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: [1,2,3,4,5,6, ...
- LeetCode初级算法之数组:48 旋转图像
旋转图像 题目地址:https://leetcode-cn.com/problems/rotate-image/ 给定一个 n × n 的二维矩阵表示一个图像. 将图像顺时针旋转 90 度. 说明: ...
- LeetCode初级算法(数组)解答
这里记录了LeetCode初级算法中数组的一些题目: 加一 本来想先转成整数,加1后再转回去:耽美想到测试的例子考虑到了这个方法的笨重,所以int类型超了最大范围65536,导致程序出错. class ...
- LeetCode初级算法--数组01:只出现一次的数字
LeetCode初级算法--数组01:只出现一次的数字 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:https://blog.csdn. ...
- LeetCode初级算法--设计问题01:Shuffle an Array (打乱数组)
LeetCode初级算法--设计问题01:Shuffle an Array (打乱数组) 搜索微信公众号:'AI-ming3526'或者'计算机视觉这件小事' 获取更多算法.机器学习干货 csdn:h ...
- Java实现 LeetCode 189 旋转数组
189. 旋转数组 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: [1,2,3,4,5,6,7] 和 k = 3 输出: [5,6,7,1,2,3,4] ...
随机推荐
- 绝对定位元素left、right、top、bottom值与其margin和宽高的关系
绝对定位元素(position: absolute)在其相对定位元素(即文档流中最近的非静态定位祖先元素)中,定位祖先元素的宽度为W,垂直高度为H,则存在以下关系: 元素水平方向 width + le ...
- CVE-2020-0769逆向分析
受影响版本: 系统 版本 Microsoft Windows 10 Windows 10 1607 Windows 10 1709 Windows 10 1803 Windows 10 1809 Wi ...
- 多项目部署在同一个GitHub Pages
由于GitHub 的约定,一个账户只能拥有一个GitHub Pages,那么,如果你有多个想部署的静态网站(博客和文档等),它们是互相隔离的,如何用同一个GitHub账户进行部署呢? 从之前如何搭建G ...
- ceph luminous版本限制osd的内存使用
引言 ceph自从到了L版本以后,L版本的启用,对性能本身有了极大的提高,一直对这个比较不放心的就是内存的占用,刚开始的时候记得大量dd就可以把内存搞崩掉,这个应该是内部的设计逻辑需要更多的内存的占用 ...
- Linux配置邮件发送信息
背景 一般情况下,我们的IT系统都会有相关的告警的处理,有的是邮件,有的是短信,这些都能很方便的获得一些有用的信息 在某些时候我们没有这样的系统,而自己又需要定期的获取一些信息的时候,配置一个邮件发送 ...
- ClickHouse 研讨会学习笔记(clickhouse tips and tricks)
一.显示执行日志 clickhouse-client --send_logs_level=trace 或者进入client session 后输入 set send_logs_level = 'tra ...
- 深度分享:面试阿里,字节跳动,美团90%会被问到的HashMap知识
一,HashTable 哈希表,它相比于hashMap结构简单点,它没有涉及红黑树,直接使用链表的方式解决哈希冲突. 我们看它的字段,和hashMap差不多,使用table存放元素 private t ...
- L-Rui
<!DOCTYPE html> <head> <meta charset="UTF-8"> <link rel="shortcu ...
- Kubernetes-20:日志聚合分析系统—Loki的搭建与使用
日志聚合分析系统--Loki 什么是Loki? Loki 是 Grafana Labs 团队最新的开源项目,是一个水平可扩展,高可用性,多租户的日志聚合系统.它的设计非常经济高效且易于操作,因为它不会 ...
- webgl智慧楼宇发光效果算法系列之高斯模糊
webgl智慧楼宇发光效果算法系列之高斯模糊 如果使用过PS之类的图像处理软件,相信对于模糊滤镜不会陌生,图像处理软件提供了众多的模糊算法.高斯模糊是其中的一种. 在我们的智慧楼宇的项目中,要求对楼宇 ...