手把手教你解决二维数组旋转问题

2023-11-07

一、背景

最近做算法题发现有些题目都需要将一个数组顺时针或逆时针旋转,之前发的题解中也涉及到过这类题,但没有细讲,在这里讲一下思路,手把手带你找到对应关系。

本文代码示例均使用java,但重要的是思路!思路!思路!与语言无关。

如果大家不明白我说的是什么,可以先移步洛谷P1205,P4924(题目会附在本文最下方)

二、直接上手!

数组旋转基本上可以分为这几类:

1.数组整体做顺/逆时针旋转

        (1)顺时针

①找对应关系 

用一个3阶矩阵举例,大家不难写出如下对应关系:(设原始矩阵为A,旋转后的矩阵为B)

B(0,0) = A(2,0) B(0,1) = A(1,0) B(0,2) = A(0,0)
B(1,0) = A(2,1) B(1,1) = A(1,1) B(1,2) = A(0,1)
B(2,0) = A(2,2) B(2,1) = A(1,2) B(2,2) = A(0,2)
②寻找内外层 

 写出对应关系后,我们进一步去寻找内外层

以目标矩阵为基准,在横向中,没有坐标改变的就是外层,一直在改变的就是内层

 为了方便大家寻找内外层关系,将对应关系转化为了竖向的

图中红色箭头表示的就是内层——即在一个周期内频繁变化的

图中蓝色箭头表示的就是外层——即在一个周期内不改变,每一个周期仅改变一次

图中箭头上方的+/-表示的是这一个周期内的变化规律是递增/递减

③设立变量

为了方便后续写代码,我们以目标矩阵的变化规律为基准设立变量

将外层变量设为i,内层变量设为j,不难看出,这里的i,j都是递增关系

那怎么用具有递增关系的i,j去表示递减关系呢

在整体旋转这里,可以直接用阶数n减,就可以得到递减关系

④代码

根据上面的推导,我们不难得出下面的代码

public class Main {
    public static void main(String[] args) {
        int[][] A = {{1,2,3},{4,5,6},{7,8,9}};
        int n = 3;
        int[][] B = new int[n][n];
        for(int i = 0;i < n;i++){
            for(int j = 0 ; j < n; j++){
                B[i][j] = A[n-1-j][i]; // n是阶数,从1开始计数,但数组索引是从0开始,所以要减1
            }
        }
    }
}

代码中的数组A,n在做题时应该会直接给出,这里只是简单举个例子。


(2)逆时针

逆时针同理,这里再带大家走一次

①找对应关系
B(0,0) = A(0,2) B(0,1) = A(1,2) B(0,2) = A(2,2)
B(1,0) = A(0,1) B(1,1) = A(1,1) B(1,2) = A(2,1)
B(2,0) = A(0,0) B(2,1) = A(1,0) B(2,2) = A(2,0)
 ②寻找内外层

 ③设立变量

老规矩,外层i 内层j,递增+i/j,递减-i/j

④代码
public class Main {
    public static void main(String[] args) {
        int[][] A = {{1,2,3},{4,5,6},{7,8,9}};
        int n = 3;
        int[][] B = new int[n][n];
        for(int i = 0;i < n;i++){
            for(int j = 0 ; j < n; j++){
                B[i][j] = A[j][n-1-i]; // n是阶数,从1开始计数,但数组索引是从0开始,所以要减1
            }
        }
    }
}

2.数组局部做顺/逆时针旋转

有时候我们不止需要对整个数组进行顺/逆时针旋转,我们还需要对这个数组中的一小部分做变化

如 将二维数组中第 x 第 y 列为中心的 2r+1 阶矩阵按照某种时针方向旋转

根据题意可以转化为,以(x-1,y-1)为中心,向外扩展±r的区域,对这个区域做旋转

以下的例子均以 n = 4,x = 3,y = 3,r = 1为例

(1)顺时针

 还是按照我们的流程一步步来

 ①找对应关系(局部)

局部改变我们没有必要去找整体的对应关系,只需要找改变区域的对应关系即可:

B(1,1) = A(3,1) B(1,2) = A(2,1) B(1,3) = A(1,1)
B(2,1) = A(3,2) B(2,2) = A(2,2) B(2,3) = A(1,2)
B(3,1) = A(3,3) B(3,2) = A(2,3) B(3,3) = A(1,3)
②寻找内外层

 

③设立变量

老规矩外层i,内层j,但是这次的范围就不是从0 -> n了,而是-r -> +r

