万物的算法日记|第一天

笔者自述:

一直有一个声音也一直能听到身边的大佬经常说,要把算法学习搞好,一定要重视平时的算法学习,虽然每天也在学算法,但是感觉自己一直在假装努力表面功夫骗了自己,没有规划好自己的算法学习和总结,因为后半年也该找实习了,所以每日的算法题要进行恶补,勤能补拙,因此有了这一个算法日记系列;

必读: 大佬你好,感谢您的阅读,这篇文章是我的算法笔记,方便我每日回顾;
为了不耽误您的时间,我把本篇日记的考点方向和算法知识总结列出来,如果对您有需要要就进行阅读

也希望对您有帮助,和您一起通关算法!致谢

请添加图片描述

算法语言:java
题目来源:力扣–书本–初级算法,可以在力扣中搜索相关题名找到更多解法和大神方法
本文知识点:

  1. 随机数
    random.nextInt(j+1) 表示范围是从0-j
  2. 交换两个数的值
    交换两个数的值,使用异或操作,^= 效率更高,通过三次的异或操作,可以交换数组中的两个值,在不适用额外变量的情况下
  3. 筛选素数的方法
    埃拉托斯特尼筛法:从2开始,将每个素数的各个倍数,标记为合数,剩下的未标记的就是素数。
  4. 位运算
    可以通过位运算和0、1相与的操作来判断该位上是否是1,>>> 表示无符号右位移,并且在最左边插入零, >> 表示有符号位移,他们两个的区别是 >>> 不考虑符号位,这样可以保证被移动数的为模式不变,不会因为符号位的扩展而改变其值,>>考虑符号位

打乱数组

在这里插入图片描述
代码:

class Solution {
    
    
    private int[] nums;
    private Random random;
    public Solution(int[] nums) {
    
    
        this.nums = nums;
        random = new Random();
    }
    
    public int[] reset() {
    
    
        return nums;
    }
    
    public int[] shuffle() {
    
    
        if(nums == null){
    
    
            return null;
        }
        int []a = nums.clone();
        for(int j =1;j<a.length;j++){
    
    
            int i = random.nextInt(j+1);
            swap(a,i,j);
        }
        return a;
    }
    private void swap(int []a,int i,int j){
    
    
        if(i != j){
    
    
            a[i] ^= a[j];
            a[j] ^= a[i];
            a[i] ^= a[j];
        }
    }
}

学到的知识点:

  1. random.nextInt(j+1) 表示范围是从0-j
  2. 交换两个数的值,使用异或操作,^= 效率更高,通过三次的异或操作,可以交换数组中的两个值,在不适用额外变量的情况下

计数质数

在这里插入图片描述
代码:

class Solution {
    
    
    public int countPrimes(int n){
    
    
        boolean[] arr = new boolean[n];
        int cnt = 0;
        //埃拉托斯特尼筛法
        for(int i =2;i<n;i++){
    
    
            if(arr[i])
                continue;
            cnt++;
            for(int j =i;j<n;j+=i){
    
    
                arr[j] = true;
            }
        }
        return cnt;
    }
}

学到的知识点:

  1. 筛选素数的方法:
    埃拉托斯特尼筛法:从2开始,将每个素数的各个倍数,标记为合数,剩下的未标记的就是素数。
代码模版:
        for(int i =2;i<n;i++){
    
    
            if(arr[i])
                continue;
            cnt++;
            for(int j =i;j<n;j+=i){
    
    
                arr[j] = true;
            }
        }

位1的个数

在这里插入图片描述
代码:


// 位1 的个数
public class day6_12_6 {
    
    
    //将 n 向右移
    public int hammingWeight(int n ){
    
    
        int count =0;
        for(int i =0;i<32;i++){
    
    
            if(((n>>>i) &1) == 1){
    
    
                count++;
            }
        }
        return count;
    }
    //将 1 向左移
    public int hammingWeight1(int n){
    
    
        int count = 0;
        for(int i =0;i<32;i++){
    
    
            if((n%(1<<i)) != 0){
    
    
                count++;
            }
        }
        return count;
    }
}

学到的知识点:

  1. 可以通过位运算和0、1相与的操作来判断该位上是否是1,>>> 表示无符号右位移,并且在最左边插入零, >> 表示有符号位移,他们两个的区别是 >>> 不考虑符号位,这样可以保证被移动数的为模式不变,不会因为符号位的扩展而改变其值,>>考虑符号位

汉明距离

在这里插入图片描述
代码:

class Solution {
    
    
     public int hammingDistance(int x,int y){
    
    
        int xor = x^y;
        int res = 0;
        while(xor != 0){
    
    
            res+=xor&1;
            xor = xor>>>1;
        }
        return res;
    }
}

学到的知识点:

  1. 有两个数,通过异或操作,在二进制表达式中,如果同一对位数相同经过异或操作就是0,不同就是1,所以之后通过无符号移动和1进行与操作就可以得出两个不同的数之间的二进制距离了、

颠倒二进制位

在这里插入图片描述
代码:

public class Solution {
    
    
    // you need treat n as an unsigned value

    //    res <<= 1;: 这行代码将 res 左移一位,相当于将 res 中的所有位向左移动一个位置。这样做是为了为下一步的操作腾出一个空位。
//    res += n & 1;: 这行代码将 n 的最低位(即最右边的位)与 1 进行按位与操作,并将结果加到 res 中。这样做是为了将 n 的最低位放置到 res 的对应位置。
//    n >>= 1;: 这行代码将 n 右移一位,将 n 的所有位都向右移动一个位置。这样做是为了处理 n 的下一位。
//    通过循环的迭代,每次将 n 的最低位取出,并将其放置到 res 的对应位置上,最终完成了整数的二进制反转。
    public int reverseBits(int n){
    
    
        int res = 0;
        for(int i =0;i<32;i++){
    
    
            res <<=1;
            res+=n&1;
            n>>=1;
        }
        return res;
    }
}

学到的知识:

  1. 两个不同的数 相加,其实底层是位运算的相加,这就不难理解,上述代码中res+=n&1 这一步操作了

猜你喜欢

转载自blog.csdn.net/weixin_54174102/article/details/131162194