LeetCode初级算法之数组:48 旋转图像
旋转图像
题目地址:https://leetcode-cn.com/problems/rotate-image/
给定一个 n × n 的二维矩阵表示一个图像。
将图像顺时针旋转 90 度。
说明:
你必须在原地旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要使用另一个矩阵来旋转图像。
示例 1:
给定 matrix =
[
[1,2,3],
[4,5,6],
[7,8,9]
],
原地旋转输入矩阵,使其变为:
[
[7,4,1],
[8,5,2],
[9,6,3]
]
示例 2:
给定 matrix =
[
[ 5, 1, 9,11],
[ 2, 4, 8,10],
[13, 3, 6, 7],
[15,14,12,16]
],
原地旋转输入矩阵,使其变为:
[
[15,13, 2, 5],
[14, 3, 4, 1],
[12, 6, 8, 9],
[16, 7,10,11]
]
四指针
这一题与前面写到的旋转数组一题相似,之前是一维的,现在相当于是二维版。同样是两种思路一种是直接设置值到最终的地方,被覆盖的值先用备份变量拿出来再往它的目的地去设。第二种就是反转的思路。

旋转上图过程
(1)
backup = m[0][1]
m[0][1] = m[0][0]
(2)
temp = backup
backup = m[1][1]
m[1][1] = temp
(3)
temp = backup
backup = m[1][0]
m[1][0] = temp
(4)
m[0][0] = backup
由于是2×2所以一次旋转设值完事,如果是3×3

和之前那一题还是有点差别,这边设置值的传递固定是四个完成一组,然后需要判断一圈有多少组
1×1 0组
2×2 1组
3×3 2组

四次设置值是一个单元操作,之后指针变动第一个指针是水平向右移动,第二个指针是垂直向下其他依次,直到头length-1。那么外循环条件是有几圈2×2,3×3都只有一圈,4×4与5×5是两圈。也就是length/2圈,内循环为每圈要移动多少组数字它取决于终点索引,并且每往内一圈length都会少2两边都会靠近1格。
- 外圈(第一圈)起点
matrix[0][0]终点matrix[0][2]有三组 - 内圈(第二圈)起点
matrix[1][1]终点matrix[1][1]只有一组
也就是当外循环完毕内循环的起点是和外循环相同,也就是j = i然后j在往后递增直到终点,终点会往内圈慢慢递减

我们这里只看首指针的变化,其他一样推总结在代码里
- 第一圈从
[0][0]--->[0][4]5组 - 第二圈从
[1][1]--->[1][3]3组 - 第三圈就
[2][2]1组
public void rotate(int[][] matrix) {
int n = matrix.length;
int s = n;
for (int i = 0; i < n/2; i++,s--) {
for (int j = i; j < s-1; j++) {
int backup = matrix[j][n-i-1];
matrix[j][n-i-1] = matrix[i][j];
int temp = matrix[n-i-1][n-j-1];
matrix[n-i-1][n-j-1] = backup;
backup = temp;
temp = matrix[n-j-1][i];
matrix[n-j-1][i] = backup;
backup = temp;
matrix[i][j] = backup;
}
}
}
总体实现了这样一个主线,但就是我们去存将被覆盖的值其实不需要另外添加一个变量backup我们可以直接把它存在首指针的地方,那个地方到最后才被设值中途是啥都没有关系我们就暂时用它存(空间已经存在了不用白不用)。
public void rotate(int[][] matrix) {
int n = matrix.length;
int s = n;
for (int i = 0; i < n/2; i++,s--) {
for (int j = i; j < s-1; j++) {
int temp = matrix[i][j]
matrix[i][j] = matrix[j][n-i-1];
matrix[j][n-i-1] = temp;
temp = matrix[n-i-1][n-j-1];
matrix[n-i-1][n-j-1] = matrix[i][j];
matrix[i][j] = temp;
temp = matrix[n-j-1][i];
matrix[n-j-1][i] = matrix[i][j];
matrix[i][j] = temp;
}
}
}

两次反转
第二种方式就反转和旋转数组一题一样我们直接观察输入图与目标图通过怎样的变换可以得到

旋转90度的关系肯定是没有直接方式的,这里我们肯定是用到的设值。通过图形变换反转类似的方式就两数交换完成就可能进行几组反转比起上面直接的一步的到位的设值方式在单元操作上两数交换比起四数看起来简一点。但有进行多组遍历的可能。它是转90而不是180如果是180就上下反转然后左右反转。所以这里只能对角反转加左右反转先后无所谓


无论怎么转都可以实现总之是通过两个数的交换就很简单,然后要进行两次。下面代码按照第一条进行,第一个变换只需要遍历左上一半即可每个完成和下面的交换即可因此列的起点是递增的j = i,第二个变换循环时列只需要左边一半就换行所以j = length/2
public void rotate(int[][] matrix) {
int n = matrix.length;
for (int i = 0; i < n; i++) {
for (int j = i; j < n; j++) {
int tmp = matrix[j][i];
matrix[j][i] = matrix[i][j];
matrix[i][j] = tmp;
}
}
for (int i = 0; i < n; i++) {
for (int j = 0; j < n / 2; j++) {
int tmp = matrix[i][j];
matrix[i][j] = matrix[i][n - j - 1];
matrix[i][n - j - 1] = tmp;
}
}
}

