LeetCode刷题报告2

📜个人简介

⭐️个人主页:摸鱼の文酱博客主页🙋‍♂️
🍑博客领域:java编程基础,mysql
🍅写作风格:干货,干货,还是tmd的干货
🌸精选专栏:【Java】【mysql】 【算法刷题笔记】
🎯博主的码云gitee,平常博主写的程序代码都在里面。
🚀支持博主:点赞👍、收藏⭐、留言💬
🍭作者水平很有限,如果发现错误,一定要及时告知作者哦!感谢感谢!

今日刷题内容

简单循环
(题目链接就不贴了,昨天的文章竟然给我警告了,说我链接太多,真无语)

剑指 Offer 64. 求1+2+…+n

这个题,看题目就知道很水

public int sumNums(int n) {
        int sum = 0;
        for(int i=1;i<=n;i++){
            sum+=i;
        }
        return sum;
    }

虽然是循环 但是还是用递归来一下吧

public int sumNums(int n) {
        if(n==0){
            return 0;
        }
        return n+ sumNums(n-1);
    }

231. 2 的幂

题目要求:给你一个整数 n,请你判断该整数是否是 2 的幂次方。如果是,返回 true ;否则,返回 false 。如果存在一个整数 x 使得 n == 2^x ,则认为 n 是 2 的幂次方。

思路:一开始看到这道题,立马想到的是拿这个数不断去除二,但是仔细一想,java的除法运算对于除不尽的数,结果是会向下取整的 所以这样做是不行的,所以要给它加上一个限定条件 可以被二整除的才除二,
不能被整除的也肯定不是2的幂

public boolean isPowerOfTwo(int n) {
        if (n <= 0) return false;
        while (n % 2 == 0) n /= 2;
        return n == 1;
    }

在这里插入图片描述

public bool isPowerOfTwo(int n){
    int i;
    unsigned int k = 1;        // (1)
    if(n <= 0) {
        return false;          // (2)
    }
    if(n == 1) {
        return true;           // (3)
    }
    for(i = 1; i <= 31; ++i) {
        k *= 2;                // (4)
        if(k == n) {
            return true;       // (5)
        }
    }
    return false;
}

然后就是位运算的解法(说实话,看了大佬的代码可以懂,但是就是想不出来)

大佬:fengziL
题解链接:https://leetcode-cn.com/problems/power-of-two/solution/5chong-jie-fa-ni-ying-gai-bei-xia-de-wei-6x9m/

解法1(相当于乘法)
通过左位移操作,列举出 int 型内的全部2的幂次方

    public boolean isPowerOfTwo(int n) {
         if (!n) return false;
        for (int i = 1, sub = 1; i < 32; ++i, sub <<= 1)
            if (sub == n) return true;
        return false;
    }

解法2(相当于除法)
通过右位操作,把n做2的幂次方的逆逻辑

public boolean isPowerOfTwo(int n) {
         if (!n) return n;
        while (n % 2 == 0) n >>= 1;
        return n == 1;
    }

解法3
利用上面掉到的常用位操作:
n & -n 得到最低位的 1 的位置
再和 n ^
如果 n 只有一个1,那么 n ^ (n & -n) 就只可能是0,要么非0

public boolean isPowerOfTwo(int n) {
        return n > 0 && (n ^ (n & -n)) == 0;
    }

解法4
直接利用常用方法 n & (n - 1) 去除最低位的1。
如果 n 的二进行里面只有一个1,那么去掉最低位的1,就只可能是0,要么非0
在这里插入图片描述

public boolean isPowerOfTwo(int n) {
        return n > 0 && (n & (n - 1)) == 0;
    }

上面4种解法的本质,其实就是求出32个bit位里面有几个1,有点类似于JAVA里面的

public boolean isPowerOfTwo(int n) {
    return n>0 && Integer.bitCount(n) == 1;
    }

解法5,特化解法
传入的参数 n 为 int 类型
也就是 -2^31 <= n < 2^31
如果 n 为 2 的幂次方的话一定是:
[1, 2^30] 双闭区间
把 n 作为除数, 2^30 作为被除数,那么,如果 n 是 2 的幂次方的话,余数肯定为0

public boolean isPowerOfTwo(int n) {
    return n > 0 && (1 << 30) % n == 0;
    }

326. 3 的幂

给定一个整数,写一个函数来判断它是否是 3 的幂次方。如果是,返回 true ;否则,返回 false 。
整数 n 是 3 的幂次方需满足:存在整数 x 使得 n == 3^x
我们不断地将 n 除以 3,直到 n=1。如果此过程中 n 无法被 3 整除,就说明 n 不是 3 的幂。

思路1:和上一题相似

    public boolean isPowerOfThree(int n) {
       while (n != 0 && n % 3 == 0) {
            n /= 3;
        }
        return n == 1;
    }
public boolean isPowerOfThree(int n) {
        int i;
        int k = 1;
        if(n <= 0) {
            return false;
        }
        if(n == 1) {
            return true;
        }
        for(i = 1; i <= 20; ++i) {  // (1)
            k *= 3;                 // (2)
            if(k == n) {
                return true;
            }
        }
        return false;
    }
   

