螺旋矩阵,两步进阶,从暴力到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列)出发,初始时向右移动:如果前方是未曾经过的格子,则继续前进,否则右转:重复上述操作直至经过矩阵中所有格子.根据经过顺序 ...
 
随机推荐
- vue中点击空白处隐藏弹框(用指令优雅地实现)
			
在写vue的项目的时候,弹框经常性出现,并要求点击弹框外面,关闭弹框,那么如何实现呢?且听我一一...不了,能实现效果就好 <template> <div> <div c ...
 - Linux定时清理30天前的Tomcat日志脚本
			
一.在tomcat的log路径下新建.sh脚本文件clean.sh,内容如下:#!/bin/bashlogs_path="/mnt/tomcat/apache-tomcat-8.5.23/l ...
 - Microsoft JET Database Engine (0x80004005)未指定的错误解决
			
Microsoft JET Database Engine (0x80004005)未指定的错误,这个错误只有在使用Access数据库时才能出现 出现以上问题,可以使用以下步骤进行解决问题: 1.系统 ...
 - redis数据类型--个人常规用法
			
一.String 1.可以容纳最高512M的value. 2.经常用于通过expire来实现自动过期的一些值,直接通过setex 来. 3.通过incrby的方式,来实现value值得增长. 4.执行 ...
 - 织梦通过 phpmyadmin 导出的数据,再次导入的时候报错
			
错误提示: #1291 – Column 'nature' has duplicated value '婆婆妈妈' in SET SQL 查询: -- -- 导出表中的数据 `dede_member_ ...
 - 打印机设置dns
			
1.登录打印机网页:打印机的ip 2.点击网络--网络标识--设置DNS
 - java字符串与二进制的相互转化
			
public class StrBinaryTurn { // 将Unicode字符串转换成bool型数组 public boolean[] StrToBool(String input) { boo ...
 - asp.net5开发中DNX SDK版本的影响
			
某次asp.net5开发中遇到了一个很奇怪的问题,引用部分的nuget包没有显示任何错误,如下图: 但是编译时出现了几百个错误: 错误基本都是形如“CS0246 The type or namespa ...
 - WCF 内置绑定在不同的传输安全模式下的信道层
			
basicHttpBinding Transport安全模式信道层 Message安全模式信道层 TransportWithMessageCredential安全模式信道层 TransportCred ...
 - 使用pycharm 运行python的django项目时报错“Quit the server with CTRL-BREAK.”
			
Quit the server with CTRL-BREAK.Error: [Errno 10013] 1昨晚测试时还好好的,怎么突然出现这个错误,于是GOOLE,找到个帖子说可能是端口占用了,用工 ...