【算法】【优选算法】位运算(上)

目录

一、位运算简介及常用操作

基础位运算:

右移:>>

左移:<<

按位取反:~

按位与:& :有0就是0

按位或:| :有1就是1

按位异或 :^ :相同为0 ,相异为1。或者无进位相加

位运算符的优先级:

加括号吧,记不住

给一个数n确定他的二进制表示的第x位(二进制表示从右向左从第一位是0)是0还是1:

将这个数先向右移x位,再与1按位与,是0第x位就是0,是1第x位就是1。

n = (n >> x) & 1

将一个数n的二进制表示的第×位修改成1:

将这个数第x位按位或上1,其余按位或上0就行

n = n | (1 << x)

将一个数的二进制表示的第×位修改成0:

将这个数的第x位按位与上0,其余按位与上1就行

n = n & ( ~ (1 << x) )

位图的思想:

本质就是哈希表,只不过是使用一个int的32个比特位里面存储0和1。

提取一个数(n)二进制表示中最右侧的1:

取相反数就是:先按位取反,再加一。本质就是将最右侧的1到最左侧区域全部取反

n & -n

干掉一个数()二进制表示中最右侧的1:

n-1 就是将二进制最右侧的1到最右侧区域全部取反

n & n-1

异或(^)运算的运算律

a ^ 0 = a

a ^ a = 0

a ^ b ^ c = a ^ ( b ^ c )

二、191.位1的个数

题目链接:191.位1的个数

题目描述:

题目解析:

  • 就是返回一个正数的二进制表示中1的个数。

解题思路:

  • 直接该数第0位按位与上1,判断是不是1。
  • 然后该数向右移动一位。循环到数变为0即可。

解题代码:

java 复制代码
//时间复杂度:O(n)
//空间复杂度:O(1)
class Solution {
    public int hammingWeight(int n) {
        int ret = 0;
        while(n != 0) {
            ret += n & 1;
             n = n >> 1;
        }
        return ret;
    }
}

三、338.比特位计数

题目链接:338.比特位计数

题目描述:

题目解析:

  • 返回0到n中每个数二进制表示的1的个数,记录在对应下标数组中。

解题思路:

  • 直接循环遍历0到n,再调用第二题的方法即可。

解题代码:

java 复制代码
//时间复杂度:O(n^2)
//空间复杂度:O(n)
class Solution {
    public int[] countBits(int n) {
       int[] ret = new int[n+1];
       for(int i = 0; i <= n; i++) {
            ret[i] = hammingWeight(i);
       } 
       return ret;
    }
    //一个数二进制表示,位1的个数
    public int hammingWeight(int n) {
        int ret = 0;
        while(n != 0) {
            ret += n & 1;
             n = n >> 1;
        }
        return ret;
    }
}

四、461.汉明距离

题目链接:461.汉明距离

题目描述:

题目解析:

  • 就是求两个正数,二进制表示的对应位不相同的个数。

解题思路:

  • 先将两数异或,不同的位就是1了。
  • 调用题目二中的求1的个数的方法即可。

解题代码:

java 复制代码
//时间复杂度:O(n)
//空间复杂度:O(1)
class Solution {
    public int hammingDistance(int x, int y) {
        int n = x ^ y;
        return hammingWeight(n);
    }
    //一个数二进制表示,位1的个数
    public int hammingWeight(int n) {
        int ret = 0;
        while(n != 0) {
            ret += n & 1;
             n = n >> 1;
        }
        return ret;
    }
}

五、136.只出现一次的数字

题目链接:136.只出现一次的数字

题目描述:

题目解析:

  • 给你一个数组,数组中元素只有一个出现一次,其余全是两次。找到这个只出现一次的数组元素并返回。

解题思路:

  • 直接将数组中所有元素一一异或,到最后出现两次的元素都变为0,只剩下要找的元素了。

解题代码:

java 复制代码
//时间复杂度:O(n)
//空间复杂度:O(1)
class Solution {
    public int singleNumber(int[] nums) {
        int ret = nums[0];
        for(int i = 1; i < nums.length; i++)
           ret ^= nums[i];
        return ret;
    }
}

六、260.只出现一次的数字 III

题目链接:260.只出现一次的数字 III

题目描述:

题目解析:

  • 一个数组,数组中元素只有两个元素只出现一次,其余全是两次。找到这两个只出现一次的数组元素并返回。

解题思路:

  • 先将所有的元素全部异或在一起,就相当于两个只出现一次的元素异或在一起。
  • 在去出上诉异或结果,最右边的1。这位上两个数字是不相同的。
  • 所以再次遍历数组与结果数组异或,如果该位上与第二步结果相同放一个下标,不同放另一个下标。最后得到的就是结果了

解题代码:

java 复制代码
//时间复杂度:O(n)
//空间复杂度:O(1)
class Solution {
    public int[] singleNumber(int[] nums) {
        int[] ret = new int[2];
        
        int n = nums[0];
        for(int i = 1; i < nums.length; i++)
            n ^= nums[i];
        int last = n & -n;
        
        for(int i = 0; i < nums.length; i++) {
            if((nums[i] & last) == 0)
                ret[0] ^= nums[i];
            else
                ret[1] ^= nums[i];
        }
        return ret;
    }
}
相关推荐
珹洺1 小时前
C++从入门到实战(十)类和对象(最终部分)static成员,内部类,匿名对象与对象拷贝时的编译器优化详解
java·数据结构·c++·redis·后端·算法·链表
一 乐1 小时前
网红酒店|基于java+vue的网红酒店预定系统(源码+数据库+文档)
java·开发语言·数据库·毕业设计·论文·springboot·网红酒店预定系统
写bug的小屁孩1 小时前
移动零+复写零+快乐数+盛最多水的容器+有效三角形的个数
c++·算法·双指针
飞川撸码1 小时前
【LeetCode 热题100】208:实现 Trie (前缀树)(详细解析)(Go语言版)
算法·leetcode·golang·图搜索算法
这就是编程2 小时前
自回归模型的新浪潮?GPT-4o图像生成技术解析与未来展望
人工智能·算法·机器学习·数据挖掘·回归
羑悻的小杀马特2 小时前
【狂热算法篇】探寻图论幽径:Bellman - Ford 算法的浪漫征程(通俗易懂版)
c++·算法·图论·bellman_ford算法
xyliiiiiL3 小时前
从责任链模式聊到aware接口
java·开发语言
Fantasydg5 小时前
DAY 31 leetcode 142--链表.环形链表
算法·leetcode·链表
basketball6166 小时前
C++ STL常用算法之常用排序算法
c++·算法·排序算法
qystca6 小时前
蓝桥云客 岛屿个数
算法·dfs·bfs