目录
1.最大公约数和最小公倍数
- 分析:辗转相除法
#include <iostream>
using namespace std;
//最大公约数
int gcd(int num1,int num2)
{
int t=num1%num2;
while(t!=0)
{
num1=num2;
num2=t;
t=num1%num2;
}
return num2;
}
//最小公倍数
int lcm(int num1,int num2)
{
return num1*num2/gcd(num1,num2);
}
int main()
{
int num1,num2;
cin>>num1>>num2;
int num_gcd=gcd(num1,num2);
cout<<"最大公约数: "<<num_gcd<<endl;
int num_lcm=lcm(num1,num2);
cout<<"最小公倍数: "<<num_lcm<<endl;
return 0;
}
- 输出结果:
2.判断素数
- 分析:
素数的定义:一个数如果只能被1和本身整除,那么这个数就是素数。判断素数的时候,循环的区间是[2,num).
- 时间复杂度:O(n^2)
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
bool isPrime(int num)
{
for(int i=2;i<num;i++)
{
if(num%i==0)
return false;
}
return true;
}
int main ()
{
int n;
cin>>n;
for(int j=2;j<n;j++)
{
if(isPrime(j))
{
cout<<j;
cout<<" ";
}
}
return 0;
}
- 改进版:
遍历区间从[2,num)到[2,sqrt(num)]
for(int i=2;i<num;i++)
变为:
for(int i=2;i*i<=num;i++)
- 输出结果:
3.计算字符串的ASCII码
- 题目描述:
编写一个程序,在终端输入一个字符,输出它的ASCII码。
- 分析:
一个字符在内存中存放的形式是以它的ASCII码形式存放的,大小为8位(bit),一个字节,例如:空格键的ASCII码为32,内存中32对应的8位二进制数100000.因此,只需变换输出的类型。
#include<iostream>
#include<stdlib.h>
using namespace std;
int main()
{
char c;
printf("please input a character\n");
scanf("%c",&c);
printf("ASCII: %d",c);
return 0;
}
4. 字符类型统计器
- 题目描述:
请输入一个C程序,在终端用键盘输入字符串,以Ctrl+Z组合键表示输入完毕,统计输入的字符串中空格符、制表符、换行符的个数,并显示统计的结果。
#include<iostream>
using namespace std;
int main()
{
int space=0,table=0,enter=0;
char c;
printf("please input a string: \n");
while(scanf("%c",&c)&&c!='q')
{
switch (c)
{
case 32:
space++;
break;
case 9:
table++;
break;
case 10:
enter++;
break;
default:
break;
}
}
printf("The number of space: %d\n",space);
printf("The number of table: %d\n",table);
printf("The number of enter: %d\n",enter);
return 0;
}
5.三位数反转
- 题目描述:
输入一个三位数,分离出2它的百位、十位、个位,反转后输出
- 分析:
- 百位:num/100;
- 十位:(num%100)/10;
- 个位:num%10;
#include <iostream>
using namespace std;
int main()
{
int num,NewNum;
printf("请输入一个三位数: \n");
cin>>num;
NewNum=num/100+((num%100)/10)*10+(num%10)*100;
cout<<"翻转结果为: "<<NewNum<<endl;
return 0;
}
6.交换变量
- 题目描述:
输入两个整数a和b,交换二者的值后输出。
- 方法一: 借助中间变量
#include <iostream>
using namespace std;
void swap(int &a,int &b)
{
int t;
t=a;
a=b;
b=t;
}
int main()
{
int a,b;
printf("请输入两个整数: \n");
cin>>a>>b;
swap(a,b);
cout<<"结果为:"<<a<<" "<<b;
return 0;
}
- 方法二: 不借助中间变量
#include <iostream>
using namespace std;
void swap1(int &a,int &b)
{
int t;
t=a;
a=b;
b=t;
}
void swap2(int &a,int &b)
{
a= a+b;
b= a-b;
a= a-b;
}
int main()
{
int a,b;
printf("请输入两个整数: \n");
cin>>a>>b;
swap1(a,b);
cout<<"结果1为:"<<a<<" "<<b<<endl;
swap2(a,b);
cout<<"结果2为:"<<a<<" "<<b<<endl;
return 0;
}
- 方法三: 位运算
void swap3(int &a,int &b)
{
a=a^b;
b=b^a;
a=a^b;
}
7.鸡兔同笼
- 题目描述:
已知鸡和兔的总数量为n,总腿数为m。输入n和m,依次输出鸡的数目和兔的数目。
- 分析:
- 鸡兔的数量不能为0,其次腿数为偶数,解方程:
- m=2*chicken+4*rabbit;
- n= chicken+ rabbit;
#include <iostream>
using namespace std;
int main()
{
int n,m;
int chicken,rabbit;
printf("请输入总数量和总腿数: \n");
cin>>n>>m;
chicken=(4*n-m)/2;
rabbit=(m-2*n)/2;
if(chicken<0||rabbit<0||m%2==1)
{
cout<<"NO answer"<<endl;
}
else
cout<<"鸡:"<<chicken<<" 兔: "<<rabbit<<endl;
return 0;
}
8.三整数排序
- 题目描述:
输入三个整数,从小到大排序后输出。
#include<iostream>
using namespace std;
int main()
{
int num1,num2,num3;
cin>>num1>>num2>>num3;
int t;
if(num1>num2)
{
t=num1;
num1=num2;
num2=t;
}
else if(num2>num3)
{
t=num2;
num2=num3;
num3=t;
}
else if(num1>num3)
{
t=num1;
num1=num3;
num3=t;
}
cout<<num1<<" "<<num2<<" "<<num3<<endl;
return 0;
}
9.年份
- 题目描述:
输入年份,判断是否为闰年。如果是,则输出yes,否则输出no.
#include <iostream>
using namespace std;
bool isLeapYear(int num)
{
if((num%4==0)&&(num%100!=0)||(num%400==0))
return true;
else
return false;
}
int main()
{
int year;
printf("请输出年份: \n");
cin>>year;
if(isLeapYear(year))
printf("是");
else
printf("否");
return 0;
}
10.矩阵的转置
- 题目描述:
从键盘输入一个n*m的矩阵,实现矩阵的转置输出。
#include <iostream>
using namespace std;
int main()
{
int n,m;
cout<<"请输入矩阵的行和列: \n";
cin>>n>>m;
int matrix[n][m];
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cin>>matrix[i][j];
}
}
cout<<"原矩阵: \n";
for(int i=0;i<n;i++)
{
for(int j=0;j<m;j++)
{
cout<<matrix[i][j]<<" ";
}
cout<<endl;
}
cout<<"矩阵的转置: \n";
for(int i=0;i<m;i++)
{
for(int j=0;j<n;j++)
{
cout<<matrix[j][i]<<" ";
}
cout<<endl;
}
return 0;
}
11.十进制和二进制转换器
题目描述:
编写一个程序,将输入的十进制数转换为二进制表示。
#include <iostream>
using namespace std;
void deTobi(int num,int stack[])
{
int i=0;
int t=num/2;
int s=num%2;
do{
t=num/2;
s=num%2;
stack[i]=s;
if(t!=0)
{
num=t;
i++;
}
}while(t);
cout<<"结果为: "<<endl;
for(;i>=0;i--)
{
cout<<stack[i];
}
}
int main()
{
int stack[10];
int num;
cout<<"请输入一个数字: "<<endl;
cin>>num;
deTobi(num,stack);
return 0;
}
12. 数组倒序
#include<iostream>
using namespace std;
void reverse_1(int *arr,int l,int r)
{
if(l<r)
{
swap(arr[l],arr[r]);
return reverse_1(arr,l+1,r-1);
}
else
return;
}
void reverse_2(int *arr,int l,int r)
{
while(l<r)
{
swap(arr[l],arr[r]);
l++;
r--;
}
}
int main()
{
int arr[5]={0,5,6,7,8};
for(int i=0;i<5;i++)
std::cout<<arr[i]<<" ";
std::cout<<std::endl;
reverse_2(arr,0,4);
for(int i=0;i<5;i++)
std::cout<<arr[i]<<" ";
std::cout<<std::endl;
return 0;
}
13. 求区间的最大和第二大元素
#include<iostream>
using namespace std;
void max_and_second_max_1(int *arr,int l,int r,int &maxIndex,int &second_maxIndex)
{
//得到最大的元素
maxIndex=l;
for(int i=l+1;i<=r;i++)
{
if(arr[maxIndex]<arr[i])
{
maxIndex=i;
}
}
//在[l,maxIndex-1][maxIndex+1,r]区间找到次大元素
second_maxIndex=l;
for(int i=l+1;i<maxIndex;i++)
{
if(arr[i]>arr[second_maxIndex])
second_maxIndex=i;
}
for(int i=maxIndex+1;i<=r;i++)
{
if(arr[i]>arr[second_maxIndex])
second_maxIndex=i;
}
}
void max_and_second_max_2(int *arr,int l,int r,int &maxIndex,int &second_maxIndex)
{
if(arr[l]>arr[l+1])
swap(arr[l],arr[l+1]);
for(int i=l+2;i<=r;i++)
{
if(arr[i]>arr[l])
{
if(arr[i]>arr[l+1])
swap(arr[i],arr[l+1]);
else
swap(arr[i],arr[l]);
}
}
maxIndex=arr[l+1];
second_maxIndex=arr[l];
}
int main()
{
int n;
std::cout<<"please input a number: "<<std::endl;
cin>>n;
int arr[n];
std::cout<<"please input array: "<<std::endl;
for(int i=0;i<n;i++)
cin>>arr[i];
int max, second_max;
max_and_second_max_2(arr,0,n-1,max,second_max);
std::cout<<"second max: "<<std::endl;
std::cout<<max<<" "<<second_max<<std::endl;
return 0;
}
14.三维形体的表面积(leetcode 892)
- 题目描述:
在 N * N 的网格上,我们放置一些 1 * 1 * 1 的立方体。
每个值 v = grid[i][j] 表示 v 个正方体叠放在对应单元格 (i, j) 上。
请你返回最终形体的表面积。
示例 1:
输入:[[2]]
输出:10
示例 2:
输入:[[1,2],[3,4]]
输出:34
示例 3:
输入:[[1,0],[0,2]]
输出:16
示例 4:
输入:[[1,1,1],[1,0,1],[1,1,1]]
输出:32
示例 5:
输入:[[2,2,2],[2,1,2],[2,2,2]]
输出:46
提示:
1 <= N <= 50
0 <= grid[i][j] <= 50
- 分析和实现:
这道题是一道和几何知识相关的题目,
- 如果只有一个方块,那么他的表面积就是6。
- 如果有两个方块,那么他们的表面积不算重叠部分就是6*2=12,而两块方块重叠所以需要减去两个面的面积(2-1)*2,最后实际面积就为10.
- 如果有三个方块,那么他们的表面积不算重叠部分就是6*3=18,而三块方块重叠所以需要减去三个面的面积(3-1)*2,最后实际面积就为14.
- 那么递推公式就是:总的表面积=6*方块的个数-(方块的个数-1)*2;
上面是不考虑相邻的情况,也就是周围没有方块,那么如果存在相邻的情况是怎么样的呢?
- 蓝色和红色存在相邻的情况,而相邻的面积为两者间矮的那个的高度的二倍。依次类推,黄色和红色的相邻面积就为2*2.
- 我们遍历的时候是从左上角开始遍历也就是(0,0),要判断相邻,也就是判断向右和向下两个方向的方块数量和自己的数量,如果再判断向上和向左方向,就存在重复计算。相邻面积=方块数量少的*2;
注意:这里要防止边界是否越界。
class Solution {
public:
int surfaceArea(vector<vector<int>>& grid) {
if(grid.empty())
return 0;
int sum=0;
for(int i=0;i<grid.size();i++)
{
for(int j=0;j<grid[0].size();j++)
{
//不考虑相邻
if(grid[i][j]==0)
continue;
sum+=grid[i][j]*6-(grid[i][j]-1)*2;
// cout<<"sum: "<<sum<<endl;
if(i+1<grid.size())
{
sum -=grid[i+1][j]>grid[i][j]?grid[i][j]*2:grid[i+1][j]*2;
}
if(j+1<grid[0].size())
{
sum-=grid[i][j+1]>grid[i][j]?grid[i][j]*2:grid[i][j+1]*2;
}
// cout<<"sum: "<<sum<<endl;
// cout<<"..............."<<endl;
}
}
return sum;
}
};
15.车的可用捕获量(leetcode 999)
- 题目描述:
在一个 8 x 8 的棋盘上,有一个白色车(rook)。也可能有空方块,白色的象(bishop)和黑色的卒(pawn)。它们分别以字符 “R”,“.”,“B” 和 “p” 给出。大写字符表示白棋,小写字符表示黑棋。
车按国际象棋中的规则移动:它选择四个基本方向中的一个(北,东,西和南),然后朝那个方向移动,直到它选择停止、到达棋盘的边缘或移动到同一方格来捕获该方格上颜色相反的卒。另外,车不能与其他友方(白色)象进入同一个方格。
返回车能够在一次移动中捕获到的卒的数量。
示例 1:
输入:[[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".","R",".",".",".","p"],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."]]
输出:3
解释:
在本例中,车能够捕获所有的卒。
示例 2:
输入:[[".",".",".",".",".",".",".","."],[".","p","p","p","p","p",".","."],[".","p","p","B","p","p",".","."],[".","p","B","R","B","p",".","."],[".","p","p","B","p","p",".","."],[".","p","p","p","p","p",".","."],[".",".",".",".",".",".",".","."],[".",".",".",".",".",".",".","."]]
输出:0
解释:
象阻止了车捕获任何卒。
示例 3:
输入:[[".",".",".",".",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".","p",".",".",".","."],["p","p",".","R",".","p","B","."],[".",".",".",".",".",".",".","."],[".",".",".","B",".",".",".","."],[".",".",".","p",".",".",".","."],[".",".",".",".",".",".",".","."]]
输出:3
解释:
车可以捕获位置 b5,d6 和 f5 的卒。
- 分析与实现:
- 首先明确有三种对象:我方的车,我方的象,敌方的卒
- 然后,我方的车要吃敌方的卒,但是我方的象不能挡着
- 我方的车只有一个,车只能向上,向下,向左,向右移动(不止移动一步)。
- 首先,我们找到我方车的位置,然后遍历左、右、上、下四个方向有没有地方的卒。
- 如果提前遇到我方的象,就直接终止搜索。
- 如果一路顺畅,直接遇到敌方的象,那么只取第一次遇到的象。
class Solution {
public:
int numRookCaptures(vector<vector<char>>& board) {
if(board.empty())
{
return 0;
}
int sum=0;
for(int i=0;i<board.size();i++)
{
for(int j=0;j<board[0].size();j++)
{
if(board[i][j]=='R')
{
for(int row=i-1;row>=0;row--)
{
if(board[row][j]=='B')
break;
if(board[row][j]=='p')
{
sum++;
break;
}
}
for(int row=i+1;row<board.size();row++)
{
if(board[row][j]=='B')
break;
if(board[row][j]=='p')
{
sum++;
break;
}
}
for(int col=j-1;col>=0;col--)
{
if(board[i][col]=='B')
break;
if(board[i][col]=='p')
{
sum++;
break;
}
}
for(int col=j+1;col<board.size();col++)
{
if(board[i][col]=='B')
break;
if(board[i][col]=='p')
{
sum++;
break;
}
}
}
else
{
continue;
}
}
}
return sum;
}
};
16. 买卖股票最佳时机(leetcode 121)
- 题目描述:
给定一个数组,它的第 i 个元素是一支给定股票第 i 天的价格。如果你最多只允许完成一笔交易(即买入和卖出一支股票),设计一个算法来计算你所能获取的最大利润。注意你不能在买入股票前卖出股票。
- 示例 1:
输入: [7,1,5,3,6,4]
输出: 5
解释: 在第 2 天(股票价格 = 1)的时候买入,在第 5 天(股票价格 = 6)的时候卖出,最大利润 = 6-1 = 5 。
注意利润不能是 7-1 = 6, 因为卖出价格需要大于买入价格。
- 示例 2:
输入: [7,6,4,3,1]
输出: 0
解释: 在这种情况下, 没有交易完成, 所以最大利润为 0
- 分析:
该题目分为两种操作:买入和卖出,而且买入在前,卖出在后,利润:卖出-买入。因此,通过遍历整个价格,同时倒序遍历价格,当买入和卖出相等时,结束,将此时的利润和前面的最大利润进行比较,取最大值。
- 改进1:
使用 两个指针min和max记录买入的最小、当轮卖出的最大价格,其余情况跳过。(但是没啥效果,哈哈哈)
- 改进2:
如果我是在历史最低点买的股票就好了!太好了,在题目中,我们只要用一个变量记录一个历史最低价格 minprice,我们就可以假设自己的股票是在那天买的。那么我们在第 i 天卖出股票能得到的利润就是 prices[i] - minprice。(分析来源于leetcode)
- 方法一:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int max_profit=INT_MIN;
//i表示买入时候的价格
//j表示卖出时候的价格
for(int i=0;i<prices.size();i++)
{
for(int j=prices.size()-1;j>i;j--)
{
int sum=prices[i]*(-1)+prices[j];
max_profit=max(sum,max_profit);
}
}
return max_profit<0?0:max_profit;
}
};
- 方法二:
class Solution {
public:
int maxProfit(vector<int>& prices) {
int max_profit=INT_MIN;
//i表示买入时候的价格
//j表示卖出时候的价格
int min_price=INT_MAX;
for(int i=0;i<prices.size();i++)
{
if(prices[i]>min_price)
continue;
min_price=prices[i];
for(int j=prices.size()-1;j>i;j--)
{
int max_price=INT_MIN;
if(prices[j]<max_price)
continue;
max_price=prices[j];
int sum=prices[i]*(-1)+prices[j];
max_profit=max(sum,max_profit);
}
}
return max_profit<0?0:max_profit;
}
};
- 方法三
class Solution {
public:
int maxProfit(vector<int>& prices) {
int max_profit=0;
int min_price=INT_MAX;
for(int i=0;i<prices.size();i++)
{
max_profit=max(max_profit,prices[i]-min_price);
min_price=min(min_price,prices[i]);
}
return max_profit;
}
};
17.旋转矩阵(leetcode 面试题01.07)
给你一幅由 N × N 矩阵表示的图像,其中每个像素的大小为 4 字节。请你设计一种算法,将图像旋转 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]
]
- 分析
按顺时针的方向对矩阵进行旋转。
- 假设是4*4的矩阵,首先从四个顶点开始分别是[0,0],[0,3],[3,0],[3,3]
- 首先保存左上角的[0,0],然后将[3,0]赋值给[0,0],将[3,3]赋值给[3,0],将[0,3]赋值给[3,3]
- 保存第一行的第二个点[0,1],然后将[3-1,0]赋值给[0,1],将[3,3-1]赋值给[3-1,0],将[0+1,3]赋值给[3,3-1]
- 保存第一行的第三个点[0,2],然后将[3-2,0]赋值给[0,2],将[3,3-2]赋值给[3-2,0],将[0+2,3]赋值给[3,3-2]
- 最外面的一圈就结束了。
- 中间的这圈重复上面的步骤。(N为矩阵的宽度)
结论:
- 对于第一圈,[0,j],[N-1-j,0],[N-1,N-1-j],[j,N-1]进行位置交换
- 对于第二圈,[1,j],[N-1-j,1],[N-1-1,N-1-j],[j,N-1-1]进行位置交换
- 对于第 i 圈,[i , j],[N-1-j , i],[N-1-i , N-1-j],[j , N-1-i]进行位置交换
- 其次,每圈中,j是小于N-1的,因为如果执行到N-1-i 的位置就重复交换了,对于圈数 i,i是小于N/2的
class Solution {
public:
void rotate(vector<vector<int>>& matrix) {
int N = matrix.size();
for (int i = 0; i < N / 2; i++) {
for (int j = i; j < N - i - 1; j++) {
int temp = matrix[i][j];
matrix[i][j] = matrix[N - j - 1][i];
matrix[N - j - 1][i] = matrix[N - i - 1][N - j - 1];
matrix[N - i - 1][N - j - 1] = matrix[j][N - i - 1];
matrix[j][N - i - 1] = temp;
}
}
}
};
18.翻转字符串的单词(leetcode 151)
- 日期:2020/4/10
- 题目:
给定一个字符串,逐个翻转字符串中的每个单词。
示例 1:
输入: "the sky is blue"
输出: "blue is sky the"
示例 2:
输入: " hello world! "
输出: "world! hello"
解释: 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
示例 3:
输入: "a good example"
输出: "example good a"
解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
说明:
- 无空格字符构成一个单词。
- 输入字符串可以在前面或者后面包含多余的空格,但是反转后的字符不能包括。
- 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含一个。
进阶:
请选用 C 语言的用户尝试使用 O(1) 额外空间复杂度的原地解法。
- 解法一:
对于翻转字符串中的单词,我们可以将每个单词看成一个整体,为了实现翻转,我们可以利用栈的特性(先进后出),那么我们如何找到整个单词呢?我们可以找到单词的首个字母的位置,然后找到单词最后一个字母的位置,将整个单词截取出来压入栈中,最后我们将栈中的元素依次输出,实现翻转。
class Solution {
public:
string reverseWords(string s) {
stack<string> s_string;
string new_string="";
int start;
int end;
int i=0;
while(i<s.length())
{
//先找到非空格字符的位置
for(;i<s.length();i++)
{
//如果字符非空格
if(s[i]!=' ')
break;
}
start=i;
// cout<<"start: "<<start<<endl;
if(i==s.length())
{
break;
}
//找到单词后的空格位置
for(;i<s.length();i++)
{
if(s[i]==' ')
break;
}
end=i;
// cout<<"end: "<<end<<endl;
//压栈
s_string.push(s.substr(start,end-start));
// cout<<"string: "<<s.substr(start,end-start)<<endl;
}
//出栈
int size=s_string.size();
for(int j=0;j<size;j++)
{
//前n-1个单词用空格隔开
if(j!=(size-1))
{
new_string+=s_string.top()+" ";
s_string.pop();
}
//最后一个单词不加空格
else
{
new_string+=s_string.top();
s_string.pop();
}
}
return new_string;
}
};
- 解法二:
- 首先对整个字符串进行整体的翻转;
- 确定子串的起始位置和结束位置。向前移动,局部反转。
- 删除末尾多余的空格。
class Solution {
public:
string reverseWords(string s) {
//翻转字符串
reverse(s.begin(),s.end());
int n=s.size();
//新的字符串的起点
int pos=0;
for(int begin=0;begin<n;begin++)
{
//从非空字符开始
if(s[begin]!=' ')
{
//添加空格做间隔
if(pos!=0)
s[pos++]=' ';
int end=begin;
//遍历到单词的结尾
while(end<n&&s[end]!=' ')
s[pos++]=s[end++];
//进行局部的翻转
reverse(s.begin()+pos-(end-begin),s.begin()+pos);
begin=end;
}
}
s.erase(s.begin()+pos,s.end());
return s;
}
};
19.顺时针打印矩阵(leetcode 面试题29)
- 题目描述:
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字。
示例 1:
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
示例 2:
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
限制:
0 <= matrix.length <= 100
0 <= matrix[i].length <= 100
- 分析:
顺时针打印矩阵,打印的时候就想蜗牛的壳一样,一圈一圈的,首先第一行和最后一行好打印,一个顺时针一个逆时针,处在中间的行,要被遍历两次,第一次是指针从第一行往最后一行走(向下),第二次是指针从最后一行往第一行方向走(向上),这样走完一圈后,新的矩阵又从新开始,但是矩阵的规模变小,需要减去2倍的圈数,当所有元素都打印完后就结束。
注意:需要对指针的方向进行判断,当行数等于最后一行-圈数时,需要改变方向,当到达第一行+圈数时,又改变方向。
class Solution {
public:
vector<int> spiralOrder(vector<vector<int>>& matrix) {
vector<int> ans;
int n=matrix.size();
if(n==0)
return ans;
int m=matrix[0].size();
if(m==0)
return ans;
int row=0;
int circle=0;
bool down=true;
while(ans.size()<n*m)
{
if(row==0+circle)
{
for(int col=0+circle;col<matrix[0].size()-circle;col++)
{
ans.push_back(matrix[row][col]);
}
}
else if(row==matrix.size()-1-circle)
{
for(int col=matrix[0].size()-1-circle;col>=0+circle;col--)
{
ans.push_back(matrix[row][col]);
}
}
else
{
if(down)
ans.push_back(matrix[row][m-1-circle]);
else
ans.push_back(matrix[row][0+circle]);
}
if(down)
{
row++;
if(row==matrix.size()-circle)
{
down=false;
row=matrix.size()-2-circle;
}
}
else
{
row--;
if(row==circle)
{
down=true;
circle++;
row=circle;
}
}
}
return ans;
}
};