每日两题cpp

  • 组队竞赛(贪心)
  • 删除公共字符(哈希)
  • 排序子序列(数组)
  • 倒置字符串(字符串)
  • 数组中出现次数超过一半的数字(数组)
  • 进制转换(数学)
  • 连续最大和(贪心,动态规划)
  • 不要二(贪心,数学)
  • 把字符串转换成整数(库函数atoi的实现)(类型转换,边界处理)
  • 另类加法(数学,位运算)
  • 走方格的方案数(动态规划,路径)
  • 参数解析(模拟,字符串)
  • 跳石板(贪心,动态规划)
  • 幸运的袋子(dfs深度搜索+剪枝)
  • 扑克牌大小(字符串,模拟)
  • 杨辉三角的变形
  • 统计每个月兔子的总数(模拟,递推)
  • 字符串通配符(字符串,模拟,DFS)
  • 最长公共子序列(动态规划)
  • 最长公共子串(动态规划)
  • 最长公共字串计算(动态规划)
  • 洗牌(数组,递推,模拟)
  • MP3光标位置(数组,滑动窗口,模拟)
  • 编辑距离(字符串,动态规划)
  • 年终奖(二维数组,动态规划)
  • 迷宫问题
  • 星际密码(递推规律)
  • 数根(字符串,高精度,整型,递归)
  • 跳台阶扩展问题(变态版青蛙跳台阶,递归,数学)
  • 高精度加法
  • 高精度减法
  • 高精度乘法
  • 不用加减乘除做加法
  • 判断三角形

组队竞赛(贪心)

解题思路

本题的主要思路是贪心算法,贪心算法其实很简单,就是每次选值时都选当前能看到的局部最解忧,所
以这里的贪心就是保证每组的第二个 是次大的 ;
先排好序,每次使用最左边的和最右边的两个进行组队,可以保证每队中间位置局部最大,对其加和;

