字符串相乘

给定两个以字符串形式表示的非负整数 num1 和 num2,返回 num1 和 num2 的乘积,它们的乘积也表示为字符串形式。

输入: num1 = "2", num2 = "3"
输出: "6"

输入: num1 = "123", num2 = "456"
输出: "56088"

https://leetcode-cn.com/problems/multiply-strings


一开始的想法是, 先把字符串转成数字相乘, 在把结果转回成字符串, 哈哈哈, 果然测试用例已经替你考虑好了, 有几个巨长无比的字符串, 保证会让你溢出的.

那就模拟一下正常的乘法怎么计算的, 比如说123*456,可以通过乘法分配率拆成,123*6+123*50+123*400, 然后得到结果在相加就是56088. 这样的方法可以完成,但是写起来感觉比较麻烦, 得一直处理进位, 而且相加也得考虑进位.

要是能不处理进位就好了, 但是不处理进位是不可能的, 那要是能统一处理进位也可以接受,  于是就变成了这样, 每个数字和每个数字单独相乘, 然后放到数组中的特定位置, 相乘结束后, 在统一的处理一次进位, 这样代码的可读性就好多了.

大体思路就是这样图, 剩下的就是具体的操作了, 看注释吧. 

class Solution {
        
    func multiply(_ num1: String, _ num2: String) -> String {
        
        // 如果有一个为0, 那么结果肯定就是0
        if Int(num1) == 0 || Int(num2) == 0 {
            return "0"
        }
        
        // 把字符串转成数组, 同时把低位放到了前面, 比如"123" -> [3,2,1]
        let num1Array = num1.reversed().map { (item) -> Int in
            return Int(String(item))!
        }
        let num2Array = num2.reversed().map { (item) -> Int in
            return Int(String(item))!
        }
        // 2数相乘,最终结果肯定小于位数和,所以结果放到result中肯定没有问题,不会溢出
        // 证明: 已知 10^m-1<= num1 <10^m, 10^n-1<= num2 <10^n,
        // 那么 10^(m+n-2)<= num1*num2 <10^(m+n).
        // 举例, 100*100<999*999<1000*1000
        var result = [Int].init(repeating: 0, count: num1Array.count+num2Array.count)
        var i = 0
        var j = 0
        // 让num1中的每一位和num2中的每一位相乘, 结果放到i+j中,result中的每一个元素可能会超过10,下面会处理
        for firstNum in num1Array {
            
            j = 0
            for secondNum in num2Array {
 
                let temp = firstNum * secondNum
                result[i+j] += temp
                j += 1
            }
            i += 1
        }
        
        // 处理result中大于10的情况, 如果大于10, 本位取余数, 同时向高位进位
        // 比如个位上是88,那么个位上变成8,十位在原来的基础上+8,
        for (i,_) in result.enumerated() {
            
            if result[i]>=10 {
                result[i+1] += result[i]/10
                result[i] %= 10
            }
        }
        
        // 此时result中个位在最前面,反转之后,把result转成字符串, 同时去掉最高位的若干个0,
       result = result.reversed()
       var characterArray = result.flatMap { String($0) }
       for item in characterArray {

           if Int(item.description)! == 0 {
               characterArray.removeFirst()
           } else {
               break
           }
       }
       let resultStr = String(characterArray)
        
        return resultStr
    }
    
    
}

看了其他效率更好的算法, 确实有优化的空间, 但是可读性就降低了很多, 更高效的算法是在2层循环中同时处理好result, 这里是先计算好result, 等2层循环结束, 在单独处理, 分开处理, 我觉得可读性更好, 更适合学习理解, 所以就没有在优化了. 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值