zoukankan      html  css  js  c++  java
  • 算法笔记1-位运算

    1.位运算

    位运算符

    • 在处理整形数值时,可以直接对组成整形数值的各个位进行操作。这意味着可以使用屏蔽技术获得整数中的各个位(? ? )
    • &(与)、| (或)、^(异或)、~ (非/取反)
    • ">>"和"<<"运算符将二进制位进行右移或者左移操作
    • ">>>"运算符将用0填充高位; >>运算符用符号位填充高位,没有<<<运算符
    • 对于int型,1<<35与1<<3是相同 的,而左边的操作数是long型时需对右侧操作数模64
    • 与:都为1结果为1,或:有一个为1结果为1,异或:二者不同时结果为1
    a b ~a a&b a|b a^b
    1 1 0 1 1 0
    0 1 1 0 1 1
    0 0 1 0 0 0
    • 判断奇偶数 x&1=1为奇数 =0为偶数 原因:奇数最后一位是1,&1后为1,偶数最后一位为0,&1后为0

    • 获取二进制位是1还是0 (两种解决方案)
      86的二进制第5位是1还是0?

    1. 1先左移4位和86与运算,结果再右移,和为1则为,为0则为0
    2. 86右移4位,然后结果为和1与运算,结果1则为,为0则为0
      86>>4&1
    • 交换两个整数变量的值
    int a=2,b=1;
    a=a^b;
    b=a^b;
    a=a^b;
    System.out.println("a=="+a+",b=="+b);
    
    • 不用判断语句,求整数的绝对值
    int a=-88;
    System.out.println((a^a>>31)+(a>>>31));
    结果:88
    
    • 异或,可以理解为不进位加法:1 +1=0 , 0+0=0 , 1+0=1 .

      性质
      1、交换律可任意交换运算因子的位置,结果不变
      2、结合律(即(a^b)^c == a^(b^c) )
      3、对于任何数x ,都有x^x=0 , x^0=x,同自己求异或为0 ,同0求异或为自己
      1 1 0 1
      ^1 1 0 1
      ————
      0 0 0 0
      4、自反性A^B^B=A^0=A ,连续和同一一个因子做异或运算,最终结果为自己

    题1:找出唯一成对的数

    1-1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现?

    import java.util.Arrays;
    import java.util.Random;
    
    public class Main {
        public static void main(String[] args) {
            int N=11;
            int[] arr=new int[N];
            for (int i = 0; i <arr.length-1 ; i++) {
                arr[i]=i+1;
            }
            arr[N-1]=new Random().nextInt(N-1)+1;
            int index=new Random().nextInt(N);
            int t;
            t=arr[N-1];
            arr[N-1]=arr[index];
            arr[index]=t;
            System.out.println(Arrays.toString(arr));
            int x=0;
            for (int i = 0; i <N-1 ; i++) {
                x=x^(i+1);
            }
            for (int i = 0; i <N ; i++) {
                x^=arr[i];
            }
    //		x^x=0,出现两次的消去,剩下出现三次的
            System.out.println(x);
    //        辅助空间方法
            int[] h=new int[N];
            for (int i = 0; i <N ; i++) {
                h[arr[i]]++;
            }
            for (int i = 0; i < N; i++) {
                if(h[i]==2){
                    System.out.println(i);
                }
            }
        }
    }
    
    

    题2:找出落单的那个数

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

    题3:二进制中1的个数

    请实现一个函数,输入一个整数,输出该数二进制表示中1的个数。
    例: 9的二进制表示为1001,有2位是1

    import java.util.Scanner;
    
    public class _1的个数 {
        public static void main(String[] args) {
            Scanner sc=new Scanner(System.in);
            int N=sc.nextInt();
            System.out.println(Integer.toString(N,2));
    
            int count=0;
            for (int i = 0; i < 32; i++) {
                if((N&1<<i)==1<<i){
                    count++;
                }
            }
            System.out.println(count);
    //      另一种解法
            count=0;
            while(N!=0){
                N=(N-1)&N;
                count++;
            }
            System.out.println(count);
        }
    }
    
    

    题4:是不是2的整数次方

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

    if(((N-1)&N)==0){
        System.out.println("yes");
    }else{
        System.out.println("no");
    }
    

    题5:将整数的二进制奇偶位互换

    1&保留,0&置零,0^保留

    public class _奇偶位交换 {
        public static void main(String[] args) {
            int a=6;
            System.out.println(m(a));
           	//结果为9
        }
        private static int m(int i){
            int ou=i&0xaaaaaaaa;//和1010 1010 ...做与运算得到偶位
            int ji=i&0x55555555;//和0101 0101 ...做与运算得到奇位
            return (ou>>1)^(ji<<1);
        }
    }
    

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

    • 给定一个介于0和1之间的实数, (如0.625) ,类型为double,打印它的二进制表示(0.101,因为小数点后的二进制分别表示0.5,0.25.0.12.....)。
    • 如果该数字无法精确地用32位以内的-进制表示,则打印“ERROR”
    public class _浮点数二进制表示 {
        public static void main(String[] args) {
            double m=0.625;
            StringBuilder re=new StringBuilder("0.");
            while(m>0){
                m=m*2;//乘2:挪整
                if(m>=1){//判断整数部分
                    re.append("1");
                    m=m-1;//消除整数部分
                }else{
                    re.append("0");
                }
            }
            if(re.length()>34){
                System.out.println("ERROR");
                return;
            }
            System.out.println(re);
        }
    }
    
    

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

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

    
    public class _07_出现K次 {
        public static void main(String[] args) {
            int[] arr = {2, 2, 2, 9, 7, 7, 7, 3, 3, 3, 6, 6, 6, 0, 0, 0};
            int len = arr.length;
            char[][] kRadix = new char[len][];
            int k = 3;
    
            int maxLen = 0;
            //转成k进制字符数组
            //对于每个数字
            for (int i = 0; i < len; i++) {
                //求每个数字的三进制字符串并翻转,然后转为字符数组
                kRadix[i] = new StringBuilder(Integer.toString(arr[i], k)).reverse().toString().toCharArray();
                if (kRadix[i].length > maxLen)
                    maxLen = kRadix[i].length;
            }
            //不进位加法
            int[] resArr = new int[maxLen];
            for (int i = 0; i < len; i++) {
                //  不进位加法
                for (int j = 0; j < maxLen; j++) {
                    if (j >= kRadix[i].length)
                        resArr[j] += 0;
                    else
                        resArr[j] += (kRadix[i][j] - '0');
                }
            }
            int res = 0;
            for (int i = 0; i < maxLen; i++) {
                res += (resArr[i] % k) * (int) (Math.pow(k, i));// 8%3=2,
            }
            System.out.println(res);
        }
    }
    

  • 相关阅读:
    Arrays工具类、二维数组
    Idea软件的使用
    循环语句
    方法
    objective-C 2.0
    Unix系统常用命令
    文献管理工具Zotero
    如何降低论文重复率
    SQL易忽视的细节
    数据库系统原理学习资源
  • 原文地址:https://www.cnblogs.com/cxynb/p/12259656.html
Copyright © 2011-2022 走看看