classSolution{public:int dx[4]={0,1,-1,0};int dy[4]={1,0,0,-1};int m =0;int n =0;intsolve(vector<vector<char>>& grid){int ret =0;
m = grid.size();
n = grid[0].size();for(int i =0; i < m; i++){for(int j =0; j < n; j++){if(grid[i][j]=='1'){
ret++;dfs(grid, i, j);}}}return ret;}voiddfs(vector<vector<char>>& grid,int i,int j){
grid[i][j]='0';for(int k =0; k <4; k++){int x = i + dx[k];int y = j + dy[k];if(x >=0&& x < m && y >=0&& y < n && grid[x][y]=='1'){dfs(grid, x, y);}}}};
算法思路:A 和 B 的最小公倍数 = A * B / 两者的最大公约数。 最大公约数:辗转相除法。
C++ 算法代码:
#include<iostream>usingnamespace std;intgcd(int a,int b){if(b ==0){return a;}returngcd(b, a % b);}intmain(){int a =0;int b =0;
cin >> a >> b;
cout <<(a * b /gcd(a, b))<< endl;return0;}
2.2 数组中的最长连续子序列(排序 + 模拟)
题目链接: NC95 数组中的最长连续子序列
题目描述:
解法:
算法思路:排序 + 模拟 。但是要注意处理数字相同的情况!
C++ 算法代码:
classSolution{public:intMLS(vector<int>& arr){sort(arr.begin(), arr.end());int n = arr.size();int ret =0;int tmp =1;for(int i =0; i < n -1; i++){if(arr[i +1]- arr[i]==1){
tmp++;if(tmp > ret){
ret = tmp;}}elseif(arr[i +1]- arr[i]==0){continue;}else{
tmp =1;}}return ret;}};
2.3 字目收集(动态规划 - 路径问题)
题目链接: DP39 字母收集
题目描述:
解法:
算法思路:基础的路径问题的 dp 模型。
C++ 算法代码:
#include<iostream>usingnamespace std;constint N =510;char g[N][N];int dp[N][N];int m =0;int n =0;intmain(){
cin >> m >> n;for(int i =1; i <= m; i++){for(int j =1; j <= n; j++){
cin >> g[i][j];}}for(int i =1; i <= m; i++){for(int j =1; j <= n; j++){int tmp =0;if(g[i][j]=='l'){
tmp =4;}elseif(g[i][j]=='o'){
tmp =3;}elseif(g[i][j]=='v'){
tmp =2;}elseif(g[i][j]=='e'){
tmp =1;}
dp[i][j]=max(dp[i -1][j], dp[i][j -1])+ tmp;}}
cout << dp[m][n]<< endl;return0;}
3. Day09
3.1 添加逗号(模拟)
题目链接: BC146 添加逗号
题目描述:
解法:
算法思路:可以从后往前遍历这个数,每提取三个数字的时候,加⼀个逗号。最后处理⼀下边界情况即可。
C++ 算法代码:
#include<iostream>usingnamespace std;intmain(){
string s;
cin >> s;
string ret;int n = s.size();for(int i =0; i < n; i++){
ret += s[i];if((n - i -1)%3==0&& i != n -1){
ret +=',';}}
cout << ret << endl;return0;}
3.2 跳台阶(动态规划)
题目链接: DP2 跳台阶
题目描述:
解法:
算法思路:最入门的动态规划问题,不必多说…
C++ 算法代码:
#include<iostream>usingnamespace std;constint N =41;intmain(){int n =0;
cin >> n;int dp[N]={0};
dp[0]=1;
dp[1]=1;for(int i =2; i <= n; i++){
dp[i]= dp[i -1]+ dp[i -2];}
cout << dp[n]<< endl;return0;}
3.3 扑克牌顺子(排序)
题目链接: 扑克牌顺子
题目描述:
解法:
规律:如果能够构成顺子的话,所有的非零元素应该满足下面两个条件:
不能出现重复元素;
max - min <= 4
C++ 算法代码:
classSolution{public:boolIsContinuous(vector<int>& numbers){sort(numbers.begin(), numbers.end());int hash[14]={0};for(int j =0; j <5; j++){if(numbers[j]==0){continue;}if(numbers[4]- numbers[j]>4){returnfalse;}else{break;}}for(int i =0; i <5; i++){if(numbers[i]!=0&& hash[numbers[i]]!=0){returnfalse;}else{
hash[numbers[i]]=1;}}returntrue;}};
4. Day10
4.1 最长回文子串(回文串)
题目链接: OR26 最长回文子串
题目描述:
解法:
算法思路:枚举所有的中心点,然后向两边扩散。
C++ 算法代码:
classSolution{public:intgetLongestPalindrome(string A){int n = A.size();int ret =1;for(int i =0; i < n; i++){// 当⻓度是奇数的时候int left = i -1;int right = i +1;while(left >=0&& right < n && A[left]== A[right]){
left--;
right++;}
ret =max(ret, right - left -1);// 当⻓度是偶数的时候
left = i;
right = i +1;while(left >=0&& right < n && A[left]== A[right]){
left--;
right++;}
ret =max(ret, right - left -1);}return ret;}};
4.2 买卖股票的最好时机(一)(贪心)
题目链接: DP30 买卖股票的最好时机(一)
题目描述:
解法:
算法思路:小贪心:
因为只能买卖⼀次,因此,对于第 i 天来说,如果在这天选择卖出股票,应该在 [0, i] 天之内,股票最低点买入股票,此时就可以获得最大利润。
那么,我们仅需维护⼀个前驱最小值的变量,并且不断更新结果即可。
C++ 算法代码:
#include<iostream>usingnamespace std;constint N =1e5+10;intmain(){int n =0;
cin >> n;int prices[N];for(int i =0; i < n; i++){
cin >> prices[i];}int ret =0;int premin = prices[0];for(int i =1; i < n; i++){
premin =min(prices[i], premin);
ret =max(ret, prices[i]- premin);}
cout << ret << endl;return0;}
#include<iostream>#include<vector>usingnamespace std;intabs(int a){if(a <0){return-a;}return a;}intmain(){int n, m, x, y;
cin >> n >> m >> x >> y;
vector<vector<longlong>>dp(n +2,vector<longlong>(m +2));
x +=1;
y +=1;
dp[0][1]=1;for(int i =1; i <= n +1; i++){for(int j =1; j <= m +1; j++){if(i != x && j != y &&abs(i - x)+abs(j - y)==3||(i == x && j == y)){
dp[i][j]=0;}else{
dp[i][j]= dp[i][j -1]+ dp[i -1][j];}}}
cout << dp[n +1][m +1]<< endl;return0;}
5. Day11
5.1 游游的水果大礼包(枚举)
题目链接: 游游的水果大礼包
题目描述:
解法:
算法思路:
很容易想到贪心,但是很不幸,贪心是错的。
正确的解法应该是枚举所有的情况~
C++ 算法代码:
#include<iostream>usingnamespace std;intmain(){int n, m, a, b;
cin >> n >> m >> a >> b;longlong ret =0;for(longlong i =0; i <=min(n /2, m); i++){longlong j =min(n - i *2,(m - i)/2);
ret =max(ret, a * i + b * j);}
cout << ret << endl;return0;}
5.2 买卖股票的最好时机(二)(贪心)
题目链接: DP31 买卖股票的最好时机(二)
题目描述:
解法:
算法思路:小贪心:因为可以无限次交易,因此,只要股票的价格有上升,就统统把利润拿到⼿。
C++ 算法代码:
#include<iostream>usingnamespace std;constint N =1e5+10;intmain(){int n =0;
cin >> n;int prices[N]={0};for(int i =0; i < n; i++){
cin >> prices[i];}int ret =0;for(int i =0; i < n -1; i++){if(prices[i +1]> prices[i]){
ret += prices[i +1]- prices[i];}}
cout << ret << endl;return0;}// 动态规划#include<iostream>#include<vector>usingnamespace std;constint N =1e5+10;intmain(){int n =0;
cin >> n;int prices[N]={0};for(int i =0; i < n; i++){
cin >> prices[i];}
vector<int>f(n +1);//卖出股票,没有股票什么都不干
vector<int>g(n +1);//买入股票
g[0]=-prices[0];for(int i =1; i <= n; i++){
f[i]=max(f[i -1], g[i -1]+ prices[i]);
g[i]=max(g[i -1], f[i -1]- prices[i]);}
cout << f[n]<< endl;return0;}
5.3 倒置字符串(字符串)
题目链接: OR62 倒置字符串
题目描述:
解法:
算法思路:找到规律反转字符串即可。
C++ 算法代码:
#include<iostream>#include<algorithm>usingnamespace std;intmain(){
string s;getline(cin, s);reverse(s.begin(), s.end());int left =0;int right =0;int n = s.size();while(right < n){if(s[right]!=' '){
right++;}else{reverse(s.begin()+ left, s.begin()+ right);
right++;
left = right;}}reverse(s.begin()+ left, s.begin()+ right);
cout << s << endl;return0;}
算法思路。简单线性 dp: 维护 i 位置之前,⼀共有多少个 “s” “sh” ,然后更新 “shy” 的个数。
C++ 算法代码:
#include<iostream>usingnamespace std;intmain(){int n =0;
cin >> n;
string str;
cin >> str;longlong s =0;longlong h =0;longlong y =0;for(int i =0; i < n; i++){char ch = str[i];if(ch =='s'){
s++;}elseif(ch =='h'){
h += s;}elseif(ch =='y'){
y += h;}}
cout << y << endl;return0;}