不难看出,目标数组起始点B(1,1) ---> B(x-1-r,y-1-r)

目标数组最终点B(3,3) ---> B(x-1+r,y-1+r)

可得出基准点是(x-1,y-1);递增就是 +i/j 递减就是 -i/j 

④代码
public class Main {
    public static void main(String[] args) {
        int n = 4;
        int x = 3;
        int y = 3;
        int r = 1;
        int[][] A = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
        //---------以上为题目给出条件-------------
        int[][] B = new int[n][n];
        for (int i = 0; i < n; i++)
            System.arraycopy(A[i], 0, B[i], 0, A.length);
        //将给出的数组复制一份,方便后续操作
        //下面进行旋转操作
        for (int i = -r; i <= r; i++) {
            for (int j = -r; j <= r; j++) {
                B[x-1+i][y-1+j] = A[x-1-j][y-1+i];
            }
        }
    }
}

System.arraycopy(Object src, srcindex, Object dest,destindex,length)

Object src:源数组
srcindx:源数组起始下标
Object dest:目的数组
destindex:目的数组起始下标

length:复制的长度

 (2)逆时针

同理,但还是在带大家走一遍

 ①找对应关系:
B(1,1) = A(1,3) B(1,2) = A(2,3) B(1,3) = A(3,3)
B(2,1) = A(1,2) B(2,2) = A(2,2) B(2,3) = A(3,2)
B(3,1) = A(1,1) B(3,2) = A(2,1) B(3,3) = A(3,1)
②寻找内外层

 ③设立变量

老规矩 外层i,内层j,从-r到+r

④代码
public class Main {
    public static void main(String[] args) {
        int n = 4;
        int x = 3;
        int y = 3;
        int r = 1;
        int[][] A = {{1, 2, 3, 4}, {5, 6, 7, 8}, {9, 10, 11, 12}, {13, 14, 15, 16}};
        //---------以上为题目给出条件-------------
        int[][] B = new int[n][n];
        for (int i = 0; i < n; i++)
            System.arraycopy(A[i], 0, B[i], 0, A.length);
        //将给出的数组复制一份,方便后续操作
        //下面进行旋转操作
        for (int i = -r; i <= r; i++) {
            for (int j = -r; j <= r; j++) {
                B[x-1+i][y-1+j] = A[x-1+j][y-1-i];
            }
        }
    }
}

以上就是这节课全部内容了,功力不深,如有错误,还请指出

还有疑问可以评论区提出

三、课后作业

1.自主摸索旋转180度如何操作

2.洛谷P1205,P4924两题

就这样,下课!!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

手把手教你解决二维数组旋转问题 的相关文章

