刷题第二天

42. 接雨水

在这里插入图片描述
思路:当前位置存水量等于左边最大值与右边最大值的最小值减去当前值;


```cpp
class Solution {
public:
    int trap(vector<int>& height) {
        if(height.size()==0) return 0;
      vector<int> left(height.size(),0);
      vector<int> right(height.size(),0);
      left[0]=height[0];//边界条件
      int res=0;
      right[height.size()-1]=height[height.size()-1];//边界条件
      for(int i=1;i<height.size();i++){//寻找当前位置左边最大值
          left[i]=max(left[i-1],height[i]);
      }
      for(int i=height.size()-2;i>=0;i--){//寻找当前位置右边最大值
          right[i]=max(right[i+1],height[i]);
      }
      for(int i=1;i<height.size()-1;i++){
          res+=min(left[i],right[i])-height[i];
      }
      return res;
    }
};
方法二:利用单调栈


若前后两个水平一致,弹出当前水平位置一样的坐标位置,可以利用坐标差来计算。
```cpp
class Solution {
public:
    int trap(vector<int>& height) {
       stack<int> st;
       int res=0;
       for(int i=0;i<height.size();i++){
           while(!st.empty()&&height[i]>height[st.top()]){//遇见凹地方,可以存放水量
               int cur=st.top();
               st.pop();
               if(st.empty()){//没有左边界
                    break;
               }
               res+=(min(height[i],height[st.top()])-height[cur])*(i-st.top()-1);//左右最小值乘以宽
           }
           st.push(i);
       }
       return res;
    }
};

在这里插入图片描述

542. 01 矩阵

在这里插入图片描述

class Solution {
    int dx[4]={0,-1,0,1};
    int dy[4]={-1,0,1,0};
public:
    vector<vector<int>> updateMatrix(vector<vector<int>>& matrix) {
      int n=matrix.size();
      int m=matrix[0].size();
      vector<vector<int>> vec(n,vector<int>(m,INT_MAX));
      queue<pair<int,int>> que;
      for(int i=0;i<n;i++){
          for(int j=0;j<m;j++){
              if(matrix[i][j]==0){
                  que.push({i,j});
                  vec[i][j]=0;
              }
          }
      }
      while(!que.empty()){
          auto it=que.front();
          que.pop();
          for(int i=0;i<4;i++){
              int x=it.first+dx[i];
              int y=it.second+dy[i];
              if(x>=0&&x<n&&y>=0&&y<m&&vec[x][y]!=0){
                  if(vec[x][y]>vec[it.first][it.second]+1){
                      vec[x][y]=vec[it.first][it.second]+1;
                      que.push({x,y});
                  }
              }
          }
      }
      return vec;
     } 
};

#480. 保龄球

题目描述
​ 打保龄球是用一个滚球去打击十个站立的柱,将柱击倒。一局分十轮,每轮可滚球一次或多次,以击倒的柱数为依据计分。一局得分为十轮得分之和,而每轮的得分不仅与本轮滚球情况有关,还可能与后续一两轮的滚球情况有关。即某轮某次滚球击倒的柱数不仅要计入本轮得分,还可能会计入前一两轮得分。具体的滚球击柱规则和计分方法如下:

​ (1)若某一轮的第一次滚球就击倒全部十个柱,则本轮不再滚球(若是第十轮则还需另加两次滚球,不妨称其为第十一轮和第十二轮,并不是所有的情况都需要滚第十一轮和第十二轮球)。该轮得分为本次击倒柱数 10 与以后两次滚球所击倒柱数之和。

​ (2)若某一轮的第一次滚球未击倒十个柱,则可对剩下未倒的柱再滚球一次。如果这两次滚球击倒全部十个柱,则本轮不再滚球(若是第十轮则还需另加一次滚球),该轮得分为这两次共击倒柱数 10 与以后一次滚球所击倒柱数之和。

​ (3)若某一轮两次滚球未击倒全部十个柱,则本轮不再继续滚球,该轮得分为这两次滚球击倒的柱数之和。

​ 总之,若—轮中一次滚球或两次滚球击倒十个柱,则本轮得分是本轮首次滚球开始的连续三次滚球击倒柱数之和(其中有一次或两次不是本轮滚球)。若一轮内二次滚球击倒柱数不足十个,则本轮得分即为这两次击倒柱数之和。

​ 下面以实例说明如下(字符“/”表示击倒当前球道上的全部的柱):

轮 1 2 3 4 5 6 7 8 9 10 11 12

击球情况 / / / 72 9/ 81 8/ / 9/ / 8/

各轮得分 30 27 19 9 18 9 20 20 20 20

累计总分 30 57 76 85 103 112 132 152 172 192

​ 现在请你编写一个保龄球实时计分程序,用来计算和显示结束后的得分情况。

输入
​ 仅有一行,为前若干轮滚球的情况,每轮滚球用一到两个字符表示,每一个字符表示一次击球,字符“/”表示击倒当前球道上的全部的柱,否则用一个数字字符表示本次滚球击倒的当前球道上的柱的数目,两轮滚球之间用一个空格字符隔开。

如上例对应的输入文件内容为:/ / / 72 9/ 81 8/ / 9/ / 8/

