文章目录
- 1.组队竞赛(贪心)
- 2.删除公共字符(hash)
- 3.排序子序列(干就完了)
- 4.倒置字符串(双指针切片)
- 5.字符串中找出连续最长的数字串(dp)
- 6.数组中出现次数超过一半的数字(dp)
- 7.计算糖果
- 8.进制转换(table表的利用)
- 9.统计回文(双指针)
- 10.连续最大和(dp)
- 11.把字符串转换成整数(细节题)
- 12.不要二(干就完了)
- 13.合法括号序列(栈的使用)
- 14.Fibonacci数列(dp)
- 15.两种排序方法(运算符重载)
- 15.最小公倍数(两种公约数求法)
- 16.走方格的方案数(dp)
- 17.另类加法(位运算)
- 18. 井字棋(干就完了)
- 19. 最近公共祖先(节点下标)
- 20. 求最大连续bit数(位运算)
- 21.二进制插入 -》(位运算)
- 22.组成偶数最近的素数 -》(质数的求法)
- 23.参数解析(遍历)
- 24.跳石板(dp)
- 25.计算日期到天数转换(做就完了)
- 26.幸运的袋子(回溯+组合)
- 27.二进制中1的个数(位运算)
- 28.手套(数学)
- 29.完全数计算(做就行了)
- 30.扑克牌大小(find、count的使用)
- 31.杨辉三角变形(滚动数组)
- 32.超长正整数相加(大数相加)
- 33.统计每个月兔子的总数(fib的变形)
- 34.字符串通配符(递归)
1.组队竞赛(贪心)
解题思路:
- 贪心算法:每次选值时都选当前能看到的局部最优解,因此只要保证每组的第二个数尽可能大
具体实现:
1.对数据排序
2.从下标为n的元素开始,步长为2,统计每个数的和。
代码实现:
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int n;
cin >> n;
int size = 3 * n;
vector<int> ar(size, 0);
for(int i = 0;i < size; i++)
cin >> ar[i];
sort(ar.begin(), ar.end());
long long res=0;
for(int i = n; i < size; i += 2)
res += ar[i];
cout << res << endl;
return 0;
}
2.删除公共字符(hash)
解题思路:
- 暴力查询,依次判断字符串2的每一个字符串1中是否出现
- hash表,把字符串2映射到hash表中,判断字符串1
具体实现:
- 将第二个字符串的字符都映射到一个hashtable数组中,用来判断一个字符在这个字符串。
- 判断一个字符在第二个字符串,不要使用删除,这样效率太低,因为每次删除都伴随数据挪动。这里可以使用一个新字符串,最后返回新字符串
代码实现:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string str1, str2;
while(getline(cin, str1))
{
cin >> str2;
int hash[256] = { 0 };
for(auto i : str2) //把str2中的元素映射到hashtable中
hash[i] = 1;
string res;
for(auto i : str1)
if(hash[i] != 1)
res.push_back(i);
cout << res << endl;
}
return 0;
}
3.排序子序列(干就完了)
解题思路:
定义一个变量 i 从位置 0 开始依次遍历字符串
分三种情况:
- 若ar[i]>ar[i+1],则进入递增序列判断,count++,i++直到下一个值大于ar[i]或者到达最后一个元素位置了
- 若ar[i]<ar[i+1],则进入递减序列判断,count++,i++直到下一个值小于ar[i]或者到达最后一个元素位置了
- 若ar[i]==ar[i+1]则 i ++
代码:
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n; cin >> n;
vector<int> ar;
ar.resize(n);
for (int& i : ar)
cin >> i;
int res = 0;
int i = 0;
while (i < n)
{
if (ar[i] < ar[i + 1])
{
while (i < n - 1 && ar[i] <= ar[i + 1]) //这里一定是<=,如果遇到等于也跳过
i++;
res++;
i++; //这里就是为什么不会越界,在查找完一次子序列之后,i++两次指向子序列下一个元素。
}
else if (ar[i] > ar[i + 1])
{
while (i < n - 1 && ar[i] >= ar[i + 1])
i++;
res++;
i++;
}
else
i++; //如果第一个数就是和下一个相等则
}
cout << res << endl;
return 0;
}
4.倒置字符串(双指针切片)
解题思路:
- 双指针切片,从字符串的最后面开始往前遍历,每统计出一个字符串则切片插入
- 接收字符串时切片,利用cin接收到空格结束的特性,把每一片拼接起来
代码:
1.
#include <iostream>
#include <string>
using namespace std;
int main()
{
string ar;
getline(cin, ar);
string res;
int left = ar.size() - 1;
int right = left;
while (left >= 0)
{
while (left >= 0 && ar[left] != ' ')
left--;
res += ar.substr(left + 1, right - left);
if (left >= 0)
res += ' ';
left--;
right = left;
}
cout << res << endl;
return 0;
}
2.
#include <iostream>
#include <string>
using namespace std;
// cin读取string时自动会被空格分隔开,用另一个字符串存储进行逆序输出
int main()
{
string s1, s2;
cin >> s2;
while (cin >> s1)
s2 = s1 + " " + s2;
cout << s2 << endl;
return 0;
}
5.字符串中找出连续最长的数字串(dp)
解题思路:
1.遍历字符串str
,用两个字符串cur
和res
保存数字串,cur
保存当前统计到的数字串,res
保存每次统计的最长数字串。
代码实现:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string res, cur, str;
cin >> str;
int i = 0;
while (i < str.size())
{
while (i < str.size() && str[i] >= '0' && str[i] <= '9')
cur.push_back(str[i++]);
if (cur.size() > res.size())
res = cur;
if (cur.size() != 0)
cur.clear();
i++;
}
cout << res << endl;
return 0;
}
6.数组中出现次数超过一半的数字(dp)
解题思路:
- 数组排序后,如果符合条件的数存在,则一定是数组中间那个数。这种方法虽然容易理解,但由于涉及到快排sort,其时间复杂度为O(NlogN)并非最优;
- 候选人,遍历数组,用
res
统计数字出现最多的次数,count
统计出现的次数。历下一个数字时,若它与之前保存的数字相同,则次数加1,否则次数减1;若次数为0,则保存下一个数字,并将次数置为1。遍历结束后,所保存的数字即为所求。然后再判断它是否符合条件即可
代码实现:
class Solution {
public:
int MoreThanHalfNum_Solution(vector<int> numbers)
{
int res;
int count = 0;
for (int i : numbers)
{
if (count == 0)
{
res= i;
count++;
}
else if (i == res)
count++;
else
count--;
}
count = 0;
for (int i : numbers)
if (i == res)
count++;
if (count > numbers.size() / 2)
return res;
return 0;
}
};
7.计算糖果
解题思路:
这道题的本质就是:判断三元一次方程是否有解及求解
代码:
#include<iostream>
using namespace std;
int main()
{
int AB_ = 0;
int BC_= 0;
int AB = 0;
int BC = 0;
cin >> AB_ >> BC_ >> AB >> BC;
int a = (AB_ + AB) / 2;
int c = (BC - BC_) / 2;
int b1 = (BC_ + BC) / 2;
int b2 = (AB - AB_) / 2;
if (b1 != b2) //这道题核心就是检查b的值是否正确
cout << "No" << endl;
else
cout << a << ' ' << b1 << ' ' << c << endl;
return 0;
}
8.进制转换(table表的利用)
解题思路:
N进制数,每个进制位的值分别是X0*N^0,X1*N^1, X2*N^2
,X0,X1,X2
就是这些进制位的值,就是就是进行取模余数就是当前低进制的位的值是多少,通过除掉进制数,进入下一个进制位的计算。
代码:
#include <iostream>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
string s, table = "0123456789ABCDEF";
int m, n;
cin >> m >> n;
bool flag = false;
// 如果是负数,则转成正数,并标记一下
if (m < 0)
{
m = 0 - m;
flag = true;
}
// 按进制换算成对应的字符添加到s
while (m)
{
s += table[m % n];
m /= n;
}
if (flag)
s += '-';
reverse(s.begin(), s.end());
cout << s << endl;
return 0;
}
9.统计回文(双指针)
#include<iostream>
#include<string>
using namespace std;
bool isbackstring(string& ar)
{
int left = 0;
int right = ar.size() - 1;
while (left < right)
{
if (ar[left] != ar[right])
return false;
left++;
right--;
}
return true;
}
int main()
{
string a, b;
cin >> a >> b;
int count = 0;
for (int i = 0; i <= a.size(); i++)
{
string c(a);
c.insert(i, b);
if (isbackstring(c))
count++;
}
cout << count << endl;
return 0;
}
10.连续最大和(dp)
#include<iostream>
#include<vector>
using namespace std;
int main()
{
int num;
cin >> num;
vector<int> vc(num, 0);
for (int i = 0; i < num; i++)
cin >> vc[i];
int res = vc[0];
int tmp;
for (int i : vc)
{
tmp += i;
tmp = max(tmp, i);
res = max(res, tmp);
}
cout << res << endl;
return 0;
}
11.把字符串转换成整数(细节题)
class Solution {
public:
int StrToInt(string str)
{
if(str.size() == 0)
return 0;
int flag = 1;
int i = 0;
if(str[i] == '+' || str[i] == '-')
{
if(str[i] == '-')
flag = -1;
i++;
}
int sz = str.size();
int res = 0;
while(i < sz)
{
if(str[i] < '0' || str[i] > '9')
return 0;
res = res * 10 + (str[i] - '0');
i++;
}
return res * flag;
}
};
12.不要二(干就完了)
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int w, h;
cin >> w >> h;
vector<vector<int>> board(w, vector<int>(h, 1));
int res = 0;
for(int i = 0; i < w; i++)
{
for(int j = 0; j < h; j++)
{
if(board[i][j] == 1)
{
if(j + 2 < h)
board[i][j + 2] = 0;
if(i + 2 < w)
board[i + 2][j] = 0;
res++;
}
}
}
cout << res << endl;
return 0;
}
13.合法括号序列(栈的使用)
class Parenthesis {
public:
bool chkParenthesis(string A, int n)
{
// write code here
stack<char> stc;
for(auto i : A)
{
if(i == '(')
stc.push(i);
else if(i == ')')
{
if(stc.empty())
return false;
stc.pop();
}
else
return false;
}
return stc.empty();
}
};
14.Fibonacci数列(dp)
#include <iostream>
#include <cmath>
using namespace std;
int main()
{
int n;
cin >> n;
int f1 = 0, f2 = 1;
int tmp;
//0 1 1 2 3 5
while(f2 < n)
{
tmp = f1;
f1 = f2;
f2 = tmp + f1;
}
cout << min(abs(n - f1), abs(f2 - n)) << endl;
return 0;
}
15.两种排序方法(运算符重载)
#include <iostream>
#include <string>
#include <vector>
void isSort(vector<string>& vec, bool& fg1, bool& fg2)
{
for(int i = 0; i < vec.size() - 1; i++)
{
if(vec[i] > vec[i + 1])
fg1 = false;
if((vec[i]).size() > (vec[i + 1]).size())
fg2 = false;
if(!fg1 && !fg2)
break;
}
}
int main()
{
int n;
cin >> n;
vector<string> vec(n);
for(auto& str : vec)
{
cin >> str;
}
bool fg1 = true, fg2 = true;
isSort(vec, fg1, fg2);
if(fg1 && fg2)
cout << "both" << endl;
else if(fg1)
cout << "lexicographically" << endl;
else if(fg2)
cout << "lengths" << endl;
else
cout << "none" << endl;
return 0;
}
15.最小公倍数(两种公约数求法)
#include <iostream>
using namespace std;
int Mindiv(int m, int n)
{
// 1.辗转相除法
// int mod;
// while(mod = m % n)
// {
// m = n;
// n = mod;
// }
// return n;
// 2.更相减损法
while(m != n)
{
if(m > n)
m = m - n;
else
n = n - m;
}
return m;
return 0;
}
int main()
{
int num1, num2;
cin >> num1 >> num2;
cout << num1 * num2 / Mindiv(num1, num2) << endl;
return 0;
}
16.走方格的方案数(dp)
递归:board[i][j] = board[i - 1][j] + board[i][j - 1]
如果 i 或者 j == 0 说明到达边界,边界的走法都是 1
#include <iostream>
using namespace std;
int WayToTar(int row, int col)
{
if(row == 0 || col == 0)
return 1;
return WayToTar(row - 1, col) + WayToTar(row, col - 1);
}
int main()
{
int row, col;
while(cin >> row >> col)
{
cout << WayToTar(row, col) << endl;
}
return 0;
}
17.另类加法(位运算)
1.不进位加法:a ^ b
2.只进位加法:(a & b) << 1
3.一直循环 不进位加法 和 进位加法 ,直到进位为 0
class UnusualAdd {
public:
int addAB(int A, int B)
{
// write code here
//1.先不进位相加^
//2.再只进位相加&<<1
//3.只要进位为0则循环结束
while(B != 0)
{
int car = A ^ B;
B = (A & B) << 1;
A = car;
}
return A;
}
};
18. 井字棋(干就完了)
class Board {
public:
bool checkWon(vector<vector<int> > board)
{
// write code here
// 这个题没有捷径就是每个位置都检查一次
int row = board.size();
//检查每一行
int i;
for(i = 0; i < row; i++)
{
if(board[i][0] + board[i][1] + board[i][2] == row)
return true;
}
//检查每一列
for(i = 0; i < row; i++)
{
if(board[0][i] + board[1][i] + board[2][i] == row)
return true;
}
//检查对角线
if(board[0][0] + board[1][1] + board[2][2] == row || board[0][2] + board[1][1] + board[2][0] == row)
return true;
return false;
}
};
19. 最近公共祖先(节点下标)
class LCA {
public:
int getLCA(int a, int b)
{
// write code here
while(a != b)
{
if(a > b)
a /= 2;
else
b /= 2;
}
return a;
}
};
20. 求最大连续bit数(位运算)
#include <iostream>
using namespace std;
int main()
{
int num;
while(cin >> num)
{
int res = 0;
int count = 0;
while(num)
{
if(num & 1) //如果num最后bit为1
{
count++;
res = max(res, count);
}
else
count = 0;
num >>= 1;
}
cout << res << endl;
}
return 0;
}
21.二进制插入 -》(位运算)
1. 这里保证了 i-j+1 必定是 0
class BinInsert {
public:
int binInsert(int n, int m, int j, int i)
{
// write code here
return n | m << j;
}
};
2. 如果不保证 i-j+1 为 0
class BinInsert {
public:
int binInsert(int n, int m, int j, int i)
{
// write code here
int tmp = m;
int setZero = 0;
while(tmp)
{
setZero <<= 1;
setZero |= 1;
tmp >>= 1;
}
for(; tmp < j; tmp++)
{
setZero <<= 1;
m <<= 1;
}
return n & (~setZero) | m;
}
};
22.组成偶数最近的素数 -》(质数的求法)
#include <iostream>
#include <algorithm>
using namespace std;
bool isPrm(int tar)
{
int tmp = sqrt(tar);
for (int i = 2; i <= tmp; i++)
{
if(tar % i == 0)
return false;
}
return true;
}
int main()
{
int n;
while (cin >> n)
{
for(int i = n / 2; i > 0; --i)
{
if(isPrm(i) && isPrm(n - i))
{
cout << i << endl << n - i << endl;
break;
}
}
}
return 0;
}
23.参数解析(遍历)
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main()
{
string str;
getline(cin, str);
vector<string> vec;
string tmp;
for(int i = 0; i < str.size(); i++)
{
if(str[i] != ' ' && str[i] != '"')
tmp.push_back(str[i]);
else
{
if(str[i] == ' ' && !tmp.empty())
vec.push_back(tmp);
else
{
i++;
while(i < str.size() && str[i] != '"')
{
tmp.push_back(str[i]);
i++;
}
i++;
vec.push_back(tmp);
}
tmp.clear();
}
}
if(!tmp.empty())
vec.push_back(tmp);
cout << vec.size() << endl;
for(auto it : vec)
cout << it << endl;
return 0;
}
24.跳石板(dp)
解题:找到状态方程:dp[i + p] = min(dp[i] + 1, dp[i + p])
意思是:dp[i + p] 位置的值等于dp[i] 的值再跳一步。其中 p 是 i 的一个约数。如果dp[i + p] 为 0 ,则dp[i + p] = dp[i] + 1
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main()
{
int N, M;
cin >> N >> M;
vector<int> dp(M + 1, 0);
dp[N] = 1;
for(int i = N; i < M; i++)
{
if(dp[i] == 0) //如果当前石板为0,则说明不可能从该跳板往后跳
continue;
for(int j = 2; j <= sqrt(i); j++)
{
if(i % j == 0) // 如果是约数则进行
{
int num1 = i + j; // 约数中较小数
int num2 = i + i / j; // 约数中较大数
if(num1 > M) // 若较小数都大于M则直接跳出
break;
if(dp[num1] == 0)
dp[num1] = dp[i] + 1;
else
dp[num1] = min(dp[num1], dp[i] + 1);
if(num2 <= M)
{
if(dp[num2] == 0)
dp[num2] = dp[i] + 1;
else
dp[num2] = min(dp[num2], dp[i] + 1);
}
}
}
}
cout << dp[M] - 1 << endl;
return 0;
}
25.计算日期到天数转换(做就完了)
#include <iostream>
using namespace std;
bool isLeapYear(int year)
{
return (year % 4 == 0 && year % 100 != 0 || year % 400 == 0);
}
int main()
{
int board[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
int y, m, d;
while(cin >> y >> m >> d)
{
int res = 0;
res += board[m - 1];
res += d;
if(isLeapYear(y) && m > 2)
res += 1;
cout << res << endl;
}
return 0;
}
26.幸运的袋子(回溯+组合)
https://www.nowcoder.com/practice/a5190a7c3ec045ce9273beebdfe029ee?tpId=85&&tqId=29839&rp=1&ru=/activity/oj&qru=/ta/2017test/question-ranking
题解:组合问题的通用解法:枚举每个节点的组合,只要符合条件结果++,不满足则跳出循环。在枚举下一个节点之前,应该进行剪枝:防止重复节点
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int LuckPacket(vector<int>& vec, int pos, int sum, int mul)
{
int count = 0;
// 每一个位置上的组合都要求一次
for(int i = pos; i < vec.size(); i++)
{
sum += vec[i];
mul *= vec[i];
if(sum > mul)
count += 1 + LuckPacket(vec, i + 1, sum, mul);
else if(vec[i] == 1)
count = LuckPacket(vec, i + 1, sum, mul);
else
break;
// 剪枝,防止重复的组合
while(i < vec.size() - 1 && vec[i] == vec[i + 1])
i++;
// 进行下一个组合时,减去当前的值
// 这里每一次循环相当于把一个值的每种组合都试一次,然后去掉当前节点,去试下一个节点的值的各种组合
// 例如,1123。先把1的所有组合试一遍:1123,12,13,之后再试2节点
sum -= vec[i];
mul /= vec[i];
}
return count;
}
int main()
{
int n;
cin >> n;
vector<int> vec(n);
for(int& i : vec)
cin >> i;
sort(vec.begin(), vec.end());
cout << LuckPacket(vec, 0, 0, 1) << endl;
return 0;
}
27.二进制中1的个数(位运算)
#include <iostream>
using namespace std;
int CotOne(int n)
{
int res = 0;
while (n)
{
res++;
n = n & (n - 1);
}
return res;
}
int main()
{
int n;
while (cin >> n)
{
cout << CotOne(n) << endl;
}
return 0;
}
28.手套(数学)
https://www.nowcoder.com/practice/365d5722fff640a0b6684391153e58d8?tpId=49&&tqId=29337&rp=1&ru=/activity/oj&qru=/ta/2016test/question-ranking
题解:模拟一下找手套的过程然后总结方法
class Gloves {
public:
int findMinimum(int n, vector<int> left, vector<int> right)
{
// write code here
// 1.当左右手套其中为0时,另一只的一定要拿
// 2.因此只需要统计每只手套中不为0的手套数量,再减去最小的数
int l_sum = 0, l_min = INT_MAX;
int r_sum = 0, r_min = INT_MAX;
int sum = 0;
for (int i = 0; i < n; i++)
{
if (left[i] * right[i] == 0)
sum += left[i] + right[i];
else
{
l_sum += left[i];
r_sum += right[i];
l_min = min(left[i], l_min);
r_min = min(right[i], r_min);
}
}
return sum + min(l_sum + 1 - l_min, r_sum + 1 - r_min) + 1;
}
};
29.完全数计算(做就行了)
#include <iostream>
#include <algorithm>
using namespace std;
bool isPernum(int tar)
{
int count = 1;
for (int i = 2; i <= sqrt(tar); i++)
{
if (tar % i == 0)
{
if (i != sqrt(tar))
count = count + tar / i + i;
else
count += i;
if (count > tar)
return false;
}
}
return count == tar;
}
int CotpNum(int n)
{
int res = 0;
for (int i = 2; i < n; i++)
{
if (isPernum(i))
res++;
}
return res;
}
int main()
{
int n;
while (cin >> n)
{
cout << CotpNum(n) << endl;
}
return 0;
}
30.扑克牌大小(find、count的使用)
- 分六种牌型:单牌,对子,三个,炸弹,顺子,王炸,可以看到每种牌型的空格数都不同
- 先判断有没有王炸,王炸大于任何牌
- 再分空格数是否相等,如果不相等且没有炸弹则返回ERROR
- 其次就是掌握string的find方法和算法中的count方法,find找到则返回下标,没找到返回-1
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main()
{
string poke;
while (getline(cin, poke))
{
if (poke.find("joker JOKER") != -1) // string.find 没有找到返回-1
{
cout << "joker JOKER" << endl;
continue;
}
int pos = poke.find('-');
string poke1 = poke.substr(0, pos);
string poke2 = poke.substr(pos + 1);
int space1 = count(poke1.begin(), poke1.end(), ' ');
int space2 = count(poke2.begin(), poke2.end(), ' ');
if (space1 != space2)
{
if (space1 == 3)
cout << poke1 << endl;
else if (space1 == 3)
cout << poke2 << endl;
else
cout << "ERROR" << endl;
}
else
{
// 比较第一张牌的大小
string board = "345678910JQKA2jokerJOKER";
if (board.find(poke1[0]) > board.find(poke2[0]))
cout << poke1 << endl;
else
cout << poke2 << endl;
}
}
return 0;
}
31.杨辉三角变形(滚动数组)
https://www.nowcoder.com/practice/8ef655edf42d4e08b44be4d777edbf43?tpId=37&&tqId=21276&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking
题解:每一行只和他的上一行有关系,因此只需要通过上一行的数据计算当前行
#include <iostream>
#include <vector>
using namespace std;
int OddPos(int n)
{
vector<int> board(2 * n - 1, 0);
board[0] = 1;
for (int i = 2; i <= n; i++)
{
for (int j = 1; j < 2 * i - 1; j++)
{
board[j] = board[j - 1] + board[j];
if (i == n && board[j] % 2 == 0)
{
return j + 1;
}
}
}
return -1;
}
int main()
{
int n;
while (cin >> n)
{
cout << OddPos(n) << endl;
}
return 0;
}
32.超长正整数相加(大数相加)
题解:
- 模拟加法,从双数的最低位开始,每一位先相加,统计进位和取模后的答案,最后反转字符串
- 若最后都相加完毕,而进位不为零,则插入1
- 方法二:先设置有效元素为
max(s1.size, s2.size()) + 1
,从后往前赋值,最后判断第一位是不是0,是0则删除
#include <iostream>
#include <string>
using namespace std;
string addSum(string& s1, string& s2)
{
string res; // 和
int i = s1.size() - 1; // 标识s1的位置
int j = s2.size() - 1; // 标识s2的位置
int car = 0; // 进位
while (i >= 0 || j >= 0)
{
if (i >= 0)
car += s1[i] - '0';
if (j >= 0)
car += s2[j] - '0';
res.push_back(car % 10 + '0');
car /= 10;
i--;
j--;
}
if (car)
res += '1';
reverse(res.begin(), res.end());
return res;
}
int main()
{
string s1, s2;
while (cin >> s1 >> s2)
{
cout << addSum(s1, s2) << endl;
}
return 0;
}
33.统计每个月兔子的总数(fib的变形)
https://www.nowcoder.com/practice/1221ec77125d4370833fd3ad5ba72395?tpId=37&&tqId=21260&rp=1&ru=/activity/oj&qru=/ta/huawei/question-ranking
题解:设一个月的兔子总数为f(n),则f(n) = f(n - 1) + f(n - 2),f(n)表示上个月兔子总数,f(n - 2)表示上上个月生产的兔子,也就是当前可以进行生产的兔子总数
#include <iostream>
using namespace std;
// f(n) = f(n - 1) + f(n - 2);
int RitCount(int mounth)
{
if (mounth < 3)
return 1;
// dp[0]:代表下个月可生产
// dp[1]:代表可生产
int res;
int dp[2] = { 1, 1 };
for (int i = 3; i <= mounth; i++)
{
res = dp[0] + dp[1];
dp[0] = dp[1];
dp[1] = res;
}
return res;
}
int main()
{
int mounth;
while (cin >> mounth)
{
cout << RitCount(mounth) << endl;
}
return 0;
}
34.字符串通配符(递归)
- 当两位置的字符相同或者str1为 ‘?’ 时,则继续往后检测
- 当两位置不同并且,str1为 ‘*’ 则分三种情况 1.匹配0个字符 2.匹配1个字符 3.匹配多个字符,只要三种情况有一种为真,则返回真
- 如果位置不同,且不为 ‘?’ 和 ‘*’ 则返回false
#include <iostream>
#include <string>
using namespace std;
bool CheckSame(const char* str1, const char* str2)
{
if (*str1 == '\0' && *str2 == '\0')
return true;
if (*str1 == '\0' || *str2 == '\0')
return false;
if (*str1 == *str2 || *str1 == '?')
{
return CheckSame(str1 + 1, str2 + 1);
}
if (*str1 == '*')
{
return CheckSame(str1 + 1, str2) || CheckSame(str1 + 1, str2 + 1) || CheckSame(str1, str2 + 1);
}
return false;
}
int main()
{
string str1, str2;
while (cin >> str1 >> str2)
{
if (CheckSame(str1.c_str(), str2.c_str()))
cout << "true" << endl;
else
cout << "false" << endl;
}
return 0;
}