随机推荐

  • 总结】python sklearn模型中random_state参数的意义

    这是在决策树CART模型时 遇到的 random state 是为了固定随机状态的 主要用在随机数据集 数据集的随机划分 设置决策树模型参数 设置随机森林模型参数 random state 取值大小可以是任意一个整数 在调参缓解 只要保证其
  • 基于Docker的JMeter分布式压测实战讲解

    一个JMeter实例可能无法产生足够的负载来对你的应用程序进行压力测试 如本网站所示 一个JMeter实例将能够控制许多其他的远程JMeter实例 并对你的应用程序产生更大的负载 JMeter使用Java RMI 远程方法调用 来与分布式网
  • 即将离开CSDN,转其他平台

    CSDN的几大作死操作 1 同质化太特么严重了 博客抄来抄去的 内容审核形同虚设 经常搜一个问题 从第一条到最后一条都是一模一样的内容 2 资源付费 资源付费本身是没有任何问题的 但是CSDN里面有几个有用的资源 很多大家花了钱一下载 发现
  • windows凭据密码怎么查看_管理Windows访问凭证,快速访问局域网上的共享资源

    内部网访问其他电脑的共享资源 基本上需要输入访问对方电脑资源允许的账号和密码 在第一次的访问中选择保存凭据后 以后访问就不要输入相应的账号和密码了 但也会出现因修改相关的访问密码或者取消了访问账号的改变 这样就会出现凭据失效的情况 下面介绍
  • 类似-Xms、-Xmn这些参数的含义:

    类似 Xms Xmn这些参数的含义 答 堆内存分配 JVM初始分配的内存由 Xms指定 默认是物理内存的1 64 JVM最大分配的内存由 Xmx指定 默认是物理内存的1 4 默认空余堆内存小于40 时 JVM就会增大堆直到 Xmx的最大限制
  • Python通过ARIMA模型进行时间序列分析预测

    ARIMA模型预测 时间序列分析预测就是在已有的和时间有关的数据序列的基础上构建其数据模型并预测其未来的数据 例如航空公司的一年内每日乘客数量 某个地区的人流量 这些数据往往具有周期性的规律 如下图所示 有的数据呈现出简单的周期性循环 有的
  • Linux嵌入式学习---c语言之循环结构

    Linux嵌入式学习 c语言之循环结构 一 while语句循环 1 1一般形式 1 2累加求和 二 do while语句循环 2 1do while语句一般形式 2 2do while语句特点 三 for语句循环 3 1for语句的一般形式
  • vue-resource请求数据的使用方法

    vue resource vue js关于客户端请求数据的官方插件 使用vue resource请求数据的步骤 1 安装vue resource插件 记得添加 save 若安装淘宝镜像用cnpm npm install vue resour
  • [蓝桥杯2023初赛] 整数删除

    给定一个长度为 N 的整数数列 A1 A2 AN 你要重复以下操作 K 次 每次选择数列中最小的整数 如果最小值不止一个 选择最靠前的 将其删除 并把与它相邻的整数加上被删除的数值 输出 K 次操作后的序列 输入格式 第一行包含两个整数 N
  • vscode:visual studio code 调试php

    简介 php是动态语言没有调试器的话排错起来很是麻烦 vscode可以说是程序员的福音 启动速度快 插件越来越多 跨平台 现在说一下vscode上调试php文件 所需文件 xampp 集成服务器 vscode Xdebug php debu
  • Rightware的Kanzi界面很快你的全液晶汽车仪表盘

    锋影 e mail 174176320 qq com 这是一个屏幕在行动的Kanzi UI编辑器 这是说 汽车仪表板没有显著在过去的几十年里发展公平 不知怎么的 我觉得喜欢的东西是会改变的 但什么也没做 至少在一个大的方式 当日产GTR天际
  • 面试必问的Spring IoC与Spring AOP面试题,你能get到几问?

    Spring IoC Q1 IoC 是什么 Q2 IoC 容器初始化过程 Q3 依赖注入的实现方法有哪些 Q4 依赖注入的相关注解 Q5 依赖注入的过程 Q6 Bean 的生命周期 Q7 Bean 的作用范围 Q8 如何通过 XML 方式创
  • (含源码)「自然语言处理(NLP)」RoBERTa&&XLNet&&语言模型&&问答系统训练

    来源 AINLPer 微信公众号 每日更新 编辑 ShuYini 校稿 ShuYini 时间 2020 07 27 引言 本次内容主要包括 稳健优化Bert模型 RoBERTa 自回归预训练模型 XLNet 无监督多任务学习语言模型 生成预
  • 【BT 协议】HFP 协议

    原文链接 https blog csdn net shichaog article details 52123439 HFP Hands free Profile 让蓝牙设备可以控制电话 如接听 挂断 拒接 语音拨号等 拒接 语音拨号要视蓝
  • C++:智能指针及其实现原理

    更多C 知识点 C 目录索引 1 RAII思想 定义一个类来封装资源的分配与释放 构造函数中完成资源的分配及初始化 析构函数中完成资源的清理 可以保证资源的正确初始化和释放 如果对象是用声明的方式在栈上创建局部对象 那么RAII机制就会正常
  • 从 MySQL 到 OBOracle:如何处理自增列?

    业务需要将数据库转换为 OceanBase 数据库 但源端涉及到 Oracle 及 MySQL 两种不同数据库 需要合并为 OceanBase 中单一的 Oracle 模式 其中源端 MySQL 数据库需要改造为 OB Oracle 并做异
  • 天梯题集——复数四则运算(fabs)

    复数四则运算 include
  • K8S kube-proxy- iptable模式实现原理分析

    每台机器上都运行一个kube proxy服务 它监听api server 和endpoint变化情况 维护service和pod之间的一对多的关系 通过iptable或者ipvs为服务提供负载均衡的能力 通常kube proxy作为deem
  • mysql auto reconnect_Python mysql (using pymysql) auto reconnect

    I m not sure if this is possible but I m looking for a way to reconnect to mysql database when the connection is lost Al
  • 手把手教你解决二维数组旋转问题

    一 背景 最近做算法题发现有些题目都需要将一个数组顺时针或逆时针旋转 之前发的题解中也涉及到过这类题 但没有细讲 在这里讲一下思路 手把手带你找到对应关系 本文代码示例均使用java 但重要的是思路 思路 思路 与语言无关 如果大家不明白我