美文网首页
位运算,二进制,异或的一些算法题

位运算,二进制,异或的一些算法题

作者: _PatrickStar | 来源:发表于2021-04-02 13:57 被阅读0次

好记性不如烂笔头
一,异或用法:
1.不借用变量前提,交换两数值?

a = a ^ b;
b = a ^ b;
a = a ^ b;

2.数组中只有一个数出现奇数次,其余数都出现了偶数次,怎么找到这个数?

public static int findOne(int[] arr){
    int a = 0;
    for(int i=0;i<arr.length;i++){
        a ^= arr[i];
    }
    return a;
}

3.提供有一个int数,提取其最右侧第一个1 (a&(~a+1))
记住定律 a&(-a) 结果是右侧第一个数为1,其余为0的数(二进制)
4.一个数组有两个数出现奇数次,其他都出现偶数次,求这两个数(需要需用2,3的结论)

//假设a,b为这两个奇数次数,原理就是先异或,求出结果eor = a^b
//可以得出结论eor必定不为0,说明二进制位必定有一位为1
//找到最右侧1的位rightOne利用3.的知识点
//可以得出结论a,b必定分属两个阵营,如果a的rightOne为1,那么b的肯定为0
//同理剩余的出现的偶数次的数他们也可以被分成这两个阵营
//再利用a去异或自己阵营的这些偶数次的数可以得到a=eor`,b则等于eor^eor`
public static void findTwo(int[] arr){
    int eor = 0;  //eor其实就是a^b
    for(int i=0;i< arr.length;i++){
        eor ^=arr[i];
    }
    int rightOne = eor&(-eor);
    int onlyOne = 0 ; //eor'
    for(int i=0;i<arr.length;i++){
        if((arr[i]&rightOne)!=0){  //说明arr[i]和rightOne的1重叠到了,就可以划出阵营
            onlyOne ^= arr[i];
        }
    }
    System.out.println("一个是"+onlyOne+"另一个是"+(onlyOne^eor));
}

5.一个数组中有一个数出现了K次,其他数出现了M次,已知M>1,K<M,求出出现K次的数的值,要求空间复杂度O(1),时间复杂度O(n)

/**
 解题思路:整型数int是32位字节的,我们开辟一个长度为32的数组,里面暂时全放0
 然后将出先K次的数二进制上出现了1的位置加到数组里面,同理M也将二进制位出现了1的数加到数组
 最后出现的数组可能就类似[...a],假设数组最后一位等于a,说明a的组成成分可能有K也可能有M
 如果有K,那么用a%M则必不可能=0,同理,如果a%M=0说明此处K的二进制位0,
 则我们就可以根据求余%运算推导出最后的k的二进制表示从而算出K为多少
 */
public static void findK(int[] arr,int k,int m){
    int[] a = new int[32];    //定义32位的数组
    for(int num : arr){               
        for (int i = 0; i < 32; i++) {         //这个是常数次循环,所以是O(1)
            if(((num>>i)&1)!=0){           //这里((num>>i)&1)!=0说明num第i位上的数是1
                a[i]++;                    //可以写成a[i]+=((num>>i)&1),就不需要if语句
            }
        }
    }
        int answer = 0;                 //结果值
        for(int i=0;i<32;i++){ 
            if(a[i]%m!=0){             //求余,如果不等于0说明此处K有1
                answer |=(1<<i);         //则将1左移i位平且和answer做或运算,并且并入answer中
            }                            //循环32次结束后,1都填上后就是k的二进制值表示方法
        }
        System.out.println(answer);
    }

相关文章

  • [leetcode刷题笔记]数学与位运算

    位运算是二进制中比较常见的运算,包括按位与&,按位或|,非~,异或∧ 等,本文记录LeetCode刷题一些知识点,...

  • 笔记

    Java中常用的计算方法 Java异或运算总结 异或运算的性质: 异或运算是基于二进制的位运算,采用符号XO...

  • 位运算,二进制,异或的一些算法题

    好记性不如烂笔头一,异或用法:1.不借用变量前提,交换两数值? 2.数组中只有一个数出现奇数次,其余数都出现了偶数...

  • 2018-06-11c语言位运算

    位运算 Ps:位运算符是指进行二进制的运算。C语言中提供的位运算包括,与(&)、或(|)、异或(^)、取反(~)、...

  • 2018-06-06位运算

    位运算 Ps:位运算符是指进行二进制的运算。C语言中提供的位运算包括,与(&)、或(|)、异或(^)、取反(~)、...

  • 使用异或运算符 ^ 互换两个变量的值

    出处 二进制位运算符 - JavaScript 教程 - 网道 ---- 异或运算符 代码 “异或运算”有一个特殊...

  • 【Java算法】Java异或运算符的概念和使用

    1.Java异或介绍 异或是一种基于二进制的位运算,用符号XOR或者 ^ 表示,其运算法则是对运算符两侧数的每一个...

  • Java学习笔记-第一天

    位运算符 位运算是直接对二进制进行运算. 异或运算(^):相同二进制位进行运算,结果是0.不相同二进制位运算结果是...

  • Java 位运算符

    位运算符主要针对二进制,它包括了:“与”、“非”、“或”、“异或”。位运算符主要针对两个二进制数的位进行逻辑运算。...

  • 位运算

    一、什么是位运算? 位运算则是对二进制一系列的变化。常用运算符有:位与(&),位或(|),异或(^),取反(~),...

网友评论

      本文标题:位运算,二进制,异或的一些算法题

      本文链接:https://www.haomeiwen.com/subject/jwzfkltx.html