算法--位运算

算法原理

常见的位运算总结

1.基础位运算

<<左移

>>右移

~按位取反

&按位与 有0就是0

|按位或 有1就是1

^异或 相同位0,相异为1/无进位相加

2.给定一个数n,确定他的二进制表示中的第x位是0还是1

3.将一个数n的二进制位表示的第x位修改为1

4.将一个数n的二进制位表示的第x位修改为0

5.位图的思想(本质就是哈希表)

我们可以用int[]来模拟一个哈希表,但当数据过大的时候,这样并不适用,我们就尝试使用位图的思想,一个int有32个比特位,每个位置可以存储0或1的信息,这样能存储的数据就大幅度增加了

(上述2,3,4都是应用了位图的思想)

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

n&-n

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

n&n-1

8.运算符的优先级

能加括号就加括号

9.异或运算的运算律

1.a^0=a;

2.a^a=0;

3.a^b^c=a(b^c)

题目解析

1.判断字符是否唯一

https://leetcode.cn/problems/is-unique-lcci/

题目描述

实现一个算法,确定一个字符串s的所有字符是否全部不同

算法原理

解法一:哈希表(o(n)的时间复杂度和空间复杂度)

解法二:位图

优化点:鸽巢原理(如果len>26,一定有重复的字符出现)

代码实现

复制代码
public boolean isUnique(String astr) {
        if(astr.length()>26){
            return false;
        }
        int bitMap=0;
        for(int i=0;i<astr.length();i++){
            int x=astr.charAt(i)-'a';
            if(((bitMap>>x)&1)==1) return false;
            bitMap |=1<<x;
        }
        return true;
    }

2.消失的数

https://leetcode.cn/problems/missing-number/description/

题目描述

给定一个包含[0,n]中n个数的数组nums,找出[0,n]这个范围内没有出现在数组中的那个数

算法原理

1.哈希表

将数组中的元素加到哈希表中,然后遍历哈希表找出那个不存在的元素(用数组模拟实现哈希表,遍历数组,存在将数组对应的值改为1)

2.高斯求和

ret=(0+nums.length)/2-sum[nums];

3.位运算(异或运算的运算律)

a^a=0 a^0=a;

让0与数组中每一位异或,再与0异或到数组的 长度,这样出现的数被异或了2次,结果不受影响,而未出现的数字被异或了一次,结果就会是缺失的数字

代码实现

复制代码
    public int missingNumber(int[] nums) {
        int ret=0;
        for(int num:nums){
            ret^=num;
        }
        for(int i=0;i<=nums.length;i++){
            ret^=i;
        }
        return ret;
    }

3.两整数之和

https://leetcode.cn/problems/sum-of-two-integers/

题目描述

给你两个整数a和b,不使用运算符+和-,计算并返回两整数之和

算法原理

位运算(异或运算--无进位相加)

代码实现

复制代码
class Solution {
    public int getSum(int a, int b) {
        while(b!=0){
            int x=a^b;
            b=(a&b)<<1;
            a=x;
        }
        return a;
    }
}

4.只出现一次的数字

https://leetcode.cn/problems/single-number-ii/

题目描述

给定一个数组nums,除某个元素仅出现一次外,其余元素恰好出现了三次,请找出并返回哪个只出现了一次的元素

算法原理

使用位图的思想,依次修改ret每个比特位的值,每次修改的时候统计所有数字第i位的和,如果最后结果%3的结果为1,ret|=(1<<i)

代码实现

复制代码
class Solution {
    public int singleNumber(int[] nums) {
        int ret=0;
        for(int i=0;i<32;i++){
            int sum=0;
            for(int x:nums){
                if(((x>>i)&1)==1){
                    sum++;
                }
            }
            sum=sum%3;
            if(sum==1){
                ret|=(1<<i);
            }
        }
        return ret;
    }
}

5.消失的两个数

https://leetcode.cn/problems/missing-two-lcci/

题目描述

给定一个数组,包含从1到n的所有整数,但是缺少了两个数字,在O(N)时间内在O(1)空间里找到这两个数字

算法原理

这道题类似于丢失的数字+只出现一次的数字

解法:位运算

1.将所有的数异或在一起,tmp

2.找到tmp中比特位为1的那一位

3.根据x位的不同,划分两类进行异或

代码实现

java 复制代码
class Solution {
    public int[] missingTwo(int[] nums) {
        // 1.先把所有的数字异或在一起
        int tmp=0;
        for(int x:nums){
            tmp^=x;
        }
        for(int i=1;i<=nums.length+2;i++){
            tmp^=i;
        }
        // 2.找出a b比特位不同的哪一位
        int diff=0;
        while(true){
            if(((tmp>>diff)&1)==1){
                break;
            }else{
                diff++;
            }
        }
        // 3.将所有的数按照diff位不同,分成两类异或
        int[] ret=new int[2];
        for(int x:nums){
            if(((x>>diff)&1)==1) ret[1]^=x;
            else{
                ret[0]^=x;
            }
        }
        for(int i=1;i<=nums.length+2;i++){
            if(((i>>diff)&1)==1)
            ret[1]^=i;
            else{
                ret[0]^=i;
            }
        }
        return ret;
    }
}
相关推荐
熊猫_豆豆1 小时前
基于A*算法的雷雨绕飞路径MATLAB实现
算法·matlab·航天·a星算法
_F_y1 小时前
二分:山脉数组的峰顶索引、寻找峰值、寻找旋转排序数组中的最小值、点名
c++·算法
Elias不吃糖1 小时前
克隆图(LeetCode 133)——用数组做映射的 DFS 解法
c++·算法·leetcode·深度优先
iiiiii111 小时前
【论文阅读笔记】IDAQ:离线元强化学习中的分布内在线适应
论文阅读·人工智能·笔记·学习·算法·机器学习·强化学习
秋深枫叶红1 小时前
嵌入式第二十三篇——数据结构基本概念
linux·数据结构·学习·算法
Zsy_0510031 小时前
【数据结构】二叉树介绍及C语言代码实现
c语言·数据结构·算法
Ayanami_Reii1 小时前
基础数学算法-移棋子游戏
数学·算法·游戏·博弈论·sg函数
谁刺我心1 小时前
蓝桥杯C++常用STL
c++·算法·蓝桥杯
wubba lubba dub dub7501 小时前
第二十七周 学习周报
学习·算法·机器学习