#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;int main()
{vector<int>arr;int n,tmp;while(cin>>n){while(cin>>tmp){arr.push_back(tmp);}//录入完成;sort(arr.begin(),arr.end());long long ret = 0;for(int i = n;i<arr.size();i+=2){ret+=arr[i];}cout<<ret<<endl;}return 0;
}

删除公共字符(哈希)

解题思路

搞个哈希表,存入要删的字符,遍历原字符串,用哈希表过滤的不需要的即可;

#include<iostream>
#include<string.h>
#include<vector>
#include<algorithm>
#include<string>
#include<unordered_set>
using namespace std;int main()
{string s1,s2;unordered_set<char>st;// 注意这里不能使用cin接收,因为cin遇到空格就结束了。// oj中IO输入字符串最好使用getline。getline(cin,s1);getline(cin,s2);for(int i = 0;i<s2.size();i++){st.insert(s2[i]);}for(int i = 0;i<s1.size();i++){if(st.find(s1[i])==st.end()) cout<<s1[i];}cout<<endl;return 0;
}

排序子序列(数组)

解题思路

flag作为标志转换器1为递增序列,-1为递减序列,每次变换完恢复0(待设置状态),循环统计转折次数;

#include<iostream>
using namespace std;int main()
{int n;cin >> n;int arr[n];//当第一次出现子序列转折时,其实已经"一刀两断",划分成两个子序列了int cnt = 1;int flag = 0;if (n <= 2) return 1;for (int i = 0; i < n; i++){cin >> arr[i];}for (int i = 0; i < n; i++){if (i + 1 < n && arr[i] < arr[i + 1]){//flag待设置,根据递增还是递减设置flag;if (flag == 0) flag = 1;//flag-1递减状态,序列出现递增,划分,cnt++flag恢复初始待设置状态if (flag == -1){flag = 0;cnt++;}}else if (i + 1 < n && arr[i] > arr[i + 1]){if (flag == 0) flag = -1;if (flag == 1){cnt++;flag = 0;}}//else 这里就是arr[i] > arr[i + 1],不处理只需要让i++ for里面处理了;}cout << cnt << endl;return 0;
}

倒置字符串(字符串)

解题思路

1.先反转每个单词;
2.再反转整体字符串则可以达到目的;(善于观察)

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;int main()
{string str;vector<int>arr;getline(cin,str);int len = str.size();//先反转每个单词int l = 0;int r = 1;while(l<len){while(r<len&&str[r]!=' ') r++;//找出空格' 'or字符串结尾位置;(最后一个单词也要反转)reverse(str.begin()+l,str.begin()+r);l = r+1;r = l;}//再反转整体reverse(str.begin(),str.end());cout<<str<<endl;return 0;
}

数组中出现次数超过一半的数字(数组)

解题思路

思路1:超过一半肯定mid位置是这个数,sort+返回;
时间O(nlogn)
思路2:出现次数抵消原理,遍历一遍最终一定剩下出现次数最多得数字,直接返回;
时间O(n),空间O(1)最优;

class Solution {public:int MoreThanHalfNum_Solution(vector<int> numbers) {int ret = numbers[0];//记录出现次数多得数字;int times = 0;//记录出现次数;for(auto &e:numbers){if(e!=ret) times--;else times++;if(times == 0){ret = e;times++;}}return ret;}
};

进制转换(数学)

解题思路

进制转换:辗转相除法;
不仅限于转二进制,有可能转16进制,因此用一个字符数组映射10-_>‘a’,11–>b’等;

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;int main()
{string ret;char arr[]= {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};int x,n;cin>>x>>n;//特殊情况,不然会打印空字符串;if(x == 0){cout<<0<<endl;return 0;}//负数在开头先输出'-'代表其为负数,再将其按整数运行,因为arr映射的时候下标都是正的;if(x<1){cout<<'-';x*=-1;}//辗转相除while(x){ret+=arr[x%n];x/=n;}//每次添加入ret的结果是低位到高位的,最后需要翻转输出reverse(ret.begin(),ret.end());cout<<ret<<endl;return 0;
}

连续最大和(贪心,动态规划)

解题思路

1.贪心,依次累加,将出现过的最大值存入max,若sum变<0,则舍弃 置sum=新的arr[i];
2.dp; dp[i] = max(nums[i],nums[i]+dp[i-1]);//状态转移方程;

贪心

class Solution {public:
//贪心;int maxSubArray(vector<int>& nums) {int ans = INT_MIN;int sum = 0;for(int i = 0;i<nums.size();i++){//如果上次的sum为<0 则置换为nums[i];if(sum<=0){sum = nums[i];}else{sum+=nums[i];}//每次更新cur;if(sum>ans){ans = sum;}}return ans;}
};

DP

class Solution {public:int maxSubArray(vector<int>& nums) {int n = nums.size();//dp数组dp[i] 就是以数组下标为 i 的数做为结尾的最大子序列和;int dp[n];//dp初始化dp[0] = nums[0];int ret = nums[0];for(int i = 1;i<n;i++){dp[i] = max(nums[i],nums[i]+dp[i-1]);//状态转移方程;if(ret<dp[i]) ret = dp[i];}return ret;}
};

不要二(贪心,数学)

解题思路

所谓欧几里得距离,就是两点之间得直线距离;(距离L=开根号((x2-x1)^2+(y2-y1)^2))
题目要距离L不能等于2,则L^2!=4,意味着(x2-x1)^2+(y2-y1)^2!=4根据表达式两个整数平方的和为4能看出只有0+4,4+0,这两种情况(对应x2-x1=2或y2-y1=2);
则用贪心的思路,可以看出:假设放蛋糕的位置是(x1,y1),则不能放蛋糕的位置(x2,y2),满足x1=x2,y1-y2=2或者x1-x2=2,y1=y2.)

#include<iostream>
#include<vector>
using namespace std;int main()
{int N, M;cin >> N >> M;vector<vector<int>>arr;arr.resize(N);//将棋盘内全放上蛋糕for (int i = 0; i < N; i++) arr[i].resize(M, 1);int cnt = 0;for (int i = 0; i < N; i++){for (int j = 0; j < M; j++){if (arr[i][j] == 1)//某个蛋糕的位置,其位置i+2 合 j+2不能放,去掉蛋糕;{cnt++;if (i + 2 < N)arr[i + 2][j] = 0;if (j + 2 < M)arr[i][j + 2] = 0;}}}cout << cnt << endl;return 0;
}

把字符串转换成整数(库函数atoi的实现)(类型转换,边界处理)

解题思路

本题关键是字符串可能100长度,那么显然会越界int~[-INT_MAX+1,INT_MAX了],atoi是直接取界返回的;
用一个大于int范围得long long ret依次进行字符转数字的处理,一但越界就停止转换,直接返回边界,牵扯类型转换;

class Solution {public://类似于库函数stoi的实现;//要点 int范围~[-INT_MAX+1,INT_MAX],越过了需要令其等于边界;int StrToInt(string str) {int flag = 1;if(str[0]=='-') flag = -1;//判断负数;int len = str.size();long long ret = 0;//数组大小100 因此某个int可能越界,搞个大的LL来处理;for(int i = 0;i<len;i++){char tmp = str[i];if(!isdigit(tmp)){if(tmp=='+'||tmp=='-') continue;return 0;//出现非法字符题return 0库里return ret(非法字符前面}ret = ret*10+(tmp-'0');//字符串从头到尾转换成数字的核心逻辑if(flag==1&&ret>INT_MAX)//正数ret某次处理完>INT_MAX了{ret = INT_MAX;break;}if(flag==-1&&ret>static_cast<long long>(INT_MAX)+1)//负数ret某次处理完>INT_MAX+1了,这里必须提升一下整形INT_MAX的范围再+1,否则会溢出!!!{ret = INT_MAX+1;break;} }//最后LL强转成int返回;return flag==1?static_cast<int>(ret):static_cast<int>(-1*ret);}
};

另类加法(数学,位运算)

解题思路

不能用±*/;那就用位运算;
两个数求和,其实就是求和后当前位的数据+两个数求和的进位;
求和后当前位的数据a^b(两数对应位置0,0->0;1,1->0;0,1->1)
求和的进位:(a&b)<<1(因为a&b找到求和前对应的位置都为1,所以求和后该位置应该置0进1位了)

class UnusualAdd {public:int addAB(int A, int B) {//可能连续进位eg(111+001),所以用whilewhile(B)//无进位则退出;{int tmp = A&B;//找到需要置0进位的多个位置i;A = A^B;B = tmp<<1;//<<1,代表i位置进位1位后需要加的数,然后准备与原数继续相加;}return A;}
};

走方格的方案数(动态规划,路径)

解题思路

DP,从头开始记录到达每一个位置所拥有的最多种路径,逐步推演到终点;
题目规定只能向下或者向上走,dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
能到达第一行和第一列上的位置所有路径均为1;

#include<bits/stdc++.h>
using namespace std;int main()
{int n, m;cin >> n >> m;//初始化棋盘格;沿着边缘线走,则大小(n+1)*(m+1)n++;m++;int dp[n][m];memset(dp,0, n * m*4);//只能向左或者向下走,则第一行&&第一列就都只有一种走法;dp数组初始化;for (int i = 0; i < n; i++){dp[i][0] = 1;}for (int i = 0; i < m; i++){dp[0][i] = 1;}//动态规划思想;dp[i][j] = dp[i - 1][j] + dp[i][j - 1];dp[i][j]=到i,j位置最多的路条数;for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){if (dp[i][j] == 0){dp[i][j] = dp[i - 1][j] + dp[i][j - 1];}}}cout << dp[n - 1][m - 1] << endl;return 0;
}

最近公共祖先(二叉树)

解题思路1

上述连续整数二叉树中父节点与子节点的关系为:root=child/2;因此a,b自下向上寻找相同的root即可

class LCA {public:int getLCA(int a, int b) {// write code herewhile(a!=b){if(a<b) b/=2;//在下面的child先走,可以保证两边平衡找最近的根;else a/=2;}return a;}
};

解题思路2

左孩子:root2,右孩子:root2+1;在二进制表示为root的二进制序列尾部追加0或1;
因此某一个祖先root发展子代的时候只是不断追加0或1,则该祖先的二进制序列对于子代的序列是公共前缀;
那么本题从高位到低位找出a,b的最长公共前缀(离a,b最近的公共祖先)转换成十进制即可;

class LCA {public:string _to_string(int x){string ans="";while(x){ans=(char)((x&1)+'0')+ans;//这个+运算顺序很巧妙地保证了转换后低高位一致的顺序行;x/=2;}return ans;}int getLCA(int a, int b) {string sa=int2b(a);string sb=int2b(b);int ans=0;for(int i=0;i<sa.length()&&i<sb.length();i++){//从高位到低位找最长公共前缀并转换成十进制if(sa[i]==sb[i]) ans=ans*2+(sa[i]-'0');else break;}return ans;}
};

参数解析(模拟,字符串)

解题思路

经典的模拟字符串处理问题;
但值得注意的是模拟问题的if else if else…的合理顺序和格式,回事代码的逻辑清晰度和可读性大大提高;
本题就两种状态;
1.普通分割,遇到‘ ’停止记录;
2.”str“两引号之间的分割,就算遇到’ '也要继续追加;出了这个”str“状态还是会有‘ ’将其正确停止并记录

#include<bits/stdc++.h>
using namespace std;
int main() {string a;getline(cin, a);vector<string> ans;bool flag = false;//状态转换机?int index = 0;string tmp = "";for (int i = 0; i < a.size(); i++) {if(a[i]=='"')//遇到‘”’,状态切换;{flag = !flag;}else if(a[i]==' '&&!flag)//普通状态,遇到' '需要记录清空tmp了{ans.push_back(tmp);tmp.clear();}else//要么普通状态没遇到“,要么特殊”输入“状态,都继续向后追加;tmp+=a[i];}if (tmp != "")//输出最后一个子段ans.push_back(tmp);cout << ans.size() << endl;for (int i = 0; i < ans.size(); i++)cout << ans[i] << endl;
}

跳石板(贪心,动态规划)

解题思路

题目要求计算从n~m位置最少的跳跃次数,那么如果能依次算出n到m每个位置的最少次数逐渐向后推演,第m个算出的数据就是答案;
int dp[m+1]数组记录走到i位置石板所需要的最少跳跃次数;
int dp[m+1]初始设为-1(代表没走到的位置),dp[n] = 0为起始位置;
arr中记录当前位置i的所有约数,在dp数组中依次假设推演(贪心);

  • 如果dp[i+arr[j]]==-1,代表该位置没到过,则dp[i+arr[j]] = dp[i]+1,代表从i位置一步到达i+arr[j]并记录;
  • 如果dp[i+arr[j]]!=-1,代表该位置到过,则dp[i+arr[j]] = min(dp[i]+1,dp[i+arr[j]]),代表从i位置一步到达i+arr[j]并记录;这也就是状态转移方程
#include<bits/stdc++.h>
using namespace std;
//求a的所有公约数,存入数组
void f(int v,vector<int>&a)
{for (int i = 2; i <= sqrt(v); ++i)//这里求约数的优化,O(n)->O(log2)大大提高了效率{if (v % i == 0){a.push_back(i);if (v / i != i) a.push_back(v / i);}}
}
int main()
{int n,m;cin>>n>>m;int dp[m+1];//dp[i] == 走到i位置石板所需要的最少跳跃次数 memset(dp,-1,(m+1)*4);//-1代表当前不能达到;dp[n] = 0; //初始化,注意n是起点;for(int i = n;i<=m;i++){if(dp[i]==-1) continue;//某个位置i都没到过,不需要考虑该i位置向后走了 直接跳过;//所有公约数数组;vector<int>arr;f(i,arr);sort(arr.begin(),arr.end());//这里把约数排序为了下面break优化越界约数(步长);//将arr种所有 有可能的公约数(步数)都考虑一边;for(int j = 0;j<arr.size();j++){if(i+arr[j]>m) break;//某个约数(步长)越界了,break,后面的也超了else{if(dp[i+arr[j]]!=-1)//之前某一步来过{//状态转移更新方程;dp[i+arr[j]] = min(dp[i+arr[j]],dp[i]+1);}else dp[i+arr[j]] = dp[i]+1;//之前还没哪一步来过}}}cout<<dp[m]<<endl;return 0;
}

幸运的袋子(dfs深度搜索+剪枝)

解题思路

对于任意两个正整数a,b如果满足 a+b>ab,则必有一个数为1,1很妙噢;
题目可以去除任意个小球,则说明这是一道灵活多答案组合,直接想想dfs深度搜索all in的出来不,发现貌似给数组排个序可以,适当剪枝,注意题目同数字小球算一种,那么别忘了去重;

#include<bits/stdc++.h>
using namespace std;
//dfs(~深搜)+剪枝;
int ans = 0;
int sum = 0;
int mul = 1;
int n;
int arr[1010];
void dfs(int index)
{for(int i = index;i<n;i++){//加入 for循环的dfs精髓1for循环的dfs精髓1for循环的dfs精髓1for循环的dfs精髓1for循环的dfs精髓1for循环的dfs精髓1sum+=arr[i];mul*=arr[i];if(sum>mul)//满足条件 ans+1;{ans++;dfs(i+1);}else if(arr[i]==1) dfs(i+1);///sum>mul但是arr[i]==1,再往下dfs一次有可能满足,那时候ans再加;else {//不满足条件,恢复+breaksum-=arr[i];mul/=arr[i];break;//sum>mul&&arr[i]!=1,不满足 剪枝 跳出循环;}//恢复 for循环的dfs精髓2for循环的dfs精髓2for循环的dfs精髓2for循环的dfs精髓2for循环的dfs//if elseif else走完,相当于i位置后面的子dfs都搞定了,则恢复i位置+“DFS向后去重”;(dfs的深搜性质必须去冲,不然会dfs出多组一样的答案,可以用1 1 1 2这个组合模拟一下即可看出来)sum -= arr[i];mul /= arr[i];for (; i < n - 1 && arr[i] == arr[i + 1]; i++);//!去重!;}
}int main()
{//根据数学推论,两个正整数a,b要想a+b>a*b,那么a,b其中一个必为1;scanf("%d",&n);for(int i = 0;i<n;i++) scanf("%d",arr+i);sort(arr,arr+n);dfs(0);cout<<ans<<endl;return 0;
}

手套(贪心,模拟)

解题思路

                        贪心思想---每次局部最优,最后全局最优(题目包含随机概率组合,问至少,那就用贪心all in)

思路:假设有一!非零!序列 a1<a2<a3<a4<…<an,最少选出多少个能够保证覆盖n种颜色?
答案是 sum(a1…an)-a1+1,类似鸽巢原理(a1显然是最小值)

所以我们利用这个公式挑某边用最少的次数覆盖所有颜色ans次,再从另一边随便拿1个return ans+1即可;

1.考虑0的影响(某种颜色手套为0,对应的left和right的这种颜色必须全拿走,否则可能配不上对不满足要求)拿走了以后sum+…的时候就不考虑这个拿走的了,min值的寻找也跟这个数无关了;
2.左边右边同时考虑 返回int ans = min(左 sum(a1…an)-a1 + 两边配不上对的手套 + 1(右随便拿一个),右 sum(a1…an)-a1 + 两边配不上对的手套 + 1(左边随便拿一个)即可; 不管左边覆盖所有颜色再从右边拿一个 还是右边覆盖所有颜色再从左边拿一个,都搞出来 挑其较小值返回即可;

class Gloves {public:int findMinimum(int n, vector<int> left, vector<int> right) {int lsum = 0;int rsum = 0;int non = 0;//无效手套个数int lmin = 30;//这里不能初始left[0],因为这个位置偶遇可能是0,那么永远也找不到left里的最小 正 整数了int rmin = 30;for (int i = 0; i < n; i++){if (left[i]*right[i] == 0) non += (left[i] + right[i]);//配不上对的手套 全拿走else{//需要拿掉的无效手套已经被全处理进none了,走到这里left[i]和right[i]都不为0,累加即可lsum += left[i];rsum += right[i];//min的寻找放在else里,否则non拿走两边的无效手套后,无效手套可能成为min,但是它并没有算在sum+...里,就不满足 sum(a1...an)-a1+1,定理了if(left[i]<lmin) lmin = left[i];if(right[i]<rmin) rmin = right[i];}}return non + min(lsum - lmin + 1, rsum - rmin + 1)  + 1;}
};

扑克牌大小(字符串,模拟)

解题思路

合理地使用substr以‘-’划分左右子字符串(两手牌);
牌依次合法出现,小王,大王要么只出现一张,如果两张同时出现则一定是王炸,且大于一切直接返回;
处理完王炸,剩下要处理的就是1-1,2-2,3-3,4-4,顺子-顺子了,string 的find妙用可以确定比较顺序;

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;
string FindMax(const string& line)
{//存在王炸,直接处理掉,免得后续4-2还得看这个2是不是王炸的情况if (line.find("joker JOKER") != string::npos)return "joker JOKER";int dash = line.find('-');//stl库string中的find妙用//分开两手牌(string或者substr都会补‘\0’放心用)string car1 = line.substr(0, dash);string car2 = line.substr(dash + 1);//获取两手牌的张数int car1_cnt = count(car1.begin(), car1.end(), ' ') + 1;//count函数+迭代器的妙用;int car2_cnt = count(car2.begin(), car2.end(), ' ') + 1;//获取两手牌的各自第一张牌string car1_first = car1.substr(0, car1.find(' '));string car2_first = car2.substr(0, car2.find(' '));if (car1_cnt == car2_cnt) //两手牌的类型相同{string str = "345678910JQKA2jokerJOKER";//这里str的设定和find的使用方便巧妙地卡出了两副牌的大小if (str.find(car1_first) > str.find(car2_first))return car1;return car2;}//两手牌类型不同or存在炸弹(若存在炸弹返回那个炸弹(只能存在一个且不是王炸))if (car1_cnt == 4) //说明是炸弹return car1;//之前处理过王炸cnt==2的情况了,这里else if (car2_cnt == 4)return car2;return "ERROR";//没比出大小ERROR放最后返回;
}
int main()
{string line, res;while (getline(cin, line)){res = FindMax(line);cout << res << endl;}return 0;
}

杨辉三角的变形

解题思路

杨辉三角问题可以转换成直角三角形,通过二维数组以及对应位置关系模拟构建;
本题按照题目意思,可以发现第n行有2n - 1个元素,第i,j元素等于上一行第j - 2,j - 1,j三列元素之和(高度规律性可观察得出),每一行的第一列和最后一列都为1;
如果是第二列注意特例则只是上一列j - 1和j两个元素之和

#include<bits/stdc++.h>
using namespace std;int main()
{//高n 最底下最长n*2-1int n;cin >> n;int m = 2*n-1;int arr[n][m];//全初始化为0memset(arr, 0, 4*n*m);for (int i = 0; i < n; i++){//初始对角线和第一列arr[i][2 * i] = 1;arr[i][0] = 1;}//构建三角(注意观察三角转直角三角形后的规则!!!)for (int i = 0; i < n; i++){for (int j = 0; j < 2 * i; j++){//第二列的特例!if (j == 1){arr[i][j] = arr[i - 1][j] + arr[i - 1][j - 1];continue;}if (arr[i][j] == 0){arr[i][j] = arr[i - 1][j - 1] + arr[i - 1][j] + arr[i - 1][j - 2];}}}for (int i = 0; i < m; i++){if (arr[n-1][i] % 2 == 0){cout << i+1<< endl;return 0;}}cout<<-1<<endl;return 0;
}

因为数据范围和内存限制,牛客更新了测试用例,跑不过去了,显然数组的方法不可行了,寻找数学规律;

通过以上的数据分析答案规律为 {-1,-1,2,3,2,4,2,3,2,4,…} ,即第n行上第一个偶数所在的下标;

#include<bits/stdc++.h>
using namespace std;int main()
{int n;cin>>n;if(n<=2){cout<<-1<<endl;return 0;}int ret[] = {2,3,2,4};n-=3;//去掉第一行第二行的特殊情况,第三行相当对应周期下标0,第四行对应周期下表1;以此类推,直接%一次就好n%=4;cout<<ret[n]<<endl;return 0;
}

统计每个月兔子的总数(模拟,递推)

解题思路

不要死磕DP,你会发现很难控制;
一看就有强规律,不妨模拟几次看看答案规律;

#include<bits/stdc++.h>
using namespace std;// 观察一下 答案是斐波那契 f(n) = fn-1+fn-2
int main()
{int n;cin>>n;int a = 1;int c = 1;int b = 1;n-=2;while(n--){c = a+b;a = b;b = c;}cout<<c<<endl;return 0;
}

字符串通配符(字符串,模拟,DFS)

解题思路

这道题类似于正则表达式的实现(Python网页爬虫处理url的时候接触过)
模拟,各种情况都考虑清楚;
思路2的DP算法优化到O(n^2)暂时不考虑

#include<bits/stdc++.h>
using namespace std;
class Solution {public:bool Fun(const char* ms, const char* str)//递归匹配;{if (*ms == '\0' && *str == '\0') return true;else if (*ms == '\0' || *str == '\0') return false;else if (isalnum(*str) && isalnum(*ms)){//这里别忘记不区分大小写;if (tolower(*str) != tolower(*ms)) return false;return Fun(ms + 1, str + 1);}else if (!isalnum(*str) && !isalnum(*ms))//两个.可以匹配{return Fun(ms + 1, str + 1);}else if (*ms == '?')//只能匹1个{//str要是'.'这种,就不满足*和?只能匹字母或数字if (!isalnum(*str)) return false;return Fun(ms + 1, str + 1);}else if (*ms == '*')//匹配0 1 或多个{while (*(ms + 1) == '*') ms++;//多个*连续需要没必要,剪一下枝if (!isalnum(*str)) return Fun(ms + 1, str);return Fun(ms + 1, str) || Fun(ms + 1, str + 1) || Fun(ms, str + 1);//类似于dfs}return false;}bool isMatch(string s, string p) {return Fun(p.c_str(), s.c_str());}
};
int main()
{//递归向后匹string str;string ms;cin >> ms >> str;bool ret = Solution().isMatch(str,ms);if (ret) cout << "true" << endl;else cout << "false" << endl;return 0;
}

最长公共子序列(动态规划)

解题思路

要求返回最长公共子序列(可以删减中间元素)的和,分解成从s1,s2的0,0位置,子问题的形式递推到i,j字符末尾,则dp[n][m]就是答案;
1.DP[i][j]数字含义:s1字符串i位置之前和s2字符串j位置之前的最大子段和;
i,j从1开始,i||j==0的位置(第一行or第一列)dp对应的值都为0(空串没有公共子段),dp数组的初始化;
2.递推公式:

  • s1[i]==s2[j]时,dp[i][j] = dp[i-1][j-1]+1;
  • s1[i]!=s2[j]时,dp[i][j] = max(dp[i-1][j],dp[i][j-1]);
class Solution {public:int longestCommonSubsequence(string text1, string text2) {//经典二维dp问题int n = text1.size();int m = text2.size();vector<vector<int>>dp(n + 1, vector<int>(m + 1));//这里已经将dp中的内容全部初始化为0了(第一行,第一列初始为0完成)for(int i = 1;i<=n;i++){for(int j = 1;j<=m;j++){if(text1[i-1]==text2[j-1])dp[i][j] = dp[i-1][j-1]+1;else{//i,j只能从dp[i-1][j]or dp[i][j-1]来了   dp[i][j] = max(dp[i-1][j], dp[i][j-1]);}}}return dp[n][m];  }
};

最长公共子串(动态规划)

解题思路

与上题子序列不同,这题子串要求只能删除连续的前缀或者后缀,而不能随便删除字符进行拟合;//那么相比上一题,这个题的公共子序列只能连续,容易很多 dp转换就一个 if(s1[i-1]==s2[j-1]) dp[i][j]=dp[i-1][j-1]+1了!;

遇上题不同的是 DP[i][j]代表s1串以i位置结尾,和s2串以j位置结尾的子段长度,进行一个max记录并记录start的位置最后返回切割串即可;

这题只需要考虑s1[i]=s2[j]的dp数组更新,因为他只允许删除连续的前缀或者后缀;

//思路:动态规划经典问题,加一个start标记即可,注意将较短子串最先出现的那个输出
#include<iostream>
#include<vector>
#include<string>
using namespace std;
void findMaxCommonStr(string s1,string s2)
{if(s1.length()>s2.length())swap(s1,s2);//s1用于保存较短的子串int len1=s1.length(),len2=s2.length();int maxLen=0,start=0;vector<vector<int> >dp(len1+1,vector<int>(len2+1,0));for(int i=1;i<=len1;++i)for(int j=1;j<=len2;++j){if(s1[i-1]==s2[j-1]){dp[i][j]=dp[i-1][j-1]+1;if(dp[i][j]>maxLen){maxLen=dp[i][j];start=i-maxLen;//记录最长公共子串的起始位置}}}cout<<s1.substr(start,maxLen)<<endl;
}
int main()
{string s1,s2;while(cin>>s1>>s2){findMaxCommonStr(s1,s2);}return 0;
}

最长公共字串计算(动态规划)

解题思路

类似于上一题,这题简化了 只要求输出max长度即可,上一题得根据这个长度找到max字串的起始位置输出子串;
DP[i][j]代表s1串以i位置结尾,和s2串以j位置结尾的子段长度;

#include<bits/stdc++.h>
using namespace std;int main()
{string s1;string s2;cin >> s1 >> s2;int n = s1.size() ;int m = s2.size() ;int dp[n+1][m+1];int max = 0;memset(dp, 0, 4 *(n+1)*(m+1));for (int i = 1; i <= n; i++){for (int j = 1; j <= m; j++){if (s1[i - 1] == s2[j - 1]) dp[i][j] = dp[i - 1][j - 1] + 1;if (dp[i][j] > max) max = dp[i][j];}}cout << max << endl;return 0;
}

洗牌(数组,递推,模拟)

解题思路

一坨牌 分两摊,左右交替放,洗round轮,模拟即可;

#include<bits/stdc++.h>
using namespace std;int main()
{int a;cin >> a;while (a--){int n, round;cin >> n >> round;int cur[2 * n];for (int i = 0; i < 2 * n; i++) cin >> cur[i];//洗牌过程while (round--){vector<int>tmp{ cur,cur + 2 * n };for (int i = 0; i < n; i++)//找出n与left[]和right[]的关系就可以一次循环同时放入对应位置{cur[2 * i] = tmp[i];//左手的牌排放的位置cur[2 * i + 1] = tmp[i + n];//右手的牌排放的位置}}//round轮洗完了,再输出最终洗牌结果;curfor (int i = 0; i < 2 * n - 1; i++){cout << cur[i] << ' ';}cout << cur[2 * n - 1] << endl;}return 0;
}

MP3光标位置(数组,滑动窗口,模拟)

解题思路

定长为4的滑动窗口思想,需要注意的是这里分窗口所在数组元素个数<=n(这种情况不用翻页 简化了很多)和窗口对应的数组>4(可能需要滑动)两种情况;

#include<bits/stdc++.h>
using namespace std;int main()
{//滑动窗口+两端点的情况?int n;cin >> n;string s;cin >> s;//起始的第一页1~4int l = 1;int r = 4;int pos = 1;for (int i = 0; i < s.size(); i++){//不用翻页的情况;if (n <= 4){for (int i = 0; i < n; i++){if (s[i] == 'U'){if (pos == 1) pos = n;else pos--;}else{if (pos == n) pos = 1;else pos++;}}for (int i = 1; i <= n; i++){cout << i << ' ';}cout << endl << pos << endl;return 0;}//n>4的正常逻辑else{if (s[i] == 'U'){//窗口不用动if (pos != l) pos--;else//窗口需要移动了{if (l == 1){l = n - 3;r = n;pos = n;}else{l--;r--;pos--;}}}else//D{if (pos != r)   pos++;else{if (r == n){l = 1;r = 4;pos = 1;}else{r++;l++;pos++;}}}}}for (int i = l; i <= r; i++){cout << i << ' ';}cout << endl << pos << endl;return 0;
}

编辑距离(字符串,动态规划)

解题思路

类似于上面的二维字符串dp问题;

dp[i][j]表示word1的i位置之前和word的j位置之前的字符串,重构所需要的最少操作次数;因此本题一只递推到dp[n][m]即可;

只有三种操作方法,追加,删除or替换一个字符;

因此转移方程对应DP[i][j]的取值从下列3种的最小

  1. dp[i-1][j]+1>>w1删除第i个>>(因为w1的0i-1已经和w2的0j已经重构了,w1的i位置多余了一个字符删掉),

  2. dp[i][j-1]+1>>w1的位置追加字符w2[i]>>(因为w1的0i和w2的0j-1重构了,w2的j位置还多一个字符,w1需要追加它),

  3. dp[i-1][j-1]+1>>替换;>>w1的i-1和w2的j-1位置重构了,新的dp[i][j]的位置也可以从他俩的钱一个位置+1,代表w1的i换成w2的j的字符即可;

转移方程:dp[i][j] = min(dp[i-1][j]+1,mindp[i][j-1]+1,dp[i-1][j-1]+1);

dp初始化://!!注意!! 这个数组的初始化第一行第一列需要给值0~m/n这样递增初始化

//eg:dp\[0][3],w1的0位置之前是“”,w2的3位置之前有3个字母,所以dp\[0][3]应该等于3;

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fdQnStY1-1659875472055)(C:/Users/15795/Desktop/img/a8d194545ef4437b858011d7b6487d15.png)]

class Solution {public:int minDistance(string word1, string word2) {int n = word1.size();int m = word2.size();//dp代表w1到i位置之前与w2到j位置之前的"最短距离"//要么删,要么加,要么替换//地推方程:dp[i][j] = min int dp[n+1][m+1];//!!注意!! 这个数组的初始化第一行第一列需要给值0~m/n这样递增初始化//eg:dp[0][3],w1的0位置之前是“”,w2的3位置之前有3个字母,所以dp[0][3]应该等于3;//初始化dp[0][0] = 0;for(int i = 1;i<=n;i++){dp[i][0] = i;}for(int j = 1;j<=m;j++){dp[0][j] = j;}for(int i = 1;i<=n;i++){for(int j = 1;j<=m;j++){//dp转移if(word1[i-1] == word2[j-1]){dp[i][j] = dp[i-1][j-1];}else{dp[i][j] = min(dp[i-1][j]+1,dp[i][j-1]+1);//减和加dp[i][j] = min(dp[i][j],dp[i-1][j-1]+1);//替换}}}return dp[n][m];}
};

年终奖(二维数组,动态规划)

解题思路(dp)

题目解析:6*6棋盘格,每个格子有一个数字代表该物品价值,需要找到一条路径,该路径上的价值和最大;

  1. dp[i][j],代表走到位置ij时候的累加最大金额;

  2. 初始化:第一行第一列对应的位置是前面位置金额的累加,因为第一行只能一直向右走累加,第一列只能一直向下走累加;

  3. 转移方程:dp[i][j] = max(dp[i-1][j],dp[i][j-1])+board[i][j];//上走下来或者左走到右边,再加当前board的钱

class Bonus {public:int getMost(vector<vector<int> > board) {// write code hereint dp[6][6];memset(dp,0,6*6*4);dp[0][0] = board[0][0];//dp数组的初始化for(int i = 1;i<6;i++){dp[0][i] += dp[0][i-1]+board[0][i];//第一行dp[i][0] += dp[i-1][0]+board[i][0];//第一列}for(int i = 1;i<6;i++){for(int j = 1;j<6;j++){//状态转移方程dp[i][j] = (max(dp[i-1][j],dp[i][j-1])+board[i][j]);}}return dp[5][5];}
};

解题思路(dfs)

二维数组的dfs类似于迷宫求最短路径这种问题;

class Bonus {public:int sum = 0;int max = 0;void dfs(vector<vector<int> >& board,int a,int b){sum+=board[a][b];if(b!=5) dfs(board,a,b+1);if(a!=5) dfs(board,a+1,b);//到终点了if(max<sum) max = sum;sum-=board[a][b];}int getMost(vector<vector<int> > board) {// write code heredfs(board,0,0);return max;}
};

迷宫问题

解题思路

maze问题是经典的回溯算法,和dp问题一样 有着强格式模板话;

本题算是比较简单的 只有一条路径,那么dfs回溯用vector记录路径即可,注意回溯时的录入当前节点和弹出当前结点的过程,即一进入dfs就把当前位置写为走过,要是出这个dfs需要回溯,就把当前节点置为未走状态;

#include<bits/stdc++.h>
using namespace std;
int n, m;
vector<pair<int, int>>tmp;
vector<pair<int, int>>best;
void dfs(vector<vector<int>>& maze, int a, int b)
{if(maze[a][b]==1) return;//位置不合法;maze[a][b] = 1;//位置合法,设置为已经走过 继续dfs向下回溯找路径;  tmp.push_back({ a,b });//记录达到的节点;if (a == n - 1 && b == m - 1)//走到终点{if (best.empty() || tmp.size() < best.size()) best = tmp;//这里也能把最短的记录到;tmp.pop_back();maze[a][b] = 0;return;}//上下左右寻找出路;if (a != 0)dfs(maze, a - 1, b);if (a != n - 1)dfs(maze, a + 1, b);if (b != 0)dfs(maze, a, b - 1);if (b != m - 1)dfs(maze, a, b + 1);//恢复路径 回溯;maze[a][b] = 0;tmp.pop_back();return;
}
int main()
{cin >> n >> m;vector<vector<int>>maze(n, vector<int>(m, 0));for (int i = 0; i < n; i++){for (int j = 0; j < m; j++){cin >> maze[i][j];}}dfs(maze, 0, 0);//从0,0开始寻找路径for (auto& e : best){printf("(%d,%d)\n", e.first, e.second);}return 0;
}

星际密码(递推规律)

解题思路

首先,给定整数x,则翻译的密码就是给定矩阵[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-AUYFlRzJ-1656125056994)(C:/Users/15795/Desktop/img/image-20220625103532957.png)]的x次幂;

乘几次观察得出,这个密码事以f(1) = 1,f(2) = 2的fib数列构成,那么问题就简单很多了;

下面是比较挫的代码;

// write your code here cpp
#include<bits/stdc++.h>
using namespace std;
int arr[10001];
void f2(int& a)//只存后四位,fib(x)可能int存不下 没关系 存后四位即可;//这个函数完全可以用 %10000来存后四位代替.....!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
{if (a <= 9999) return;string tmp = to_string(a);a = stoi(tmp.substr(tmp.size() - 4));
}
void Init()//初始化fib数组 因为会连续输入好几个x 让你求fib(x),用WHILE那种循环求fib(x)的话的话会重复大量计算,超时!!应该用全局数组一遍记录好达到剪枝;
{arr[1] = 1;arr[2] = 2;for (int i = 3; i <= 10000; i++){arr[i] = arr[i - 1] + arr[i - 2];f2(arr[i]);//强制存后四位}
}void f(int x)//这里完全可以用printf("%04d",x);来代替....!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
{//因为肯可能求10000个fib  越界了,题目有要求只需要后四位,就对后四位操作;string ret = "0000";ret += to_string(arr[x]);int len = ret.size();cout << ret.substr(len - 4);
}
int main()
{int flag;Init();while (cin >> flag){for (int i = 0; i < flag; i++){int x;cin >> x;f(x);}cout <<endl;}return 0;
}

优美版本(善于观察,学以致用。。。)

数根(字符串,高精度,整型,递归)

解题思路

即便是想到了应该cin到一个string里,因为数据范围最长可以到100多位数字!

但是,一直在同一个string里操作各位相加还有进位递归啥的不方便;

善于观察可以看出 即便是100多个9,累加也不会超int范围,那我们就用string浅录入过度一下,手动累加一边放入一个int中再用这个int进行递归逐位相加就好啦!

#include<bits/stdc++.h>
using namespace std;int f(int x)//计算一个整数的各位和,最终为个位数时递归终止返回
{if(x<10){return x;}int tmp = 0;while(x){tmp += x%10;x/=10;}return f(tmp);
}int main()
{string s;//最多输入长度为102的数字组合,就算102个9相加int也能装下;//while(cin>>s){int sum = 0;for(int i = 0;i<s.size();i++)//则相当于放入第一次输入的大整数通过string将各位累加放入了int sum{sum+=s[i] - '0';}cout<<f(sum)<<endl;}return 0;
}

跳台阶扩展问题(变态版青蛙跳台阶,递归,数学)

解题思路

//青蛙跳台阶;
//1-1 2-2 3-4…
//和青蛙一次只能1or2步思路类似;
//达到第n的方法可以:
//从第n-1直接跨1个台阶,从第n-2直接跨2个台阶,从n-3一步跨3个台阶。。。从n-(n-1)个台阶一次跨n-1到终点
//递推公式:f(n) = f(0)+f(1)+… f(n-1) 普通青蛙跳台阶的递推公式:f(n) = f(n-1)+f(n-2)//一次只能跳1 or 2个台阶;’

class Solution {public:int jumpFloorII(int number) {if(number == 1) return 1;//f(1) = 1int sum = 1;//f(0) = 1;for(int i = 1;i<number;i++){    sum+=sum;}return sum;}
};

高精度加法

string Add(string& a, string& b)//高精度加
{string ret;int ra = a.size() - 1;int rb = b.size() - 1;int carry = 0;//进位while (ra >= 0 || rb >= 0 || carry > 0){int tmp = 0;tmp += ra < 0 ? 0 : a[ra] - '0';tmp += rb < 0 ? 0 : b[rb] - '0';tmp += carry;carry = tmp / 10;tmp %= 10;ret += '0' + tmp;ra--;rb--;}reverse(ret.begin(), ret.end());return ret;
}

高精度减法

bool Cmp(string &a,string &b)//返回a<b
{if (a.size() < b.size())return true;else if (a.size() > b.size()) return false;else {for (int i = 0; i < a.size(); i++) {if (s[i] < b[i])return true;else if(s[i] > b[i]) return false;}return false;//a == b }
}string Sub(string &a,string &b)// a - b
{int flag = 0;//保证 大 - 小//if (atoi(a.c_str()) < atoi(b.c_str())) {//这样比其实也是有风险的,万一高精度直接越界//    flag = 1;//最后需要输出'-'符号;//    swap(a, b);//}if(Cmp(a,b)){flag = 1;//最后需要输出'-'符号;swap(a, b);}string ret;int ra = a.size() - 1;int rb = b.size() - 1;while (ra>=0||rb>=0){if (ra>=0&&rb<0) {//被减数把减数减完了,还有剩余 直接挪下来;ret += a[ra];ra--;continue;}if (a[ra] < b[rb]) {//需要借位;int index = ra-1;while (a[index] == '0') index--;//找到借的那一位 位置下表a[index]--;//借的那一位被拿掉;for (int i = ra - index ; i > 1; i--) {a[++index] = '9';//路途中补9}ret +=a[ra]-b[rb]+10 +'0';//进了10 然后再减b}else ret += a[ra]-b[rb] +'0';ra--;rb--;}if (flag) ret += '-';reverse(ret.begin(),ret.end());//去除借位之后可能产生的首部无效0(最高位为1 并被借走就这样多了个无效0);if (ret[0] == '0')ret.erase(0,1);return ret;
}

理论上,有了高精度加法和减法,就能(通过交换律)完成无论是正数还是负数之间的加减运算了!

高精度乘法

string f(string &a,string &b)
{string ret = "0";int ra = a.size()-1;int rb = b.size()-1;int carry = 0;//进位int flag = 0;for (int i = rb; i >= 0; i--) {//一共走乘数长度轮string stmp;//记录每一轮的结果!carry = 0;//进位清零!!for (int i = 0; i < flag; i++) stmp += '0';//乘数下一位的轮次,需要在上一倍基础上扩大十倍后再加下一轮的结果!for (int j = ra; j >= 0; j--) {//乘数的某一位,分别与被乘数的每一位相乘,并记录结果进入ret;int tmp = 0;tmp += (a[j] - '0') * (b[i] - '0')+carry;carry = tmp / 10;tmp %= 10;stmp += tmp + '0';}if (carry)stmp += carry+'0';//看还有没有进位reverse(stmp.begin(), stmp.end());ret = Add(ret,stmp);//高精度加法flag++;}return ret;
}

不用加减乘除做加法

考察位运算:

a^b和(a&b)<<1结合使用;

a^b相当于把不进位的0和1加起来了,进位的1和1抵消为0;

(a&b)<<1相当于把需要进位的两个1拿出去进位了,下一轮再加起来 (原进位位置已经被^把两个1消掉了)

class Solution {public:int Add(int num1, int num2) {int a = num1;int b = num2;int carry;int sum = a ^ b;while (carry = (a&b)<<1) {sum = a ^ b;a = sum;//注意在sum与carry^之前,需要先记录当前sum,之后才能看当前sum与carry有没有进位,需不需要继续while循环+b = carry;sum = sum^carry;}return sum;
}
};

判断三角形

记住定理,三角形成立条件:任意两边之和大于第三边;

数据范围过大,使用高精度加法,进行判定;

#include<iostream>
#include<algorithm>
#include<stdlib.h>
using namespace std;bool Cmp(string& s, string& b)//判断大整数a是不是大于b
{if (s.size() > b.size())return true;else if (s.size() < b.size()) return false;else {for (int i = 0; i < s.size(); i++) {if (s[i] > b[i])return true;else if(s[i]<b[i])return false;}return false;}return false;
}string Add(string a, string b)//高精度加法
{string ret;int ra = a.size() - 1;int rb = b.size() - 1;int carry = 0;//进位while (ra >= 0 || rb >= 0 || carry > 0){int tmp = 0;tmp += ra < 0 ? 0 : a[ra] - '0';tmp += rb < 0 ? 0 : b[rb] - '0';tmp += carry;carry = tmp / 10;tmp %= 10;ret += '0' + tmp;ra--;rb--;}reverse(ret.begin(), ret.end());return ret;
}int main()
{string a, b, c;while (cin >> a >> b >> c) {string tmp1 = Add(a, b);string tmp2 = Add(a, c);string tmp3 = Add(c, b);if (Cmp(tmp1, c) && Cmp(tmp2, b) && Cmp(tmp3, a))//Add(q,b)>c 这种判断是错的,因为两个string类型表示的长int 不能直接用string原生的>进行大小判断;cout << "Yes" << endl;else cout << "No" << endl;}return 0;}

一些经典的算法题目cpp相关推荐

  1. POJ 3040 Allowance——经典贪心算法题目

    题目链接 题目大意: 约翰要给他的牛贝西发工资,每天不得低于C元,约翰有n种面值的钱币,第i种的面值为v_i,数量有b_i.问这些钱最多给贝西发多少天的工资.注意,每种面值的金钱都是下一种的面值的倍数 ...

  2. C语言100个经典的算法

    POJ上做做ACM的题 语言的学习基础,100个经典的算法 C语言的学习要从基础开始,这里是100个经典的算法-1C语言的学习要从基础开始,这里是100个经典的算法 题目:古典问题:有一对兔子,从出生 ...

  3. 语言的学习基础,100个经典的算法

    POJ上做做ACM的题 语言的学习基础,100个经典的算法 C语言的学习要从基础开始,这里是100个经典的算法-1C语言的学习要从基础开始,这里是100个经典的算法 题目:古典问题:有一对兔子,从出生 ...

  4. 算法题目中经典问题(易错点)

    算法题目中经典问题.易错点 (一).二维数组的传参问题 1.方法一:形参为二维数组并给定第二维长度 2.方法二:形参为指向数组的指针并给出数组长度 3.二维数组定义为全局变量 (二).多组测试控制台数 ...

  5. 算法:经典题五 题目五 信封套娃层数问题 转化为 数组最长递增子序列问题

    输入:一组信封长宽信息 二维数组(假设都是长大于宽的) 输出:套信封层数最多的 信封个数,最多套多少层娃 要点: 第一纬度信息,从小到大排序,第二维信息再从大到小排序,求第二维的最长递增子序列长度就是 ...

  6. Java经典算法题目(兔子题)及题目分析

    Java经典兔子问题 题目:古典问题:3个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 分析:首先我们要明白题目的意思指的是每个月的兔子总 ...

  7. 算法面试:精选微软经典的算法面试100题(第1-20题)

    算法面试:精选微软经典的算法面试100题 引言: 给你10分钟时间,根据上排给出十个数,在其下排填出对应的十个数 要求下排每个数都是先前上排那十个数在下排出现的次数. 上排的十个数如下: [0,1,2 ...

  8. [经典排序算法][集锦]

    经典排序算法 经典排序算法,以下文章参考了大量网上的资料,大部分都给出了出处 这一系列重点在理解,所以例子什么的都是最简单的情况,难免失误之处,多指教 大多数排序算法都给出了每一步的状态,以方便初学者 ...

  9. 算法面试:精选微软等公司经典的算法面试100题 第26-35题

    算法面试:精选微软等公司经典的算法面试100题 第26-35题 26.左旋转字符串 题目: 定义字符串的左旋转操作:把字符串前面的若干个字符移动到字符串的尾部. 如把字符串abcdef左旋转2位得到字 ...

最新文章

  1. 【vue】.native给组件绑定原生事件
  2. 5.1.8 缓冲区管理
  3. ubuntu 下通过 sh 命令运行脚本产生如下错误:[: y: unexpected operator
  4. lua运行外部程序_LTUI v2.2 发布, 一个基于lua的跨平台字符终端UI界面库
  5. 美国知名华人学者陈刚被捕,他出身贫寒,是一个不折不扣的工作狂
  6. 基于JavaSwing+mysql的图书管理系统设计和实现
  7. 这份数十万人浏览,作为企业风向标的BI报告,你一定要看看
  8. super.onCreate(savedInstanceState)
  9. Jaxb2 转换XML文档
  10. Vue Cli 打包之后静态资源路径不对的解决方法
  11. TCP/IP:ARP与RARP详细解析
  12. [工具] Numpy
  13. Unity DOTS在hybird renderer v2 中rendermesh不显示
  14. 计算机一级ps怎么保存,2017年计算机等考一级PS辅导:PS图像格式详细解说
  15. 计算机提示运行错误,每次电脑一开机就会提示脚本运行错误
  16. Leetcode 318. Maximum Product of Word Lengths
  17. 直播类app开发,如何实现直播的相关功能
  18. Deep Learning 最优化方法
  19. AD9361使用概述
  20. python的range函数用法和实例

热门文章

  1. 扎心了!37岁被裁,好几个月都没有找到工作,面试大公司被婉拒,无奈只能降薪去小公司,没想到还被人嫌弃技术太落后...
  2. dump文件,windbg
  3. php web 登录验证,Web登录Authorization验证
  4. 通达信 服务器 修改,通达信验证服务器数据库修改
  5. 测试理论基础(重点)
  6. Python自学笔记1(think python)
  7. 数据库设计1-数据库设计简述
  8. 华为云服务权限在哪_华为云数据湖探索服务DLI,精细化保障企业大数据安全
  9. 2021年JavaScript最新手机号码、电话号码正则表达式
  10. 【升级pip;查看pip版本】