螺旋矩阵,两步进阶,从暴力到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列)出发,初始时向右移动:如果前方是未曾经过的格子,则继续前进,否则右转:重复上述操作直至经过矩阵中所有格子.根据经过顺序 ...
随机推荐
- c# Equals对比忽略大小写
String.Equals(str1,str2,StringComparison.CurrentCultureIgnoreCase); StringComparison.CurrentCultureI ...
- linux别名防删除
最近有不相信rm -rf 了,虽然恢复了但是很难受啊 加个别名吧, 1.查看系统别名配置 alias 2.配置别名(临时生效) alias rm='echo do not use rm command ...
- Maven_setting.xml
<?xml version="1.0" encoding="UTF-8"?> <!-- Licensed to the Apache Soft ...
- TOMCAT热部署 catalina.home catalina.base
catalina.home 一台机器通常只有一个, 指向Tomcat的安装目录 catalina.base 一台机器可以启动多个Context, 每个Context对应一个catalina.base ...
- Hystrix使用小结
通过服务熔断实现服务降级 @HystrixCommand(fallbackMethod = "reliable", commandProperties = { @HystrixPr ...
- 去除 Git 安装后的右键菜单
64位 windows 8.1 安装 Git 后,右键菜单多了3个选项(Git Init Here,Git Gui, Git Bash),但是用不着,需要删掉.方法如下: 1.在 CMD 中进入 Gi ...
- Options Menu的android3.0以上和以下版本显示刷新原理,刷新适配
一 显示区别: 2.3.x及以下版本,需要按菜单键显示菜单,当菜单打开时,第一个可见的部分是图标菜单,最多可容纳6个菜单项.如果你的菜单包括Android的地方超过6项,第六项,其余将被归到”More ...
- Ubuntu同屏多终端
sudo apt-get install terminator
- Unity Destroy和DestroyImmediate
Destroy(Object obj, float t = 0.0F); 删除一个游戏对象,组件或者资源. 物体obj现在被销毁或在指定了t时间过后销毁.如果obj是组件,它将从GameObject销 ...
- jquery的.get方法说解
·Customer类 public class Customer { public int Unid { get; set; } public string CustomerName { get; s ...