342. 4的幂

给定一个整数,写一个函数来判断它是否是 4 的幂次方。如果是,返回 true ;否则,返回 false 。

整数 n 是 4 的幂次方需满足:存在整数 x 使得 n == 4^x

public boolean isPowerOfFour(int n) {
        while (n != 0 && n % 4 == 0) {
            n /= 4;
        }
        return n == 1;
     
    }

public boolean isPowerOfFour(int n){
    int i;
    int k = 1;
    if(n <= 0) {
        return false;
    }
    if(n == 1) {
        return true;
    }
    for(i = 1; i <= 15; ++i) {  // (1)
        k *= 4;                 // (2)
        if(k == n) {
            return true;
        }
    }
    return false;
}

1492. n 的第 k 个因子

给你两个正整数 n 和 k 。如果正整数 i 满足 n % i == 0 ,那么我们就说正整数 i 是整数 n 的因子。
考虑整数 n 的所有因子,将它们 升序排列 。请你返回第 k 个因子。如果 n 的因子数少于 k ,请你返回 -1 。
思路:要的是从小到大排序的因子,那咱就给他从小到大去遍历,是因子就计数加一,直到等于时输出

public int kthFactor(int n, int k) {
        int count = 0;
        for (int num = 1; num <= n; num++) {
            if (n % num == 0) {
                ++count;
                if (count == k) {
                    return num;
                }
            }
        }
        return -1;
    }

想想这个思路其实还可以优化,可以减少遍历的范围,如果 n=1000,那么从 501 开始到 999 结束,这些数都不是 n 的因子

public int kthFactor(int n, int k) {
        int count = 0, factor;
        for (factor = 1; factor * factor <= n; ++factor) {
            if (n % factor == 0) {
                ++count;
                if (count == k) {
                    return factor;
                }
            }
        }
        --factor;
        if (factor * factor == n) {
            --factor;
        }
        for (; factor > 0; --factor) {
            if (n % factor == 0) {
                ++count;
                if (count == k) {
                    return n / factor;
                }
            }
        }
        return -1;
    }

367. 有效的完全平方数

题目要求:给定一个 正整数 num ,编写一个函数,如果 num 是一个完全平方数,则返回 true ,否则返回 false 。
思路:最简单暴力的解法–从1开始给他遍历,拿每个数的平方结果去和给定数字比较,有相同的放回true,遍历结束还没有就返回false

public boolean isPerfectSquare(int num) {
        for(int i=1;i<=(num + 1)/2;i++){
            if(i * i == num){
                return true;
            }
        }
        return false;
    }

虽然是过了,但是这个时间消耗也太长了吧,想想还有没有更巧妙的方法

在这里插入图片描述

于是我想起了在某个范围内去找一个数,这范围内的数还是有序,那不就是给二分查找准备的:

public boolean isPerfectSquare(int num) {
        long l = 0, r = num;
        while (l < r) {
            long mid = l + r + 1 >> 1;
            if (mid * mid <= num) l = mid;
            else r = mid - 1;
        }
        return r * r == num;
    }

果然,二分查找yyds;
在这里插入图片描述

去题解里看看大佬们的解法:
在这里插入图片描述

思路:使用内置的库函数
根据完全平方数的性质,我们只需要直接判断num 的平方根 x 是否为整数即可。对于不能判断浮点数的值是否等于整数的语言,则可以通过以下规则判断:

public boolean isPerfectSquare(int num) {
        int x = (int) Math.sqrt(num);
        return x * x == num;
    }

emmm 虽然他说进阶要求是不让使用sqrt,那就再看看还有没有别的,
果然,官方题解就是不缺高大上:牛顿迭代法(我滴个乖乖,从小到大,看见牛顿总没好事)
这是牛大大的原理:(看到这个我又想起了被高数折磨的日子)
在这里插入图片描述

在这里插入图片描述
嘶~~,怎么说呢,第一次看完这个思路,我感觉他在说废话,这不就是正着说完反着说???
然后动手就没然后了,反正按我的理解实现的怎么也过不了
最后选择直接看代码,然后放弃这个解法(狗头保命).

    public boolean isPerfectSquare(int num) {
        double x0 = num;
        while (true) {
            double x1 = (x0 + num / x0) / 2;
            if (x0 - x1 < 1e-6) {
                break;
            }
            x0 = x1;
        }
        int x = (int) x0;
        return x * x == num;
    }

下面是宫水三叶大佬提供的数学思路,看这个我感觉我好像又行了,这理解清新脱俗,让人一看就懂
在这里插入图片描述

public boolean isPerfectSquare(int num) {
        int x = 1;
        while (num > 0) {
            num -= x;
            x += 2;
        }
        return num == 0;
    }

今日感悟

用位运算解题,很多时候都有意想不到的效果,理解它的原理时感觉也并没有那么难,但是自己很难找到其规律和特点
还是要多多练习,多练一些题型,应该就可以找到位运算解题的条件和规律

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值