C++刷题 - 7.23

发布于:2025-07-24 ⋅ 阅读:(16) ⋅ 点赞:(0)

 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 组成,并找出这样的最长子数组的长度。

这是一个典型的滑动窗口问题,可以用以下步骤解决:

  1. 滑动窗口维护:用 left 和 right 指针表示当前窗口的左右边界。

  2. 统计非 tag 的数量:窗口中最多只能有一个非 tag 元素(因为可以修改一个元素)。

  3. 窗口收缩条件:当窗口中非 tag 的数量超过 1 时,移动 left 指针以缩小窗口。

  4. 更新最大长度:每次窗口合法时(非 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;
}

这段代码的主要功能是从一个字符串中提取所有整数(包括负数),将它们排序后返回最大的三个数。

主要逻辑步骤:

  1. 初始化:创建一个空向量ret来存储提取的数字。

  2. 遍历字符串

    • 逐个字符检查是否是数字('0'-'9')

    • 当发现数字时:

      • 记录数字开始的位置(rem = i-1

      • 将连续的数字字符转换为整数(tem = (strs[i]-'0') + tem*10

      • 跳过后续的数字字符(i++

    • 检查数字前是否有负号(strs[rem]=='-'

      • 如果有负号,将数字转为负数存入结果

      • 否则直接存入结果

  3. 排序和返回结果

    • 将所有提取的数字按降序排序(sort(ret.begin(),ret.end(),greater<int>())

    • 如果数字不超过3个,返回全部

    • 如果超过3个,只返回前三个最大的数字

示例分析:

对于输入字符串 "a56b-6-8()_56dcsdc"

  1. 提取的数字:

    • "56" → 56

    • "-6" → -6

    • "-8" → -8

    • "56" → 56

  2. 排序后:56, 56, -6, -8

  3. 返回前三个: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;
    }
};

这段代码实现了一个简单的校验和计算功能,主要处理十六进制字符串的校验和计算。下面是对其逻辑的详细分析:

主要功能

  1. 输入填充:确保输入字符串的长度满足要求(每4个字节一组)

  2. 校验和计算:对分组后的数据进行异或运算

  3. 结果格式化:确保输出是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;  // 输出: 123
    
    std::string str2 = "1010";
    int num2 = std::stoi(str2, nullptr, 2);  // 二进制转换
    std::cout << num2 << std::endl;  // 输出: 10
    
    return 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;  // 输出: 123
    std::cout << "第一个非数字字符位置: " << idx << std::endl;  // 输出: 3
    
    return 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;  // 输出: 255
    
    std::string oct_str = "77";
    int oct_num = std::stoi(oct_str, nullptr, 8);
    std::cout << oct_num << std::endl;  // 输出: 63
    
    return 0;
}
  1. stoi 会忽略字符串开头的空白字符

  2. 转换会一直进行直到遇到第一个非数字字符

  3. 对于空字符串或仅包含空白字符的字符串会抛出 invalid_argument 异常

  4. 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;
}

 


网站公告

今日签到

点亮在社区的每一天
去签到