位运算---算法的基础

Posted Heisenberg_Posion

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了位运算---算法的基础相关的知识,希望对你有一定的参考价值。

位运算,我们在学习中是很少碰到的,但是位运算还是有它自己独特的魅力

首先我们需要知道一些基本知识

对于int型1<<35和1<<3位是一样的,因为int只有32位,会进行取模操作


关于异或我们需要知道的

异或能交换两个数的值

与0异或的结果不变,与1异或结果相反

那么就有 a^0=a , a^a=0;

public void changeTwoNumber() 
    int a=2,b=1;
    a=a^b; 
    b=a^b;  //b=a^b^b =b=a^0=a
    a=a^b;  //a=a^b^a=b  b已经变成a了
    System.out.println(a+"+"+b);


题1:找出唯一成对的数

算法思想:

A,B,C,A是数组中的元素 , 先将数组中不重复的元素异或得到一个结果,再将这个结果与数组中的每个元素进行异或,留下来的那个数就是会重复的成对的数。

ABC^A (AB^C)

package com.zjl.bitOperation;

import org.junit.Test;

import java.util.Arrays;
import java.util.Random;

/**
 * @author 朱佳林
 * @version 1.0
 * @englishName jack
 */
public class TheOnlyDoubleNumber 
    private final static int ArrayNum =11;
    public static void main(String[] args) 
        //对数组进行赋值
        int[] array=new int[ArrayNum];
        for (int i = 0; i < ArrayNum-1; i++) 
            array[i]=i+1;
        
        array[ArrayNum-1]=new Random().nextInt(ArrayNum-1)+1;
        //将这个数与之前的某个数进行交换
        int index=new Random().nextInt(ArrayNum-2);
        int temp=array[ArrayNum-1];
        array[ArrayNum-1]=array[index];
        array[index]=temp;

        int x=0;
        System.out.println( Arrays.toString(array));
        for (int i = 0; i <ArrayNum-1 ; i++) 
            x=x^(i+1);
        
        for (int i = 0; i < ArrayNum; i++) 
            x=x^array[i];
        
        System.out.println(x);
    

题2:找出落单的那个数

一个数组里除了某一个数字之外,其他的数字都出现了两次。请写程序找出这个只出现一次的数字。

算法思想,将数组里个每个数进行异或得到的最终结果就是落单的那个数,因为成对的数异或结果为0,落单的那个数与0异或结果就是自身。

package com.zjl.bitOperation;

import java.util.Arrays;
import java.util.Random;

/**
 * @author 朱佳林
 * @version 1.0
 * @englishName jack
 */
public class TheOnlyNumber 

    public static void main(String[] args) 
        //初始化数据
        final int ARRAY_NUM=1001;
        int[] array=new int[ARRAY_NUM];
        int value=0;
        for (int i = 0; i <ARRAY_NUM-1 ; i++) 
            if (i%2==0) 
                value++;
            
            array[i]=value;
        
        array[ARRAY_NUM-1]=new Random().nextInt(10)+ARRAY_NUM/2+1;
        //将这个数与之前的某个数进行交换
        int index=new Random().nextInt(ARRAY_NUM -2);
        int temp=array[ARRAY_NUM -1];
        array[ARRAY_NUM -1]=array[index];
        array[index]=temp;
        System.out.println(Arrays.toString(array));
        int result=0;
        for(int arr:array)
            result^=arr;
        
        System.out.println(result);
    

题3:二进制中1的个数

package com.zjl.bitOperation;

import java.util.Scanner;

/**
 * @author 朱佳林
 * @version 1.0
 * @englishName jack
 */
public class FindNum_1_number 
    public static void main(String[] args) 
        Scanner scanner = new Scanner(System.in);
        System.out.println("Please input a number");
        int testNum=scanner.nextInt();
        int count=0;
        for (int i = 0; i <32 ; i++) 
            //一位一位的去判断
            if ((testNum&1<<i)==1<<i) 
                count++;
            
        
        System.out.println(count);
    

题4:用一条语句判断一个整数是不是2的整数次方

算法思想:

2的整数次方-1之后的那个数的二进制位除了高位其余都为1与之前的数异或结果就为0

public void judgeNumTwo() 
    Scanner scanner = new Scanner(System.in);
    int testNum=scanner.nextInt();
    if (((testNum-1)&testNum)==0) 
        System.out.println("YES");
    
    else 
        System.out.println("NO");
    

题5:0~1间浮点实数的二进制表示

如果无法表示,则输出ERROR

package com.zjl.bitOperation;

import org.junit.Test;
import org.omg.CORBA.PUBLIC_MEMBER;

import java.awt.*;

/**
 * @author 朱佳林
 * @version 1.0
 * @englishName jack
 */
public class DecimalBinary 

    //野方法
    public static void main(String[] args) 
        new DecimalBinary().judgeDecimal(0.875);
        StringBuilder stringBuilder = new StringBuilder("0.");
        double temp=0.625;
        double last=temp;
        for (int i = 1; i <33 ; i++) 
            double toReduce=Math.pow(2,-i);
            //如果小,说明能减,那么就添上1,不能就补0
            if (toReduce<=last) 
                last-=toReduce;
                stringBuilder.append("1");
            
            else 
                stringBuilder.append("0");
            
            if (last==0) 
                System.out.println(stringBuilder.toString());
                return;
            
            if (stringBuilder.length()>34) 
                System.out.println("ERROR");
                return;
            
        
    
    //这是传统的方法,知道如何将小数转换为二进制数
    //乘2,如果>1,则补1,然后减1,如果小于1,则继续乘2,直到这个数=0
    public void judgeDecimal(double temp) 
        StringBuilder stringBuilder = new StringBuilder("0.");
        while (temp>0) 
            temp=temp*2;
            if (temp>=1) 
                stringBuilder.append(1);
                temp-=1;
            
            else 
                stringBuilder.append(0);
            
            if (stringBuilder.length()>34) 
                System.out.println("ERROR");
                return;
            
        
        System.out.println(stringBuilder.toString());
    


题7:出现k次与出现1次

数组中只有-一个数出现了1次,其他的数都出现了k次,请输出只出现了1次的数。
2 个相同的2 进制数做不进位加法,结果为0
10个相同的10进制数做不进位加法,结果为0
k 个相同的k 进制数做不进位加法,结果为0

不进位加法也是异或运算,上述就是10个十进制的1相加如果不进位那肯定是0

这题会知道用java的一个类转进制就行,我觉得,因为有更好的方法map

Integer.toString(arr[i],k)

以上是关于位运算---算法的基础的主要内容,如果未能解决你的问题,请参考以下文章

位运算的运用场景使用总结

算法零基础学习leetcode 231326324题解

算法零基础学习leetcode 231326324题解

Java基础-位运算

乱序版 ● 剑指offer每日算法题打卡题解——位运算 (题号15,16,65)

算法很美Java版