小易的升级之路
思路:
本题的能力值的累加分两种情况,一种是直接相加bi,一种是累加当前能力值于bi的最大公约数。最大公约数可以通过碾转相除法求得:a与b的最大公约数相当于b与a,b余数的最大公约数。如果求余结果为0, 则b为所求结果。
代码:
#include<iostream>
#include<vector>
using namespace std;
// //辗转相除法
// int GCD(int a, int b) {
// int c;
// while (c = a % b) {
// a = b;
// b = c;
// }
// return b;
// }
//直接计算
int gcd(int a, int ev) {
int min = a > ev ? ev : a;
int gcd;
for (int i = min; i >= 1; i--) {
if (a % i == 0 && ev % i == 0) {
gcd = i;
break;
}
}
return gcd;
}
int main() {
int n, a;
while (cin >> n >> a) {
vector<int> v(n);
for (int i = 0; i < n; i++) {
cin >> v[i];
}
for (auto ev : v) {
if (ev <= a) {
a += ev;
} else {
a += gcd(a, ev);
}
}
cout << a << endl;
}
return 0;
}
找出字符串中第一个只出现一次的字符
思路:
- 用一个数组的每一个位置表示对应的位置。对应的字符位置存放字符出现的次数。统计完之后,遍历输入字符,遇到第一个只出现一次的字符就停止。
- 也可以用一个map来记录字符串中字符出现的次数,然后遍历字符串,直到找到第一个只出现一次的字符为止。
代码:
#include<iostream>
#include<string>
#include<map>
using namespace std;
int main() {
string str;
cin >> str;
map<char, int> countmap;
for (auto& s : str) {
countmap[s]++;
}
int flag = 1;
for (auto& s : str) {
if (countmap[s] == 1) {
cout << s;
flag = 0;
return 0;
}
}
cout << -1;
return 0;
}
微信红包
思路:
本题两种思路,第一种排序思路,如果一个数出现次数超过一半了,排序过后,必然排在中间,则最后遍历整个数组查看是否符合即可。第二种思路可以用map统计每个数字出现的次数,最后判断有没有超过一半的数字。
代码:
class Gift {
public:
int getValue(vector<int> gifts, int n) {
// write code here
map<int, int> countMap;
for (auto v : gifts) {
countMap[v]++;
}
int ret = 0;
for (auto m : countMap) {
if ((m.second * 2) > n) {
ret = m.first;
}
}
return ret;
}
};
计算字符串的编辑距离
思路:
状态:
子状态:word1的前1,2,3,…m个字符转换成word2的前1,2,3,…n个字符需要的编辑距离
F(i,j):word1的前i个字符于word2的前j个字符的编辑距离
状态递推: F(i,j) = min { F(i-1,j)+1, F(i,j-1) +1, F(i-1,j-1) +(w1[i]==w2[j]?0:1) }
上式表示从删除,增加和替换操作中选择一个最小操作数
F(i-1,j): w1[1,…,i-1]于w2[1,…,j]的编辑距离,删除w1[i]的字符—>F(i,j)
F(i,j-1): w1[1,…,i]于w2[1,…,j-1]的编辑距离,增加一个字符—>F(i,j)
F(i-1,j-1): w1[1,…,i-1]于w2[1,…,j-1]的编辑距离,如果w1[i]与w2[j]相同, 不做任何操作,编辑距离不变,如果w1[i]与w2[j]不同,替换w1[i]的字符为w2[j]—>F(i,j)
初始化: 初始化一定要是确定的值,如果这里不加入空串,初始值无法确定 F(i,0) = i :word与空串的编辑距离,删除操作
F(0,i) = i :空串与word的编辑距离,增加操作
返回结果:F(m,n)
其实自己看这些东西也很是头大,那么直接通俗来说解题步骤吧。
-
先初始化一个二维数组,注意这里行和列都需要多开一个,
-
然后把第0行和0列,依次从0开始往后赋值
- 然后根据递推方程,依次计算两个字符串相差的距离,其实对角线的最后一个就是所求结果。
代码:
#include<iostream>
#include<string>
#include<vector>
using namespace std;
int main() {
string str1, str2;
getline(cin, str1);
getline(cin, str2);
int size1 = str1.size();
int size2 = str2.size();
//行和列都多开一个空间
vector<vector<int>> vv(size1 + 1, vector<int>(size2 + 1, 0));
//s1初始化
for (int i = 1; i <= size1; i++) {
vv[i][0] = i;
}
//s2初始化
for (int j = 1; j <= size2; j++) {
vv[0][j] = j;
}
for (int i = 1; i <= size1; i++) {
for (int j = 1; j <= size2; j++) {
if (str1[i-1] != str2[j-1]) {
vv[i][j] = 1 + min(vv[i - 1][j], vv[i][j - 1]);
vv[i][j] = min(vv[i][j], 1 + vv[i - 1][j - 1]);
} else {
vv[i][j] = 1 + min(vv[i - 1][j], vv[i][j - 1]);
vv[i][j] = min(vv[i][j], vv[i - 1][j - 1]);
}
}
}
cout<<vv[size1][size2];
return 0;
}
end