C++刷题 - 7.23
1. 比特翻转
#include <vector>
#include <iostream>using namespace std;// tag = 1
int solution(int tag, vector<int> nums)
{// 滑动窗口int ret = 0;int count = 0; // !tag的数量for (int left = 0, right = 0; right < nums.size(); right++){if(nums[right]!=tag) count++; // 进窗口while(count>1) // 判断{if(nums[left]!=tag) count--;left++; // 出窗口}ret = max(ret,right-left+1); // 更新大小}return ret;
}int main()
{vector<int> nums{0,1,1,0,1,0,1,0,0};cout<<solution(1,nums);
}
我们需要找到数组中最长的连续子数组,其中最多只能有一个元素与 tag
(这里是 1
)不同。换句话说,你可以将子数组中的一个 非tag
元素改为 tag
,使得该子数组全部由 tag
组成,并找出这样的最长子数组的长度。
这是一个典型的滑动窗口问题,可以用以下步骤解决:
滑动窗口维护:用
left
和right
指针表示当前窗口的左右边界。统计非
tag
的数量:窗口中最多只能有一个非tag
元素(因为可以修改一个元素)。窗口收缩条件:当窗口中非
tag
的数量超过1
时,移动left
指针以缩小窗口。更新最大长度:每次窗口合法时(非
tag
数量 ≤1
),计算窗口长度并更新最大值。
2. 抽取TOP3数字
#include <vector>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;// tag = 1
vector<int> solution(string strs)
{vector<int> ret;for(int i=0;i<strs.size();i++){int tem = 0;int rem = -1;bool flag = false;while (strs[i]<='9'&&strs[i]>='0') //{if(flag == false) rem = i-1;flag = true;tem = (strs[i]-'0') + tem*10;i++;}if(flag) {flag = false;if(rem>=0&&strs[rem]=='-') ret.push_back(0-tem);else ret.push_back(tem);}}sort(ret.begin(),ret.end(),greater<int>());if(ret.size()<=3) return ret;else {vector<int> ret3;for(int i=0;i<3;i++) ret3.push_back(ret[i]);return ret3; }
}int main()
{string st = "a56b-6-8()_56dcsdc";vector<int> ret = solution(st);for(auto e:ret)cout<<e<<endl;
}
这段代码的主要功能是从一个字符串中提取所有整数(包括负数),将它们排序后返回最大的三个数。
主要逻辑步骤:
初始化:创建一个空向量
ret
来存储提取的数字。遍历字符串:
逐个字符检查是否是数字('0'-'9')
当发现数字时:
记录数字开始的位置(
rem = i-1
)将连续的数字字符转换为整数(
tem = (strs[i]-'0') + tem*10
)跳过后续的数字字符(
i++
)
检查数字前是否有负号(
strs[rem]=='-'
)如果有负号,将数字转为负数存入结果
否则直接存入结果
排序和返回结果:
将所有提取的数字按降序排序(
sort(ret.begin(),ret.end(),greater<int>())
)如果数字不超过3个,返回全部
如果超过3个,只返回前三个最大的数字
示例分析:
对于输入字符串 "a56b-6-8()_56dcsdc"
:
提取的数字:
"56" → 56
"-6" → -6
"-8" → -8
"56" → 56
排序后:56, 56, -6, -8
返回前三个:56, 56, -6
3.简易校验和算法
#include <string>
#include <sstream>
#include <iomanip>
#include <string>using namespace std;class Solution {
public:std::string decimalToHex(int decimal) {std::stringstream ss;ss << std::hex << std::uppercase << decimal; // 转为大写十六进制return ss.str();
} string SimpleCheckSum(const string& inputStr){string ret = string();string strs = inputStr;if((inputStr.size()/2)%4!=0){int needSize = 4-(inputStr.size()/2)%4;for(int i=0;i<needSize;i++){ strs+="FF";}}//cout<<strs<<endl;int n = (strs.size()/2)/4;if(n==1){ret = strs;}else{int left = stoi(strs.substr(0,8),nullptr,16);for(int i=0;i<n-1;i++){int right = stoi(strs.substr(i*8+8,8),nullptr,16); left = left^right;}ret = decimalToHex(left); if(ret.size()<8){int i = 8-ret.size();while(i){ret = '0'+ret;i--;}}}return ret;}
};
这段代码实现了一个简单的校验和计算功能,主要处理十六进制字符串的校验和计算。下面是对其逻辑的详细分析:
主要功能
输入填充:确保输入字符串的长度满足要求(每4个字节一组)
校验和计算:对分组后的数据进行异或运算
结果格式化:确保输出是8位大写十六进制字符串
stoi
是 C++11 引入的字符串转换函数,用于将字符串转换为整数。它是 <string>
头文件中定义的标准库函数。
基本语法
cpp
int stoi(const string& str, size_t* idx = 0, int base = 10);
参数说明
str
:要转换的字符串idx
(可选):一个指针,用于存储第一个未转换字符的位置(索引)base
(可选):转换的基数(进制),默认为10(十进制)
返回值
返回转换后的整数值
使用示例
1. 基本用法
cpp
#include <iostream> #include <string>int main() {std::string str1 = "123";int num1 = std::stoi(str1);std::cout << num1 << std::endl; // 输出: 123std::string str2 = "1010";int num2 = std::stoi(str2, nullptr, 2); // 二进制转换std::cout << num2 << std::endl; // 输出: 10return 0; }
2. 使用 idx 参数
cpp
#include <iostream> #include <string>int main() {std::string str = "123abc";size_t idx;int num = std::stoi(str, &idx);std::cout << "数字部分: " << num << std::endl; // 输出: 123std::cout << "第一个非数字字符位置: " << idx << std::endl; // 输出: 3return 0; }
3. 不同进制转换
cpp
#include <iostream> #include <string>int main() {std::string hex_str = "FF";int hex_num = std::stoi(hex_str, nullptr, 16);std::cout << hex_num << std::endl; // 输出: 255std::string oct_str = "77";int oct_num = std::stoi(oct_str, nullptr, 8);std::cout << oct_num << std::endl; // 输出: 63return 0; }
stoi
会忽略字符串开头的空白字符转换会一直进行直到遇到第一个非数字字符
对于空字符串或仅包含空白字符的字符串会抛出
invalid_argument
异常C++ 还提供了类似的函数:
stol
(转 long)、stoul
(转 unsigned long)、stoll
(转 long long)等
在 C++ 中,你可以使用以下几种方法将数字转换为不同进制的字符串表示:
1. 使用 std::to_string
(仅限十进制)
对于简单的十进制转换,可以使用 std::to_string
:
cpp
#include <iostream> #include <string>int main() {int num = 123;std::string str = std::to_string(num);std::cout << str << std::endl; // 输出: "123"return 0; }
2. 使用 std::bitset
(二进制转换)
对于二进制转换,std::bitset
很方便:
cpp
#include <iostream> #include <bitset> #include <string>int main() {int num = 10;std::string binary = std::bitset<8>(num).to_string(); // 8位二进制std::cout << binary << std::endl; // 输出: "00001010"return 0; }
3. 使用 std::ostringstream
(通用方法)
对于任意进制的转换,可以使用 std::ostringstream
结合流操作符:
cpp
#include <iostream> #include <sstream> #include <iomanip>std::string to_base_string(int num, int base) {std::ostringstream oss;if (base == 2 || base == 8 || base == 10 || base == 16) {switch (base) {case 2: oss << std::bitset<32>(num); break; // 二进制case 8: oss << std::oct << num; break; // 八进制case 10: oss << std::dec << num; break; // 十进制case 16: oss << std::hex << num; break; // 十六进制}} else {// 自定义进制转换(2-36)const char* digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";bool is_negative = num < 0;unsigned int unum = is_negative ? -num : num;do {oss << digits[unum % base];unum /= base;} while (unum > 0);if (is_negative) oss << '-';std::string result = oss.str();std::reverse(result.begin(), result.end());return result;}return oss.str(); }int main() {std::cout << to_base_string(255, 2) << std::endl; // 二进制: "11111111"std::cout << to_base_string(255, 8) << std::endl; // 八进制: "377"std::cout << to_base_string(255, 10) << std::endl; // 十进制: "255"std::cout << to_base_string(255, 16) << std::endl; // 十六进制: "ff"std::cout << to_base_string(255, 36) << std::endl; // 三十六进制: "73"return 0; }