螺旋矩阵,两步进阶,从暴力到o(1)
题目描述
一个 n 行 n 列的螺旋矩阵可由如下方法生成:
| 1 | 2 | 3 | 4 |
| 12 | 13 | 14 | 5 |
| 11 | 16 | 15 | 6 |
| 10 | 9 | 8 | 7 |
现给出矩阵大小 n 以及 i 和 j ,请你求出该矩阵中第 i 行第 j 列的数是多少。
输入描述:
输入共一行,包含三个整数 n,i,j ,每两个整数之间用一个空格隔开,分别表示矩阵大小、待求的数所在的行号和列号。
输出描述:
输出一个整数,表示相应矩阵中第 i 行第 j 列的数。
输入
4 2 3
输出
14
备注:
对于 50% 的数据, 1 ≤ n ≤ 100 ;
对于 100% 的数据, 1 ≤ n ≤ 30,000,1 ≤ i ≤ n,1 ≤ j ≤ n
链接:https://ac.nowcoder.com/acm/problem/16502
来源:牛客网
1.暴力模拟法,o(n*2),只能通过50%的数据。
#include<iostream>
using namespace std; /***********************
1<=n<=30000无法用数组存储
***********************/ int n,i,j;
int top_bound,bottom_bound,left_bound,right_bound;
int count=1;
int direction=0; int main(){
cin>>n>>i>>j;
int k=1,m=1;
top_bound=1;
bottom_bound=n+1;
left_bound=0;
right_bound=n+1;
while(count<=n*n){
switch(direction){
case 0:
//cout<<"from "<<k<<" "<<m<<" steps to "<<"direction "<<direction<<endl;
if(m==right_bound){
//cout<<"reach right_bound "<<right_bound<<" change direction from "<<direction<<" ";
direction=(direction+1)%4;
right_bound--;
m--;
k++;
//cout<<"to "<<direction<<endl;
continue;
}
if(k==i&&m==j){
cout<<count<<endl;
return 0;
}
m++;
count++;
break; case 1:
//cout<<"from "<<k<<" "<<m<<" steps to "<<"direction "<<direction<<endl;
if(k==bottom_bound){
//cout<<"reach bottom_bound "<<bottom_bound<<" change direction from "<<direction<<" ";
direction=(direction+1)%4;
bottom_bound--;
k--;
m--;
//cout<<"to "<<direction<<endl;
continue;
}
if(k==i&&m==j){
cout<<count<<endl;
return 0;
}
k++;
count++;
break; case 2:
//cout<<"from "<<k<<" "<<m<<" steps to "<<"direction "<<direction<<endl;
if(m==left_bound){
//cout<<"reach left_bound "<<left_bound<<" change direction from "<<direction<<" ";
direction=(direction+1)%4;
left_bound++;
m++;
k--;
//cout<<"to "<<direction<<endl;
continue;
}
if(k==i&&m==j){
cout<<count<<endl;
return 0;
}
m--;
count++;
break; case 3:
//cout<<"from "<<k<<" "<<m<<" steps to "<<"direction "<<direction<<endl;
if(k==top_bound){
//cout<<"reach top_bound "<<top_bound<<" change direction from "<<direction<<" ";
direction=(direction+1)%4;
top_bound++;
k++;
m++;
//cout<<"to "<<direction<<endl;
continue;
}
if(k==i&&m==j){
cout<<count<<endl;
return 0;
}
k--;
count++;
break;
} }
return 0;
}
2. 外圈优化法,o(n),可通过100%的数据。
| 1 | 2 | 3 | 4 |
| 12 | 13 | 14 | 5 |
| 11 | 16 | 15 | 6 |
| 10 | 9 | 8 | 7 |
#include<iostream>
using namespace std; /***************************
1. 1 ≤ n ≤ 30000,因此无法将整个矩阵存储下来,只能输出目标结果
2. 模拟整个过程仍会超时,可将情况分为3类
(1)n==1, 输出1
(2)i,j==1|n,即该数在旋转矩阵的外围计算旋转矩阵边界上的值
(3)中间的数,根据首先计算外围数的个数,在外圈的数的基础上进行模拟
****************************/
int n,i,j;
int anchor=1,dist,anchor_pos=1; int min(int x,int y,int z,int q){
return min(min(min(x,y),z),q);
}
int min(int x,int y){
return x>y?y:x;
} int main(){
cin>>n>>i>>j;
if(n==1){
cout<<1<<endl;
}else{
int left,right,top,bottom;
left=j-1;
right=n-j;
top=i-1;
bottom=n-i;
//cout<<left<<" "<<right<<" "<<top<<" "<<bottom<<endl;
dist=min(left,right,top,bottom);
anchor_pos=dist+1;
anchor=n*n-(n-2*dist)*(n-2*dist)+1;
//cout<<dist<<" "<<anchor<<endl; //接下来进行模拟,可在4*inner_n-4次计算中找到目标(i,j)
int k=anchor_pos,m=anchor_pos; //当前位置
int direction=0; //当前方向
int top_bound=dist+1;
int bottom_bound=n-dist+1;
int left_bound=dist;
int right_bound=n-dist+1; int count=anchor; while(count<=n*n){
switch(direction){
case 0:
//cout<<"from "<<k<<" "<<m<<" steps to "<<"direction "<<direction<<endl;
if(m==right_bound){
//cout<<"reach right_bound "<<right_bound<<" change direction from "<<direction<<" ";
direction=(direction+1)%4;
right_bound--;
m--;
k++;
//cout<<"to "<<direction<<endl;
continue;
}
if(k==i&&m==j){
cout<<count<<endl;
return 0;
}
m++;
count++;
break; case 1:
//cout<<"from "<<k<<" "<<m<<" steps to "<<"direction "<<direction<<endl;
if(k==bottom_bound){
//cout<<"reach bottom_bound "<<bottom_bound<<" change direction from "<<direction<<" ";
direction=(direction+1)%4;
bottom_bound--;
k--;
m--;
//cout<<"to "<<direction<<endl;
continue;
}
if(k==i&&m==j){
cout<<count<<endl;
return 0;
}
k++;
count++;
break; case 2:
//cout<<"from "<<k<<" "<<m<<" steps to "<<"direction "<<direction<<endl;
if(m==left_bound){
//cout<<"reach left_bound "<<left_bound<<" change direction from "<<direction<<" ";
direction=(direction+1)%4;
left_bound++;
m++;
k--;
//cout<<"to "<<direction<<endl;
continue;
}
if(k==i&&m==j){
cout<<count<<endl;
return 0;
}
m--;
count++;
break; case 3:
//cout<<"from "<<k<<" "<<m<<" steps to "<<"direction "<<direction<<endl;
if(k==top_bound){
//cout<<"reach top_bound "<<top_bound<<" change direction from "<<direction<<" ";
direction=(direction+1)%4;
top_bound++;
k++;
m++;
//cout<<"to "<<direction<<endl;
continue;
}
if(k==i&&m==j){
cout<<count<<endl;
return 0;
}
k--;
count++;
break;
} }
}
return 0;
}
3. 外圈+内圈优化,0(1)之路
| 1 | 2 | 3 | 4 |
| 12 | 12+1 | 12+2 | 5 |
| 11 | 12+4 | 12+3 | 6 |
| 10 | 9 | 8 | 7 |
| 1 | 2 |
| 4 | 3 |
#include<iostream>
using namespace std; int n,i,j;
int anchor,dist;
int left,right,top,bottom; int min(int x,int y,int z,int q){
return min(min(min(x,y),z),q);
} int min(int x,int y){
return x>y?y:x;
} int f(){
int inner_n =n-2*dist;
int inner_i =i-dist;
int inner_j =j-dist;
//cout<<inner_n<<" "<<inner_i<<" "<<inner_j<<" "<<endl;
if(i-1==dist||n-j==dist){
return inner_i+inner_j-1;
}
return 4*inner_n-inner_i-inner_j-1;
} int main(){
cin>>n>>i>>j;
if(n==1){
cout<<1<<endl;
}else{
int left,right,top,bottom;
left=j-1;
right=n-j;
top=i-1;
bottom=n-i;
dist=min(left,right,top,bottom);
anchor=n*n-(n-2*dist)*(n-2*dist);
//cout<<dist<<" "<<anchor<<endl;
int ans = anchor+f();
cout<<ans<<endl;
}
return 0;
}
螺旋矩阵,两步进阶,从暴力到o(1)的更多相关文章
- 模拟【p2239】 螺旋矩阵
顾z 你没有发现两个字里的blog都不一样嘛 qwq 题目描述--->p2239 螺旋矩阵 看到题,很明显,如果直接模拟的话,复杂度为\(O(n^2)\)过不去.(这个复杂度应该不正确,我不会分 ...
- 第29题:LeetCode54:Spiral Matrix螺旋矩阵
给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中的所有元素. 示例 1: 输入: [ [ 1, 2, 3 ], [ 4, 5, 6 ], [ 7, 8, 9 ...
- PAT 1050. 螺旋矩阵(25)
本题要求将给定的N个正整数按非递增的顺序,填入"螺旋矩阵".所谓"螺旋矩阵",是指从左上角第1个格子开始,按顺时针螺旋方向填充.要求矩阵的规模为m行n列,满足条 ...
- NOIP2014-普及组复赛-第三题-螺旋矩阵
题目描述 Description 一个n行n列的螺旋矩阵可由如下方法生成: 从矩阵的左上角(第1行第1列)出发,初始时向右移动:如果前方是未曾经过的格子,则继续前进,否则右转:重复上述操作直至经过矩阵 ...
- Code Kata:螺旋矩阵 javascript实现
1 2 3 4 5 16 17 18 19 6 15 24 25 20 7 14 23 22 21 8 13 12 11 10 9 如图所示,就是一个5*5的螺旋矩阵 我的思路如下: 第一步:拆分 ...
- HrbustOJ 1564 螺旋矩阵
Description 对于给定的一个数n,要你打印n*n的螺旋矩阵. 比如n=3时,输出: 1 2 3 8 9 4 7 6 5 Input 多组测试数据,每个测试数据包含一个整数n(1<=n& ...
- 使用 JS 输出螺旋矩阵
关于螺旋矩阵 这是我曾经遇到过的面试题,在 LeetCode 上找到了题目的原型,难度中等.题目描述如下: 给定一个包含 m x n 个元素的矩阵(m 行, n 列),请按照顺时针螺旋顺序,返回矩阵中 ...
- PHP实现螺旋矩阵(螺旋数组)
今天碰到一个比较有意思的问题, 就是把A到Y这25个字母以下面的形式输出出来 A B C D E P Q R S F O X Y T G N W V U H M L K J I 问题很有意思,就是转圈 ...
- 【模拟】[NOIP2014]螺旋矩阵[c++]
题目描述 一个n行n列的螺旋矩阵可由如下方法生成: 从矩阵的左上角(第1行第1列)出发,初始时向右移动:如果前方是未曾经过的格子,则继续前进,否则右转:重复上述操作直至经过矩阵中所有格子.根据经过顺序 ...
随机推荐
- 使用jmeter往指定文件中插入一定数量的数据(转)
有一个需求,新建一批账号,把获取的账号相关信息存入文本文件,当文本文件保存的数据达到一定的数量,就自动停止新建账号. 分析下需求: 1.把账号信息保存到文件,需要使用bean shell脚本(bean ...
- Vue里的nextTick方法
官方解释: 在下次 DOM 更新循环结束之后执行延迟回调.在修改数据之后立即使用这个方法,获取更新后的 DOM. 自己总结: `Vue.nextTick(callback)`,当数据发生变化,更新后执 ...
- python_sting字符串的方法及注释
string类型是python内置的类型,无需安装 方法/属性 说明 capitalize() 把字符串的第一个字符改为大写 casefold() 把整个字符串的所有字符改为小写 ...
- 关于String的split方法
在做剑指offer的时候,有一道替换空格的题,立刻就想到用这个split方法来做,但发现,这个方法会丢掉字符串最后的空格??? 百度后,知道原因,这里直接复制粘贴了: 在使用java中的split按照 ...
- docker~aspnetcore2.0镜像安装软件的加速器
一般对于安装软件加速时,我们大多数会选择阿里云,而对于aspnetcore2.0这个进项来说,由于使用的是Debian操作系统,所有我们要找到它对应的mirror列表,下面是我整理的一个sources ...
- 用 Java 实现断点续传参考 (HTTP)
断点续传的原理 其实断点续传的原理很简单,就是在 Http 的请求上和一般的下载有所不同而已. 打个比方,浏览器请求服务器上的一个文时,所发出的请求如下: 假设服务器域名为 ...
- [Environment Build] 工作中遇到的关于Git的问题
修改已经提交的commit中的author, commit git commit --amend --author 'Your Name <Your Email>' git commit ...
- 学习笔记:MDN的服务器端网站编程
互联网是如何工作的 互联网(Internet)和网络(web) 互联网是基础设施,网络是建立在这种基础设施之上的服务. 网页,网站,网络服务器和搜索引擎的区别是什么? 网页(webpage) 一份能够 ...
- 解决Django Rest Framework中的跨域问题
方案一: 全局配置 自定义中间件 # my_md.py class MiddlewareMixin(object): def __init__(self, get_response=None): se ...
- Windows 10 取消桌面右键“图像属性”、“图像选项”
Windows 10 取消桌面右键"图像属性"."图像选项" 桌面右键 说明:在windows 10中,桌面右键出现"图像属性"." ...