目录
前言
跟着英雄哥打卡第二十七天
[专题跳转->《算法零基础100讲》]
[万人千题社区跳转]
一、千位分隔数
跳转力扣:1556. 千位分隔数
难度:★☆☆☆☆
说明:首先获取数字的长度(可用转换字符串求长度偷懒,也可以先循环求出),从后面往前数,每3个数加一个小数点,加小数点的时候注意前面还有没有数,用当前数n即可判断
代码如下(示例):
class Solution {
public:
string thousandSeparator(int n) {
if (n == 0) return "0";
int t = to_string(n).size();
string res;
int cnt = 0;
while (n) {
res += to_string(n % 10);
n /= 10;
cnt ++;
if (!(cnt % 3) && n) { // 插入'.'的时候需要特殊判断
res += '.';
}
}
reverse(res.begin(), res.end()); // 由于是从后往前进行插入,
// 最后要转回来
return res;
}
};
二、字符串转化后的各位数字之和
跳转力扣:1945. 字符串转化后的各位数字之和
难度:★☆☆☆☆
说明:循环求得字母转为对应数字后的字符串【将"abc"转换为"123"】,后进行k次循环操作,将各位数相加,得出结果
代码如下(示例):
class Solution {
public:
int getLucky(string s, int k) {
string t;
for (int i = 0; i < s.size(); i ++) {
t += to_string(s[i] - 'a' + 1); // 'a' -> '1'
}
int sum;
while (k --) {
sum = 0;
for (int i = 0; i < t.size(); i ++) { '11' -> 11
sum += t[i] - '0';
}
t = to_string(sum);
}
return sum;
}
};
三、字符串中第二大的数字
跳转力扣:1796. 字符串中第二大的数字
难度:★☆☆☆☆
说明:进行排序去重操作,以便确认能不能找到第二大的数,从小到大遍历找到第二大的数即可,注意字符与数字之间的转换,以及可以用isdigit()函数筛选数字,最后返回第二大数_2,不需要对是否能找到第二大数进行特殊判断,原因是一开始对第一第二大的数已经赋值为-1
代码如下(示例):
class Solution {
public:
int secondHighest(string s) {
int _1 = -1, _2 = -1;
// 排序+去重
sort(s.begin(), s.end());
s.erase(unique(s.begin(), s.end()), s.end());
for (int i = 0; i < s.size(); i ++) { // 查找第二大值_2
if (isdigit(s[i]) && s[i] - '0' > _1) {
_2 = _1;
_1 = s[i] - '0';
}
else if(isdigit(s[i]) && s[i] - '0' > _2) {
_2 = s[i] - '0';
}
}
return _2;
}
};
三、最小时间差
跳转力扣:539. 最小时间差
难度:★☆☆☆☆
说明:minute()函数:求得该时间的分钟数;排序后循环遍历相邻两个数值的差值理论上最小值,用minn值维护,另外由于时间循环的特殊性,需要对最小与最大值的差值做特殊判断,找到最小值
代码如下(示例):
class Solution {
public:
int minute(string s) {
return (s[0] - '0') * 600 + (s[1] - '0') * 60 + (s[3] - '0') * 10 + (s[4] - '0');
}
int findMinDifference(vector<string>& timePoints) {
if (timePoints.size() > 1440) // 24*60=1440
return 0; // 若大于该数则必有重复
vector<int> time(timePoints.size()); // 记录分钟数的数组
for (int i = 0; i < timePoints.size(); i ++) {
time[i] = minute(timePoints[i]);
}
sort(time.begin(), time.end());
int minn = INT_MAX;
for (int i = 1; i < time.size(); i ++) {
minn = min(minn, time[i] - time[i - 1]);
if (minn == 0)
return 0;
}
// 由时间循环性,需要对最后一个数据进行特殊判断
return min(minn, 1440 + time[0] - time[time.size() - 1]);
}
};
四、罗马数字转整数
跳转力扣:13. 罗马数字转整数
难度:★★☆☆☆
说明:dict哈希表存储罗马数字对应数值,从左往右判断对应罗马数字是否小于下一位的罗马数字,若小于则减去罗马数字对应数值,若大于则加上对应数值(惊奇的发现在if判断语句加上i < s.size() - 1 后执行用时少些许,最后一位一定是加)
代码如下(示例):
class Solution {
public:
int romanToInt(string s) {
unordered_map<char, int> dict{{'I', 1}, {'V', 5}, {'X', 10}, {'L', 50}, {'C', 100}, {'D', 500}, {'M', 1000}};
int ans = 0;
for (int i = 0; i < s.size(); i ++) {
if (i < s.size() - 1 && dict[s[i]] < dict[s[i + 1]]) { // 左减
ans -= dict[s[i]];
}
else ans += dict[s[i]]; // 右加
}
return ans;
}
};
六、整数转罗马数字
跳转力扣:12. 整数转罗马数字
难度:★★☆☆☆
说明:先用pair从大到小存储可能的罗马数字组合体,循环遍历数组找到大于该罗马值的数,即可减去该罗马数字对应的数值,同时将该罗马值加入到答案中,直至num减到0即表示结束
代码如下(示例):
pair<int, string> dict[] = {
{1000, "M"}, {900, "CM"}, {500, "D"}, {400, "CD"},
{100, "C"}, {90, "XC"}, {50, "L"}, {40, "XL"},
{10, "X"}, {9, "IX"}, {5, "V"}, {4, "IV"},
{1, "I"}};
class Solution {
public:
string intToRoman(int num) {
string ans;
for (auto p: dict) {
while (num >= p.first) { // 找到大于罗马组合体的数
num -= p.first;
ans += p.second;
}
if (num == 0) {
break;
}
}
return ans;
}
};
七、字符串压缩
跳转力扣:面试题 01.06. 字符串压缩
难度:★★☆☆☆
说明:从前往后遍历,若当前字符与下一个字符不同时,则压缩,压缩后计数记得初始化,若相同则计数+1,直至与下一个不相同进行压缩
代码如下(示例):
class Solution {
public:
string compressString(string s) {
string ans;
int cnt = 1;
for (int i = 0; i < s.size(); i ++) {
if (s[i] != s[i + 1]) { // 压缩
ans += s[i];
ans += to_string(cnt);
cnt = 1;
}
else cnt ++;
}
return ans.size() < s.size() ? ans: s;
}
};
八、字符串相加
跳转力扣:415. 字符串相加
难度:★★★☆☆
说明:大数相加模板如下:为方便进位计算,从小位开始相加,可先将加数逆转后再从左往右相加,最后记得再反转回来
代码如下(示例):
class Solution {
public:
string addStrings(string num1, string num2) {
reverse(num1.begin(), num1.end());
reverse(num2.begin(), num2.end());
string num3;
int t = 0;
for (int i = 0; i < num1.size() || i < num2.size(); i ++) {
if (i < num1.size()) t += num1[i] - '0';
if (i < num2.size()) t += num2[i] - '0';
num3 += t % 10 + '0';
t /= 10;
}
if (t) num3 += t % 10 + '0';
reverse(num3.begin(), num3.end());
return num3;
}
};
九、二进制求和
跳转力扣:67. 二进制求和
难度:★★★☆☆
说明:与上体相似,套模板类比即可
代码如下(示例):
class Solution {
public:
string addBinary(string num1, string num2) {
reverse(num1.begin(), num1.end());
reverse(num2.begin(), num2.end());
string num3;
int t = 0;
for (int i = 0; i < num1.size() || i < num2.size(); i ++) {
if (i < num1.size()) t += num1[i] - '0';
if (i < num2.size()) t += num2[i] - '0';
num3 += t % 2 + '0';
t /= 2;
}
if (t) num3 += t % 2 + '0';
reverse(num3.begin(), num3.end());
return num3;
}
};
十、检查某单词是否等于两单词之和
跳转力扣:1880. 检查某单词是否等于两单词之和
难度:★★★☆☆
说明:将’a’转换为’0’:‘a’-‘a’+‘0’==‘0’
代码如下(示例):
class Solution {
public:
int stoiPlus(string s) {
string res;
for (int i = 0; i < s.size(); i ++) {
res += s[i] - 'a' + '0'; // 'a' -> '0'
}
return stoi(res);
}
bool isSumEqual(string firstWord, string secondWord, string targetWord) {
return stoiPlus(firstWord) + stoiPlus(secondWord) == stoiPlus(targetWord);
}
};
十一、字符串相乘
跳转力扣:43. 字符串相乘
难度:★★★☆☆
说明:num1从右往左的每一位分别乘num2从右往左的每一位,例如先取出num2最后一位k1,然后num1从右往左遍历每一位,与k相乘的结果记录在cur字符串中,遍历完后可得到num1与k相乘的结果,然后取出num2倒数第二位k2,再与num1从右往左每一位相乘,得到的新的cur与上一位相乘结果cur相加,直至遍历到num2第一位,其间一直累加cur得到最后所求结果num3
代码如下(示例):
class Solution {
public:
string multiply(string num1, string num2) {
string num3 = "0";
reverse(num1.begin(), num1.end());
reverse(num2.begin(), num2.end());
for (int i = 0; i < num2.size(); i ++) {
string cur = "";
int k = num2[i] - '0';
for (int j = 0; j < i; j ++) cur += '0';
for (int j = 0, t = 0; j < num1.size() || t; j ++) {
if (j < num1.size()) t += (num1[j] - '0') * k;
cur += t % 10 + '0';
t /= 10;
}
reverse(cur.begin(), cur.end());
while (cur.back() == 0 && cur.size() > 1) cur.pop_back();
num3 = add(num3, cur);
}
// 比较笨的删除前置零的方法
reverse(num3.begin(), num3.end());
while (num3.back() == '0' && num3.size() > 1) num3.pop_back();
reverse(num3.begin(), num3.end());
return num3;
}
// 大数相加模板
string add(string num1, string num2) {
reverse(num1.begin(), num1.end());
reverse(num2.begin(), num2.end());
string num3;
int t = 0;
for (int i = 0; i < num1.size() || i < num2.size(); i ++) {
if (i < num1.size()) t += num1[i] - '0';
if (i < num2.size()) t += num2[i] - '0';
num3 += t % 10 + '0';
t /= 10;
}
if (t) num3 += t % 10 + '0';
reverse(num3.begin(), num3.end());
return num3;
}
};
十二、整数转换英文表示
跳转力扣:273. 整数转换英文表示
难度:★★★☆☆
说明:很特别的一道题,建议直接跳转官方解答!
【官方】整数转换英文表示