leetcode 43. 字符串相乘

203 阅读1分钟

题目链接

注意题目要求中的“说明”部分:

  • num1 和 num2 只包含数字 0-9。
  • num1 和 num2 均不以零开头,除非是数字 0 本身。

解题基本思路直截了当,就死模拟乘法过程。

假设两字符串是,“12345”和“678”,
先计算 “12345”乘以“600”,
再计算 “12345”乘以“70”,加上前一步的中间结果,
然后是 “12345”乘以“8”,加上前一步的中间结果。
得到最终结果。

代码已提交通过。

func multiply(num1 string, num2 string) string {
        // 空串无意义
	if num1 == "" {
		panic("num1 is empty")
	}
	if num2 == "" {
		panic("num2 is empty")
	}
	if num1 == "0" || num2 == "0" { // 只要有一个数是0,结果就是0
		return "0"
	}
        // 如果一个数是1,结果就是另外一个数
        if num1 == "1" {
                return num2
        }
        if num2 == "1" {
                return num1
        }
        // 选出长度较短的,便于后续优化
	if len(num1) <= len(num2) {
		return multiplyImpl(num1, num2)
	}
	return multiplyImpl(num2, num1)
}

func multiplyImpl(sn, ln string) string {
	var(
		sl = len(sn)
		ll = len(ln)
                // res和tmp在下面循环过程中可以复用
		res = make([]byte, 1, ll)
		tmp = make([]byte, 0, ll)
	)
	res[0] = '0'
	for i := 0; i < sl; i++ {
		tmp = mul(ln, sn[i], sl-i-1, tmp[:0])
		res = add(res, tmp)
	}
        // 翻转res中的元素使得左边是高位,右边是低位。
	for i, j := 0, len(res)-1; i < j; i, j = i+1, j-1 {
		res[i], res[j] = res[j], res[i]
	}
	return string(res)
}

// 注意这里的结算结果在[]byte中的放置顺序,左边是低位,右边是高位。
// 比如某个中间结果的整数形式是 123450,
// 在[]byte中的放置情况是 ['0','5','4','3','2','1']。
func mul(m string, s byte, suffixZeroCount int, tmp []byte) []byte {
	if s == '0' {
		return append(tmp, '0')
	}
	for i := 0; i < suffixZeroCount; i++ {
		tmp = append(tmp, '0')
	}
        if s == '1' { // 可以简化处理
                for i := len(m)-1; i >= 0; i-- {
                        tmp = append(tmp, m[i])
                }
                return tmp
        }
	var(
		r int
		sn = getN(s)
	)
	for i := len(m)-1; i >= 0; i-- {
		x := sn*getN(m[i]) + r
		tmp = append(tmp, getB(x%10))
		r = x/10
	}
	if r > 0 {
		tmp = append(tmp, getB(r))
	}
	return tmp
}

// 输入的两个[]byte中的放置顺序都是左边是低位,右边是高位。
func add(res, b []byte) []byte {
	bl := len(b)
	if bl == 1 && b[0] == '0' {
		return res
	}
	var (
		i int
		j int
		r int
		al = len(res)
	)
	for i < al && j < bl {
		x := getN(res[i])+getN(b[j]) + r
		d := getB(x%10)
		if i < len(res) {
			res[i] = d
		} else {
			res = append(res, d)
		}
		r = x/10
		i++
		j++
	}
        var iEnd bool
	for i < al { // 处理剩余部分
		x := getN(res[i]) + r
		d := getB(x%10)
		if i < len(res) {
			res[i] = d
		} else {
			res = append(res, d)
		}
		r = x/10
		i++
                iEnd = true
	}
	for j < bl { // 处理剩余部分
		x := getN(b[j]) + r
		d := getB(x%10)
		if j < len(res) {
			res[j] = d
		} else {
			res = append(res, d)
		}
		r = x/10
		j++
	}
	if r > 0 { // 如果还有进位
		d := getB(r)
                if iEnd {
                       if i < len(res) {
                               res[j] = d    
                       } else {
                               res = append(res, d)
                       }
                } else {
                       if j < len(res) {
                               res[j] = d
                       } else {
                               res = append(res, d)
                       }
	        }
	}
	return res
}

// 将字符形式的数字转换成整型
func getN(b byte) int {
	return int(b-'0')
}

// 将整型数字转换成字符形式
func getB(n int) byte {
	return byte(n)+'0'
}