【LeetCode】1805. 字符串中不同整数的数目

题目描述

给你一个字符串 word ,该字符串由数字和小写英文字母组成。
请你用空格替换每个不是数字的字符。例如,“a123bc34d8ef34” 将会变成 " 123 34 8 34" 。注意,剩下的这些整数为(相邻彼此至少有一个空格隔开):“123”、“34”、“8” 和 “34” 。
返回对 word 完成替换后形成的 不同 整数的数目。
只有当两个整数的 不含前导零 的十进制表示不同, 才认为这两个整数也不同。

示例 1:

输入:word = “a123bc34d8ef34”
输出:3
解释:不同的整数有 “123”、“34” 和 “8” 。注意,“34” 只计数一次。

示例 2:

输入:word = “leet1234code234”
输出:2

示例 3:

输入:word = “a1b01c001”
输出:1
解释:“1”、“01” 和 “001” 视为同一个整数的十进制表示,因为在比较十进制值时会忽略前导零的存在。

提示:

1 <= word.length <= 1000
word 由数字和小写英文字母组成

方法一:模拟,错误

思路:

  • 遍历 word ,使用 atoi 函数 将整数字符串转换为 int型,再放入 set 集合(有序、不重复),最后返回 set 内的元素个数。

情况

  • 通过测试点 82 / 85;

错误原因

  • 最后几个测试点的数值太大,在 set 里面会溢出,全部变为 -1 ;

收获

  • 学会了 string 的相关用法:
    • 向 string 类型添加字符char : s += char;
    • 将 string 清空:使用函数 string.clear();
    • 将 string 转换为 int 型:num = atoi(s.c_str());
  • 学会了 set 的相关用法:
    • set < int > nums; 【有序、不重复的迭代器】
    • 向 set 添加元素 : nums.insert();
class Solution {
public:
    int numDifferentIntegers(string word) {
        int ans = 0;
        string s;
        set<int> nums;
        for(auto& w : word){
            // 如果当前字符不是数字,且s中已经保存了数字
            if(!isdigit(w) && s.size()!=0){
                // 将字符串转换为整数
                int num = atoi(s.c_str());
                nums.insert(num);
                s.clear();
            }
            else if(isdigit(w)){
                s += w;
            }
        }
        // 最后一个数字字符串需要额外考虑
        if(s.size()){
            int num = atoi(s.c_str());
            nums.insert(num);
        }
        return nums.size();
    }
};

方法二:方法一的基础上做了改进

思路:

  • 由于方法一的错误在于 set 无法存储太大的 int 型数字,那么我就「保留整数字符串」,直接存入 set 。
    但是在存入之前,需要「去除整数字符串的前导零」。
    在这里我定义了一个 trim 函数,指针 p 用来指向第一个非 0 的元素,此时我们就找到了需要替换的起始位置,通过 字符串长度和起始位置 相减,就得到了跨越的长度。
    因此,最终得到了存入 set 的字符串。

情况

  • 通过;

收获

  • 学会了 string 的相关用法:
    • 向 string 类型替换字符char : s.substr(替换的起始位置,跨越的长度);

时间复杂度:O(n),其中 n 是 word 的长度;
空间复杂度:O(n),其中 n 是哈希表需要占用的空间。
在这里插入图片描述

class Solution {
public:
    // 去除字符串的前导零
    string trim(string str){
        int p = 0; // 指向第一个非0元素
        for(auto& c : str){
            if(c == '0')   p ++;
            else break;
        }
        return str.substr(p, str.size() - p);

    }
    int numDifferentIntegers(string word) {
        int ans = 0;
        string s;
        set<string> nums;
        for(auto& w : word){
            // 如果当前字符不是数字,且s中已经保存了数字
            if(!isdigit(w) && s.size()!=0){
                nums.insert(trim(s));
                s.clear();
            }
            else if(isdigit(w)){
                s += w;
            }
        }
        // 最后一个数字字符串需要额外考虑
        if(s.size()){
            nums.insert(trim(s));
        }
        return nums.size();
    }
};

方法三:方法二的优化,双指针

思路:

  • 总体思路和方法二一样,不同的是它的代码比较简洁。直接使用双指针 i 和 j,「一次性」就把整数字符串找到,而我方法二的做法还使用了一个 字符串 s 来保存整数字符串,进而去除其前导 0 。
    因此方法三的空间使用率会更低一些。

情况

  • 通过;

收获

  • 代码简化;

时间复杂度:O(n),其中 n 是 word 的长度;
空间复杂度:O(n),其中 n 是哈希表需要占用的空间。
在这里插入图片描述

class Solution {
public:
    int numDifferentIntegers(string word) {
        set<string> nums;
        int n = word.size();
        for(int i=0; i<n; i++){
            if(isdigit(word[i])){
                // eg:000123a
                // j指向a, i指向1
                int j = i;
                while(isdigit(word[j]) && j<n) j++;
                while(i < j && word[i] == '0') i++;
                nums.insert(word.substr(i, j-i));
                i = j;
            }
        }
        return nums.size();
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值