29. 两数相除

链接

题目.

难度:

middle意思

解答:

思想就是两个正整数除,其实除法就是减法

package main

import (
	"fmt"
	"math"
)

func dividePositive(dividend int, divisor int) int {
	sum := 0
	for i := 1; i <= dividend; i++ {
		sum += divisor

		if sum == dividend {
			return i
		}

		if sum > dividend {
			return i - 1
		}
	}

	return 0
}

func divide(dividend int, divisor int) int {
	if dividend == 0 {
		return 0
	}

	if divisor == 0 {
		return math.MaxInt32
	}

	if divisor == 1 {
		return dividend
	}

	if divisor == -1 {
		if dividend == math.MinInt32{
			return math.MaxInt32
		}
		return -dividend
	}

	if dividend > 0 && divisor > 0 {
		return dividePositive(dividend, divisor)
	}

	if dividend > 0 && divisor < 0 {
		return -dividePositive(dividend, -divisor)
	}

	if dividend < 0 && divisor > 0 {
		return -dividePositive(-dividend, divisor)
	}

	if dividend < 0 && divisor < 0 {
		return dividePositive(-dividend, -divisor)
	}

	//never reach
	return 0
}

func main() {
	fmt.Println(divide(10, 3))
	fmt.Println(divide(7, -3))
}

复杂度分析

time

O(n)

space

O(1)

执行结果

执行用时 :2132 ms, 在所有 golang 提交中击败了29.03%的用户
内存消耗 :2.4 MB, 在所有 golang 提交中击败了50.00%的用户

这个结果太不理想了,可不可以再优化一下呢?具体来说dividePositive这个函数的复杂度可以优化吗?答案是可以的。我们可以事先计算好被除数的2倍,4倍 2**n倍,这样会减少很多计算

改进

func dividePositive(dividend int, divisor int) int {
	if dividend < divisor {
		return 0
	}

	if dividend == divisor {
		return 1
	}

	fastVec := []int{1}
	fastMap := map[int]int{1: divisor}

	sum := divisor
	for i := 2; i <= dividend; i = i + i {
		sum = sum + sum
		if sum == dividend {
			return i
		}

		if sum > dividend {
			break
		}

		fastVec = append(fastVec, i)
		fastMap[i] = sum
	}

	count := 0
	for j := len(fastVec) - 1; j >= 0; j-- {
		n1, n2 := fastVec[j], fastMap[fastVec[j]]
		if n2 <= dividend {
			count += n1
			dividend = dividend - n2
		}
	}

	return count
}

复杂度分析2

time

O(logn)

space

O(logn)

执行结果2

执行用时 :4 ms, 在所有 golang 提交中击败了78.49%的用户
内存消耗 :2.4 MB, 在所有 golang 提交中击败了76.00%的用户

另外,我们可以采取移位的思想,这样空间复杂度也是O1了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值