第一题 两整数之和

题目

解题思路

本题要求我们实现加法

失去了编写代码过程中最基础的运算符
我们只能在更底层的实现中寻求帮助

在数电中我们学过半加器电路计算加法

半加器电路是指对两个输入数据位相加,输出一个结果位和进位,没有进位输入的加法器电路。 是实现两个一位二进制数的加法运算电路。半加器是通过异或门来具体实现的。

恰巧,golang中^算符作为二元运算符的时候也提供了异或功能
可以发现,对于整数 a 和 b:

在不考虑进位的情况下,其无进位加法结果为 a⊕b。
而所有需要进位的位为 a & b,进位后的进位结果为(a & b) << 1。

代码实现

func getSum(a, b int) int {
    for b != 0 {//由于b存储低位的进位信号,将b设为循环终止条件
        c := uint(a&b) << 1
        a ^= b
        b = int(c)
    }
    return a
}

复杂度分析

时间复杂度:O(log(max_int)),其中我们将执行位运算视作原子操作。

空间复杂度:O(1)。

第二题 逆波兰表达式求值

题目

思路

逆波兰表达式的优点为我们的解答提供了思路

使用栈完成求值计算

代码

func evalRPN(tokens []string) int {
    stack := []int{}
    for _, token := range tokens {
        //读取字符
        val, err := strconv.Atoi(token)
        if err == nil {
            //转换成数字成功,是数字
            stack = append(stack, val)
        } else {
            //是算符,取出两个数计算并将结果入栈
            num1, num2 := stack[len(stack)-2], stack[len(stack)-1]
            stack = stack[:len(stack)-2]
            switch token {
            case "+":
                stack = append(stack, num1+num2)
            case "-":
                stack = append(stack, num1-num2)
            case "*":
                stack = append(stack, num1*num2)
            default:
                stack = append(stack, num1/num2)
            }
        }
    }
    return stack[0]
}

复杂度分析

时间复杂度:O(n),其中 n 是数组 tokens 的长度。需要遍历数组 tokens 一次,计算逆波兰表达式的值。

空间复杂度:O(n),其中 n 是数组 tokens 的长度。使用栈存储计算过程中的数,栈内元素个数不会超过逆波兰表达式的长度。

03-05 14:16