常考算法面试题:字符串(大数)相加、字符串(大数)相减、字符串(大数)相乘,解题方法总结

常考算法面试题:字符串(大数)相加、字符串(大数)相减、字符串(大数)相乘

笔者今年秋招,最近投了一些大厂的实习,某为的手撕代码题目为 字符串相乘,某讯的手撕代码题目为字符串相减。
于是去LeetCode和网上搜索了一下,发现这类题目是面试的常考题。只要会四则运算这道题的思路就很清晰,主要字符串的处理,难点也在于字符串处理。 以下代码本人均在GCC编译器下运行过,没有问题。自己写上主函数、输入、调用算法函数即可编译运行验证,或者去leetCode找到原题直接粘贴上去。

1、字符串相加
LeetCode上的字符串相加题目如下所示:
LeetCode原题链接
常考算法面试题:字符串(大数)相加、字符串(大数)相减、字符串(大数)相乘,解题方法总结_第1张图片

解法思路:
定义两个指针 i和 j分别指向num1和 num 2的末尾,即最低位,同时定义一个变量add 维护当前是否有进位,然后从末尾到开头逐位相加即可。你可能会想两个数字位数不同怎么处理,这里我们统一在指针当前下标处于负数的时候返回 0,等价于对位数较短的数字进行了补零操作,这样就可以除去两个数字位数不同情况的处理。

Cpp代码如下

string addStrings(string num1, string num2) 
{
    int i=num1.length()-1;
    int j=num2.length()-1;
    int add = 0;                        // 保存进位的值
    string ans = "";                    // 保存结果的字符串

    while(i>=0 || j>=0 || add != 0)
    {
        int x = i>=0 ? num1[i]-'0':0;   // 指针当前下标为非负数的时候返回当前整数num[i]-'0'(此处减‘0’因为字符要转换为整数),处于负数的时候返回 0
        int y = j>=0 ? num2[j]-'0':0;   
        int result = x + y + add;
        ans.push_back('0'+result%10);   // 将每一位的计算结果压入字符串ans,因为压入的是result的个位 字符数字,所以压入的是 '0'+result%10
        add = result/10;                // 计算当前进位的值
        i-=1;
        j-=1;
    }
    reverse(ans.begin(), ans.end());    // 将压入ans中的字符串反转,即为正确结果
    return ans;
}

2、字符串相减
该题LeetCode上没有找到对应的题目

给定两个字符串形式的非负整数 num1 和num2 ,计算它们的差。
提示:
num1 和num2 的长度都小于 5100
num1 和num2 都只包含数字 0-9
num1 和num2 都不包含任何前导零
你不能使用任何內建 BigInteger 库, 也不能直接将输入的字符串转换为整数形式

解法思路:
字符串相减解法的思路与字符串加法的思路类似,不同点在于加法有进位,减法需要向高位借位,借位可以通过if来判断,然后通过索引将高一位减1。
还需要注意消除结果的前导零。比如 123-120 = 003 就不是正确答案。

Cpp代码如下

string subStrings(string num1, string num2)
{
    int i = num1.length()-1;
    int j = num2.length()-1;
    string res = "";

    while(i>=0 || j>=0)
    {
        int x=i >= 0 ? num1[i]-'0': 0;
        int y=j >= 0 ? num2[j]-'0': 0;
        int result = 0;                 // 保存每一位的运算结果
        
        // 判断被减数某位的值与减数某位的值的大小,如果小于则借位,大于则直接相减
        if(x < y)   
        {
            result = x+10-y;
            num1[i-1] -= 1;
        }
        else
        {
            result = x-y;
        }

        res.push_back('0'+result);      // 将运算结果转换为字符压入 字符串res
        i-=1;
        j-=1; 
    }

    // 删除前导的 0
    int k = res.length()-1;
    while(res[k] == '0' && k > 0)    // 判断 字符串的末尾(不能超出k范围)是否为 '0', 为 '0'则压出
    {
        res.pop_back();
        k--;
    }

    // 反转字符串 res, 即为要求的字符串的差
    reverse(res.begin(), res.end());

    return res;
}

3、字符串乘法
LeetCode上的字符串相乘题目如下所示:
LeetCode原题链接
常考算法面试题:字符串(大数)相加、字符串(大数)相减、字符串(大数)相乘,解题方法总结_第2张图片

解题思路1:
如果num1 和 num2之一是 0,则直接将 0 作为结果返回即可。
如果num1 和 num2都不是0,则可以通过模拟「竖式乘法」的方法计算乘积。从右往左遍历乘数,将乘数的每一位与被乘数相乘得到对应的结果,再将每次得到的结果累加(利用上面的字符串相加的函数即可)。这道题中,被乘数是 num1,乘数是 num2。
需要注意的是,num2除了最低位以外,其余的每一位的运算结果都需要补 0,第 i位即补 n-i个 0。
常考算法面试题:字符串(大数)相加、字符串(大数)相减、字符串(大数)相乘,解题方法总结_第3张图片

Cpp代码如下

    string multiply(string& num1, string& num2)
    {
        // 如果 num1或 num2为0,则返回结果 0
        if(num1 == "0" || num2 == "0")
            return "0";
        string ans = "0";
        int m=num1.size()-1;
        int n =num2.size()-1;
        for(int i=n; i>=0; i--)
        {
            string curr;
            int add = 0;
    
            // 乘数为第n-i位(按字符串索引的顺序),则再栈底添加 i个0
            for(int j=n; j>i; j--)
            {
                curr.push_back(0);
            }
            int y = num2[i] - '0';      // y 为乘数
            // 遍历 被乘数的每一位,分别与乘数y 相乘, 并将相乘所得每一位的结果压入 curr中
            for(int j=m; j>=0; j--)
            {
                int x = num1[j] - '0';  // x 为被乘数的某一位
                int product = x*y + add;
                curr.push_back(product%10);
                add = product/10;
            }
            // 若一轮乘法运算存在进位
            while(add != 0)
            {
                curr.push_back(add%10);
                add /= 10;
            }
    
            // 每个元素加 '0', 即为对的字符串
            for(auto& c : curr)
            {
                c += '0';
            }
    
            reverse(curr.begin(), curr.end());      // curr字符串,即为每次所求字符串
        
        ans = addStrings(ans, curr);                // 将 每一轮curr的结果相加
        }
    
        return ans;
    }

    string addStrings(string& num1, string& num2)
    {
        int i=num1.length()-1;
        int j=num2.length()-1;
        int add=0; 
        string ans = "";

        while(i>=0 || j>=0 || add != 0)
        {
            int x=i >= 0 ? num1[i]-'0':0;
            int y=j >= 0 ? num2[j]-'0':0;
            
            int result = x+y+add;
            ans.push_back('0'+result%10);
            add = result/10;
            i-=1;
            j-=1;
        }
        reverse(ans.begin(), ans.end());

        return ans;
    }

你可能感兴趣的:(高频算法面试题,算法,字符串,leetcode,数据结构)