[小玄的刷题日记]《LeetCode零基础指南》(第二讲) 函数

371.两整数之和

1.两整数之和 


1,“正常”思路

int getSum(int a, int b){
    return a + b;
}

2,位运算

预备知识:有符号的整数通常使用补码来表示和存储。补码具有以下特性:

  1. 正整数的补码与原码相同;负整数的补码为其原码除符号位外的所有位取反后+1
  2. 可以将减法运算转换为补码的加法运算来实现
  3. 符号位与数值位可以一起参与运算

异或相当于一次无进位加法。来看一个例子

 a ^ b得到了一个无进位加法运算结果,如果要得到 a + b 的结果的最终值,我们还要找到进位的数,把这二者相加

我们可以用操作获得进位

由计算结果可见,0100 并不是我们想要的进位,1 + 1所获得的进位应该放在它的更高位,即在左侧位上,因此我们还要将 0100 左移一位,这才是我们所要的进位结果

总结一下:

  1. a + b 的问题拆分为(a + b 的无进制位结果)( a + b 的进制位结果)
  2. 无进位加法使用异或计算得出
  3. 进位结果使用与运算移位运算得出
  4. 循环此过程,直到进位为 0 
int getSum(int a, int b){
    int c = 0;
    while(b)
    {
        c = (unsigned int)(a & b) << 1;
        a ^= b;
        b = c;
    }
    return a;
}

面试题 17.01. 不用加号的加法 - 力扣(LeetCode) (leetcode-cn.com)

1,正常做法

2,位运算 

int Add(int a, int b){
    int c = 0;
    while(b)
    {
        c = (unsigned int)(a & b) << 1;
        a ^= b;
        b = c;
    }
    return a;
}

 思路参考第一题

剑指 Offer 65. 不用加减乘除做加法 - 力扣(LeetCode) (leetcode-cn.com)

此题的解法也类似上面两道题


面试题 08.05. 递归乘法 - 力扣(LeetCode) (leetcode-cn.com)

对于这一题,我们可以采用暴力的方法直接 return a * b

不过,我们也可以按照题目的意思来操作一下下。

int multiply(int A, int B){
    int result; 
    if (B > 1)
    result = multiply(A, B - 1) + A;
    else
    result = A;
    return result;
}

 递归使用乘法函数,相当于b次的a相加

方法二 

基本情况:

  1. B = 0 , 结果 == 0
  2. B = 1 , 结果 == A

考虑B为偶数的情况

res = A * ( B / 2) +  A * ( B / 2)

B为奇数时,只要在原本的结果上再加上 A 即可 

int multiply(int A, int B){
    if(B == 0) return 0;
    if(B == 1) return A;
    int C = 0;
    if(B & 1 > 0) //表示B为奇数
    {
        C = A;
    }
    return multiply(A , B >> 1) + multiply(A , B >> 1) + C;
}

 29. 两数相除 - 力扣(LeetCode) (leetcode-cn.com)

题目规定了【只能存储32位整数】,如果我们使用64位整数,可以极大地方地方便我们的代码,但这是违反题目规则的。

如果除法结果溢出,我们需要返回  2(31)- 1

  1. 当除数为32位有符号整数的最小值-2(31) - 1时,如果除数为1,我们直接返回         -2(31)  ||   如果除数为-1,那么答案为 2(31),产生了溢出,我们需要返回的值为2(31) - 1
  2. 当被除数为0时,我们可以直接返回0

 于是,年幼的我们选择了

向大佬学习

int divide(int dividend, int divisor){
    int cnt = 0;
    int sign = 1;
    if ((dividend ^ divisor) < 0) { // 两数任意一个为负数
        sign = -1;
    }
    if (divisor == INT_MIN) { // 除数边界值特殊处理
        if (dividend == INT_MIN) {
            return 1;
        } else {
            return 0;
        }
    }
    if (dividend == INT_MIN) { // 被除数边界值特殊处理
        if (divisor == -1) {
            return INT_MAX;
        } else if (divisor == 1) {
            return INT_MIN;
        }
        dividend += abs(divisor); // 先执行一次加操作,避免abs转换溢出
        cnt++;
    } 
    int a = abs(dividend);
    int b = abs(divisor);
    while (a >= b) {
        int c = 1;
        int s = b;
        // 需指数级快速逼近,以避免执行超时
        while (s < (a >> 1)) { // 逼近至一半,同时避免溢出
            s += s;
            c += c;
        }
        cnt += c;
        a -= s;
    }
    return (sign == -1) ? -cnt : cnt;
}

 50. Pow(x, n) - 力扣(LeetCode) (leetcode-cn.com)

我尝试使用了常规的思路如下

double myPow(double x, int n){
    double sum = 1;
    int i = 0;
    if(n == 0)
    return 1.0;
    if(n > 0)
    {
        for(i = 1;i <= n;i++)
        sum *= x;
    }
    if(n < 0)
    {
        x = 1.0 / x;
        for(i = 1;i <= -n;i++)
        sum *= x;
    }
    return sum;
}

 不过时间复杂度太高,运行超时。后来去学习了大佬的解法如下:

方法一 :递归

double myPow(double x, int n){
    if (n == 0) return 1;
    if (n == 1) return x;
    if (n ==-1) return 1/x;
    double temp = myPow(x, n / 2);
    return temp * temp * myPow(x, n % 2);
}

方法二:迭代

double myPow(double x, int n){
    double res = 1.0;
    if (n < 0) x = 1/x;
    while (n) {
        if (n & 1) res = res * x;   //括号内等同(n % 2)
        x = x * x;
        n = n / 2;
    }
    return res;
}

方法三:快速幂  

快速幂的本质是分治算法 。

 举个例子:

从x开始,直接将上一次的结果进行平方,计算6次就能得到x(64)次方,而不需要对x*63次x

从左到右进行推导看上去比较困难,因为在每一步中,我们不知道在将上一次的结果平方后是否还需要*x。如果我们从右往左看,分治的思想就很明显了。

  1. 当我们要计算x^{n} 时,我们可以先递归计算出 y = x^{[n/2]} ,其中[n /2 ]表示对a进行向下取整
  2. 根据递归的结果,如果n为偶数,你们 x^{n} = y^{2} ;如果n为奇数,那么x^{n} = y^{2}* x
  3. 递归的边界为 n = 0,任意数的 0次方 为1
class Solution {
public:
    double quickMul(double x, long long N) {
        if (N == 0) {
            return 1.0;
        }
        double y = quickMul(x, N / 2);
        return N % 2 == 0 ? y * y : y * y * x;
    }

    double myPow(double x, int n) {
        long long N = n;
        return N >= 0 ? quickMul(x, N) : 1.0 / quickMul(x, -N);
    }
};

 69. Sqrt(x) 题解 - 力扣(LeetCode) (leetcode-cn.com)

(卷不动了)


面试题 16.07. 最大数值 - 力扣(LeetCode) (leetcode-cn.com)

没什么好说的了,三目操作符yyds


今天的LeetCode之旅到此结束,希望能跟英雄哥继续努力学习,不断提高自己!!

  • 18
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 8
    评论
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

玄澈_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值