C++基础编程题

目录

1.最大公约数和最小公倍数

2.判断素数

3.计算字符串的ASCII码

4. 字符类型统计器

 5.三位数反转

6.交换变量

7.鸡兔同笼

8.三整数排序

9.年份

10.矩阵的转置

11.十进制和二进制转换器

12. 数组倒序

 13. 求区间的最大和第二大元素

14.三维形体的表面积(leetcode 892)

15.车的可用捕获量(leetcode 999)

16. 买卖股票最佳时机(leetcode 121)

17.旋转矩阵(leetcode 面试题01.07)

18.翻转字符串的单词(leetcode 151)

19.顺时针打印矩阵(leetcode 面试题29)

未完待续.......持续更新


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它的百位、十位、个位,反转后输出

  • 分析:
  1. 百位:num/100;
  2. 十位:(num%100)/10;
  3. 个位: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,依次输出鸡的数目和兔的数目。

  • 分析:
  1. 鸡兔的数量不能为0,其次腿数为偶数,解方程:
  2. m=2*chicken+4*rabbit;
  3. 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

  • 分析和实现:

这道题是一道和几何知识相关的题目,

  1. 如果只有一个方块,那么他的表面积就是6。
  2. 如果有两个方块,那么他们的表面积不算重叠部分就是6*2=12,而两块方块重叠所以需要减去两个面的面积(2-1)*2,最后实际面积就为10.
  3. 如果有三个方块,那么他们的表面积不算重叠部分就是6*3=18,而三块方块重叠所以需要减去三个面的面积(3-1)*2,最后实际面积就为14.
  4. 那么递推公式就是:总的表面积=6*方块的个数-(方块的个数-1)*2;

上面是不考虑相邻的情况,也就是周围没有方块,那么如果存在相邻的情况是怎么样的呢?

  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 的卒。

  •  分析与实现:
  • 首先明确有三种对象:我方的车,我方的象,敌方的卒
  • 然后,我方的车要吃敌方的卒,但是我方的象不能挡着
  • 我方的车只有一个,车只能向上,向下,向左,向右移动(不止移动一步)。
  1. 首先,我们找到我方车的位置,然后遍历左、右、上、下四个方向有没有地方的卒。
  2. 如果提前遇到我方的象,就直接终止搜索。
  3. 如果一路顺畅,直接遇到敌方的象,那么只取第一次遇到的象。
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:

Profit Graph

如果我是在历史最低点买的股票就好了!太好了,在题目中,我们只要用一个变量记录一个历史最低价格 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]
]

rotate.gif

  • 分析 

按顺时针的方向对矩阵进行旋转。

  • 假设是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;


    }
};
  • 解法二:
  1. 首先对整个字符串进行整体的翻转;
  2. 确定子串的起始位置和结束位置。向前移动,局部反转。
  3. 删除末尾多余的空格。

fig

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;
    }
};

未完待续.......持续更新

  • 19
    点赞
  • 175
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

火柴的初心

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值