输出
​ 输出一个整数表示最后的得分。

样例输入
/ / / 72 9/ 81 8/ / 9/ / 8/
样例输出
192

#include<iostream>
using namespace std;
#include<string>

struct node {
	char num[3];
	int num1, num2, flag;//一个字符串有两局,需要两个变量记录当前得分。
};
node s[15];
int main() {
	int ans = 0;
	int i = 0;

	while (cin >>s[i].num) {
		if (s[i].num[0] == '/') {
			s[i].num1 = s[i].num2 = 10;//num1供上一局进行选择
			s[i].flag = 2;//表示直接清空
		}
		else if (s[i].num[1] == '/') {
			s[i].num1 = s[i].num[0] - '0';//间接清空第一局得分
			s[i].num2 = 10;//间接清空第二局得分
			s[i].flag = 1;//表示间接清空
		}
		else {
			s[i].num1 = s[i].num[0] - '0';
			s[i].num2 = s[i].num[1] - '0' + s[i].num1;
		}
		i++;
	}
	for (int i = 0; i < 10; i++) {
		ans += s[i].num2;//先加上当前局得分
		if (s[i].flag == 1) {
			ans += s[i + 1].num1;
		}
		else if (s[i].flag == 2) {
			if (s[i + 1].flag == 2) {
				ans += 10 + s[i + 2].num1;
			}
			else {
				ans += s[i + 1].num2;
			}
		}
	}
	cout << ans << endl;
}

3. 无重复字符的最长子串

在这里插入图片描述
分析:求得是最长连续字符串

class Solution {
public:
    int lengthOfLongestSubstring(string s) {
    unordered_map<char,int> mp;
   int res=0;
   int left=0;//当前窗口左边值
   for(int i=0;i<s.size();i++){
       if(mp.find(s[i])==mp.end()||left>mp[s[i]]){
           res=max(res,i-left+1);
       }
       else{
           left=mp[s[i]]+1;//更新左窗口值
       }
       mp[s[i]]=i;
   }
   return res;
    }
};

1695. 删除子数组的最大得分

给你一个正整数数组 nums ,请你从中删除一个含有 若干不同元素 的子数组。删除子数组的 得分 就是子数组各元素之 和 。

返回 只删除一个 子数组可获得的 最大得分 。

如果数组 b 是数组 a 的一个连续子序列,即如果它等于 a[l],a[l+1],…,a[r] ,那么它就是 a 的一个子数组。

示例 1:

输入:nums = [4,2,4,5,6]
输出:17
解释:最优子数组是 [2,4,5,6]
示例 2:

输入:nums = [5,2,1,2,5,2,1,2,5]
输出:8
解释:最优子数组是 [5,2,1] 或 [1,2,5]

分析:是按和来求最长连续数组

class Solution {
public:
    int maximumUniqueSubarray(vector<int>& nums) {
        vector<int> dp(nums.size());
        dp[0]=nums[0];
        for(int i=1;i<nums.size();i++){
            dp[i]=dp[i-1]+nums[i];//统计连续和数组
        }
        int res=0;
        int left=0;
        unordered_map<int,int> mp;
        for(int i=0;i<nums.size();i++){
          if(mp.find(nums[i])==mp.end()||left>mp[nums[i]]){
            if(left==0){
              res=dp[i];
          }
          else{
             res=max(res,dp[i]-dp[left-1]);
            }
          }
          else{
               left=mp[nums[i]]+1;  
          }
          mp[nums[i]]=i;}
          return res;
    }
};

#484. 柱状统计图

题目描述
​ 给出一些字符串,总长度不超过 1000,统计其中大写字母的个数,并按照给定样例格式输出。

输入
​ 一堆字符串,每两个字符串之间可能用空格、换行隔开。

输出
​ 参照样例输出柱状统计图,每个 ∗ 表示出现一次,注意每行不要有多余的空格。

样例输入
ABC ABC.DEF()G GCC XY
354342aaaCaa aaaaaaaabcdbcd
样例输出
*
*
*



A B C D E F G H I J K L M N O P Q R S T U V W X Y Z

#include<iostream>
using namespace std;
#include<algorithm>
int nums[130];
char str[1005];
int main() {
	while (cin >> str) {
		for (int i = 0; str[i]; i++) {
			nums[str[i]]++;
		}
	}
	int mmax = 0;
	//获取最大值
	for (int i = 'A'; i < 'Z'; i++) {
		mmax = max(mmax, nums[i]);
	}
	//从上向下遍历
	for (int i = mmax; i >0; i--) {
		int index = 'A';
		//从后往前遍历
		for (int j = 'Z'; j > 'A'; j--) {
			if (nums[j] >= i) {
				index = j;//最远出现距离
				break;
			}
		}
		for (int j = 'A'; j <= index; j++) {
			if (j != 'A') {
				cout << " ";
			}
			if (nums[j] >= i) {
				cout << "*";
			}
			else {
				cout << " ";
			}
		}
		cout << endl;
	}
	for (char i = 'A'; i <= 'Z'; i++) {
		if (i != 'A') {
			cout << " ";
		}
			cout << i;
	}


	cout << endl;




}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值