总结
总体来说都是一个原地算法,时间也都是O(n^2),像这一题与之前一题都是属于数组内原地的变化位置即多值交换以及换成多组反转即两值交换的组合。主要也是体会在数组这样的数据结构当中我们可以有的算法思想:遍历、逆序、原地交换、快慢指针。万变不离其中,那么从更新《LeetCode日常》系列开始到这篇为止LeetCode初级算法合集中的数组篇章完结即将开启下一篇章字符串相关算法
LeetCode初级算法之数组:48 旋转图像的更多相关文章
- LeetCode初级算法之数组:66 加一
加一 题目地址:https://leetcode-cn.com/problems/plus-one/ 给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一.最高位数字存放在数组的首位, 数 ...
- 算法练习LeetCode初级算法之数组
删除数组中的重复项 官方解答: 旋转数组 存在重复元素 只出现一次的数 官方解答: 同一个字符进行两次异或运算就会回到原来的值 两个数组的交集 II import java.util.Arr ...
- LeetCode初级算法之数组:36 有效数独
有效数独 题目地址:https://leetcode-cn.com/problems/valid-sudoku/ 判断一个 9x9 的数独是否有效.只需要根据以下规则,验证已经填入的数字是否有效即可. ...
- LeetCode初级算法之数组:283 移动零
移动零 题目地址:https://leetcode-cn.com/problems/move-zeroes/ 给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺 ...
- LeetCode初级算法之数组:350 两个数组的交集 II
两个数组的交集 II 题目地址:https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/ 给定两个数组,编写一个函数来计算它们的交 ...
- LeetCode初级算法之数组:136 只出现一次的元素
只出现一次的元素 题目地址:https://leetcode-cn.com/problems/single-number/ 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找 ...
- LeetCode初级算法之数组:189 旋转数组
旋转数组 题目地址:https://leetcode-cn.com/problems/rotate-array/ 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数. 示例 1: 输 ...
- LeetCode初级算法之数组:122 买卖股票的最佳时机 II
买卖股票的最佳时机 II 题目地址:https://leetcode-cn.com/problems/best-time-to-buy-and-sell-stock-ii/ 给定一个数组,它的第 i ...
- LeetCode初级算法之数组:1 两数之和
两数之和 题目地址:https://leetcode-cn.com/problems/two-sum/ 给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个整 ...
随机推荐
- 虚拟机vbox给vdi增加容量到16G后的一系列操作
虚拟机vbox给vdi增加容量到16G后的一系列操作windows 下:cmdVbox/bin下1.#VBoxManage modifyhd "cloned.vdi" --resi ...
- BeatifulSoup在测试工作中的应用
近期要做一个项目,重复性劳动比较多,小伙伴建议我用Jsoup,但是由于项目紧急,我直接选择了BeautifulSoup,关键原因是我Java语言不如Python掌握的熟练啊!所以,查了一圈它的中文文档 ...
- linux中KVM桥接网卡br0
在centos虚拟化当中需要增加一个桥接网卡,然后将虚拟化当中的机器的网卡桥接到桥接网卡,下面将描述设置方法: 查看现有网卡 [root@zb ~]# vim /etc/sysconfig/netwo ...
- HttpClient4.5X使用-集成微服务
HttpClient4.5X使用-集成微服务 1.什么是HttpClient HTTP 协议可能是现在 Internet 上使用得最多.最重要的协议了,越来越多的 Java 应用程序需要直 ...
- 《Spring Boot 实战纪实》之需求管理
目录 前言 (思维篇)人人都是产品经理 1.需求文档 1.1 需求管理 1.2 如何攥写需求文档 1.3 需求关键点文档 2 原型设计 2.1 缺失的逻辑 2.2 让想法跃然纸上 3 开发设计文档 3 ...
- Windows上Jenkins插件下载慢解决方法
替换文件内容 Jenkins/updates/default.json 替换 updates.jenkins-ci.org/download 为 mirrors.tuna.tsinghua.edu.c ...
- python-网络安全编程第六天(threading多线程模块&Queue模块&subprocess模块)
前言 昨天晚上9点多就睡了 2点起来没睡意... 那就学习吧emmmm ,拿起闲置几天的python课程学习.学习到现在5.58了 总结下 继续开始学习新的内容 多多线程? 线程(英语:thread) ...
- 运维自动化之1 - ansible 批量主机管理
2000 - 2016 年,维护的小型机.linux刚开始的2台增加到上千台,手工检查.日常版本升级需要管理太多设备,必须通过运维自动化实现 特别是版本升级,需要到同类机器部署代码.起停设备,必须在一 ...
- 深度分析:Java 静态方法/变量,非静态方法/变量的区别,今天一并帮你解决!
静态/非静态 方法/变量的写法 大家应该都明白静态方法/字段比普通方法/字段的写法要多一个static关键字,简单写下他们的写法吧,了解的可以直接略过 class Test{ // 静态变量 publ ...
- Linux nginx安装篇
目录 前言 版本 安装 1.下载 2.安装依赖 3.编译安装 4.启动 5.服务启动 参考资料 前言 最近新申请了一台服务器,需要安装下nginx服务,安装nginx不是第一次,之前反反复复也装过,由 ...