位运算介绍、图解位运算相关题目【一个数字出现了K次,其他数字出现了M次,M > 1 K < M 找到出现了K次的数】【找到出现奇数次的数】等题目

news2024/9/25 17:17:47

位运算

常见的位运算 >>、>>>、<<、|、&、^、||、&&、~等

原码、反码、补码

  1. 原码
    将一个整数转换成二进制形式,就是其原码。例如 6 原码就是……0000 0000 0000 0110

  2. 反码
    对于正数,它的反码就是其原码(原码和反码相同);负数的反码是将原码中除符号位以外的所有位(数值位)取反,也就是 0 变成 1,1 变成 0。例如 6的原码和反码都是……0000 0000 0000 0110;反码 …… 1111 1111 1111 1001

  3. 补码
    对于正数,它的补码就是其原码(原码、反码、补码都相同);负数的补码是其反码加 1。

补码是在反码的基础上打了一个补丁,所以叫“补码”。

数的二进制表示

正数:就是其二进制表示 (原码)

0 : 0000000…… 0

负数:去掉符号位后 二进制的补码

为什么java中负数的值是去掉符号位后 二进制的补码

就是这样设计的,也是系统底层为了运算,与非门计算的时候通过一套逻辑运算,不用走多个分支,可以直接进行二进制的加法运算

输出int类型数字二进制形式

public void print(int number) {
		for (int i = 31; i >= 0; i--) {
			System.out.print((number & (1 << i)) == 0 ? "0" : "1");
		}
		System.out.println();
	}
}

求相反数

int a = 10;
~a + 1 = -10

二进制取反在 + 1 即可

找到数字二进制最后一位1

a & (~a + 1) = a & (-a)

a & ~a 的结果是所有位数都是 0

(~a + 1) 就是为了补上这一位,然后提取a二进制的最后一位 1

img

位运算实战

不用中间变量交换两个数

使用异或操作 二进制为 相同为0,不同为1 ,^ 满足交换律与结合律

结论1:一个数 ^ 自己 = 0 ( a ^ a = 0)

结论2:一个数 ^ 0 = 当前数 (a ^ 0 = a)

结论3:a ^ b ^ a = b => (a ^ a ^ b) = b

交换过程

num1 = num1 ^ num2;
num2 = num1 ^ num2;
num1 = num2 ^ num1;

交换过程:

初始条件 => num1 = A num2 = B

1,num1 = A ^ B ; 此时 num1值已经改变为A ^ B

2,num2 = num1 ^ num2 => A ^ B ^ B = > A 此时num2的值改变为 A

3,num1 = num2 ^ num1 => A ^ A ^ B = > B 完成值交换

img

public static void exchangeTwoNumber(int num1,int num2){
    num1 = num1 ^ num2;
    num2 = num1 ^ num2;
    num1 = num2 ^ num1;
    System.out.println( num1 + "  ***   " + num2);
}
一组数找到出现奇数次的数

在一组数种有一种数出现了奇数次,其他数字全部出现偶数次,找出出现奇数次数的数字

  • 一种数出现奇数次 a

思路 :相同的数 ^ 为0任何一个数 ^ 0 等于那个数 ,可以将所有的数 ^ 剩下的就是 奇数次的数 a

  • 两种数出现奇数次 分别为 a 和 b 例: (11 22 33 4 5)

思路:

1,将所有的数 ^ 结果是剩下的两种奇数次 a ^ b 的值 res

2,因为a != b 所以 res != 0

3,取出 res 二进制中最后一位 1 ,把这个位置记为 X 位 (当然取任何一位1 都可以 为什么要取这一个1?)

4,因为 在这个 1 的 X位置上 a 和 b 的值是不一样的 (一个是 1 一个是 0)

5,现在假设 a 的X 位置为 1 b的X位置 为 0 ( a的X 位置为0 ,b X位置为1 也可以)

6,所以可以把 所有的数分为两类 这个位置上的数字是 1的 和是 0 的 ( a 和其他出现偶数次数的 X位置为1的 | b 和其他出现偶数次的 X位置为 0的 )

7,现在把 a 和其他出现偶数次数的 X位置为1的 进行 ^ 运算 就求出了 找到了a

8,res ^ a = b

img

	/**
     * 一种数出现了奇数次,其他数出现了偶数次 找到这个数
     */
    public static int getOddOne(int arr[]) {
        int odd = 0;
        for (int i = 0; i < arr.length; i++) {
            odd = odd ^ arr[i];
        }
        return odd;
    }

    /**
     * 两种数出现了奇数次,其他数出现了偶数次 找到这个数
     */
    public static int[] getOddTwo(int arr[]) {
        int resArr[] = new int[2];
        int res = 0;
        for (int i = 0; i < arr.length; i++) {
            res = res ^ arr[i];
        }

        int resEnd = res & (~res + 1);
        int resTemp = 0;
        for (int i = 0; i < arr.length; i++) {
            // 相同位置为 1
            if ((arr[i] & resEnd) == 1) {
                resTemp ^= arr[i];
            }
        }
        resArr[0] = resTemp;
        resArr[1] = resTemp ^ res;
        return resArr;
    }
找到出现次数K次数的数

一组int类型数字中有一个数字出现了K次,其他数字出现了M次,M > 1 K < M 找到出现了K次的数

要求,额外空间复杂度 O(1), 时间复杂度 O(N)

思路:

1,定义一个长度为 32 的数组arr , 装的是所有数字 每一个位置 值为 1的个数 (解释见下图)

2,每一个位置中的数字个数,一定为 M的整数倍,或者 M的整数倍 + K 因为 K< M

3,所有值为 1的个数为 M的整数倍 + K 说明K的二进制在当前位置有值

4,将K的所有二进制位数拼接在一起,就找到了这个数

img

扩展

一组int类型数字中,其他数字出现了M次,剩下那一个数字如果出现了K次,返回这个数,如果没出现K次,返回 - 1

难点:如果出现了K次的数字是0,不会有 二进制为1的位置存入二进制数组,要单独处理

public class BitKM {
    public static void main(String[] args) {
//        int[] arr2 = {2, 2 ,2 ,6 ,6 ,6,3};
//        int i = getKNumber(arr2, 1, 3);
//        System.out.println(i);
        int maxKinds = 100;
        int k = 7;
        int m = 8;
        int range = 200;
//        for (int j = 0; j < 1000; j++) {
//            int[] randomArr = getRandomArr(maxKinds, range, k, m);
//            int mapValue = myHashMapTest(randomArr, k, m);
//            int kNumber = getKNumber(randomArr, k, m);
//            if(mapValue != kNumber){
//                System.out.println(mapValue);
//                System.out.println(kNumber);
//                System.out.println("出错了 " );
//            }
//        }
//        System.out.println(" no problem");
        for (int j = 0; j < 1000; j++) {
            int[] randomArr = getRandomArrForIfHasK(maxKinds, range, k, m);
            int mapValue = myHashMapTest(randomArr, k, m);
            int kNumber = getKNumberIfHas(randomArr, k, m);
            if(mapValue != kNumber){
                System.out.println(mapValue);
                System.out.println(kNumber);
                System.out.println("出错了 " );
            }
        }
        System.out.println(" no problem");
    }

    // arr种 找出出现k次的数
    public static int getKNumber(int arr[],int k,int m){
        int [] arrRes = new int[32];
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < 32; j++) {
                // 1010101
//                if(((arr[i] >> j) & 1) == 1){
//                    arrRes[j] ++;
//                }
                arrRes[j]+= (arr[i] >> j) & 1;
            }
        }
        int res = 0;
        for (int i = 0; i < 32; i++) {
            if(arrRes[i] % m == k){
                res |= (1 << i);
            }
        }
        return res;
    }
    // arr种 如果有出现k次的数 返回 否则 返回 -1
    public static int getKNumberIfHas(int arr[],int k,int m){
        int [] arrRes = new int[32];
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < 32; j++) {
                // 1010101
//                if(((arr[i] >> j) & 1) == 1){
//                    arrRes[j] ++;
//                }
                arrRes[j]+= (arr[i] >> j) & 1;
            }
        }
        int res = 0;
        for (int i = 0; i < 32; i++) {
            if (arrRes[i] % m !=0 ){
                if(arrRes[i] % m == k){
                    res |= (1 << i);
                } else {
                    return -1;
                }
            }
        }
        if (res == 0){
            int count = 0;
            for(int num : arr){
                if(num == 0){
                    count ++;
                }
            }
            if(count != k){
                return -1;
            }
        }
        return res;
    }

    public static int myHashMapTest(int [] arr ,int k,int m){
        // HashMap< 数字,出现的次数 >
        HashMap<Integer,Integer> hashMap = new HashMap<>();
        for (int i = 0; i < arr.length; i++) {
            Integer orDefault = hashMap.getOrDefault(arr[i], 0);
            hashMap.put(arr[i] ,  ++orDefault);
        }
        for (int num : hashMap.keySet()){
            if(hashMap.get(num) == k){
                return num;
            }
        }

        return -1;
    }

    public static int[] getRandomArr(int maxKinds,int range, int k, int m){
        // 出现了K次的数
        int kNum = getRangeNumber(range);
        int kinds = (int)(Math.random() * maxKinds) + 2;
        int [] arrRes = new int[ k  + m * (kinds - 1)];
        HashSet<Integer> hashSet = new HashSet<>();
        int index = 0;
        for (int i = 0; i < k; i++) {
            arrRes[index++] = kNum;
        }
        hashSet.add(kNum);
        kinds--;
        while (kinds > 0){
            int num;
            do {
                num = getRangeNumber(range);
            } while (hashSet.contains(num));
            hashSet.add(num);
            kinds--;
            for (int i = 0; i < m; i++) {
                arrRes[index++] = num;
            }
        }
        for (int i = 0; i < arrRes.length; i++) {
            int change = (int) (Math.random() * arrRes.length);
            int temp = arrRes[i];
            arrRes[i] = arrRes[change];
            arrRes[change] = temp;
        }
        return arrRes;
    }
    public static int[] getRandomArrForIfHasK(int maxKinds,int range, int k, int m){
        // 出现了K次的数
        int kNum = getRangeNumber(range);
        int kTimes = Math.random() < 0.5 ? k : (int) ((Math.random() * (m - 1))+ 1);
        int kinds = (int)(Math.random() * maxKinds) + 2;
        int [] arrRes = new int[ kTimes  + m * (kinds - 1)];
        HashSet<Integer> hashSet = new HashSet<>();
        int index = 0;
        for (int i = 0; i < kTimes; i++) {
            arrRes[index++] = kNum;
        }
        hashSet.add(kNum);
        kinds--;
        while (kinds > 0){
            int num;
            do {
                num = getRangeNumber(range);
            } while (hashSet.contains(num));
            hashSet.add(num);
            kinds--;
            for (int i = 0; i < m; i++) {
                arrRes[index++] = num;
            }
        }
        for (int i = 0; i < arrRes.length; i++) {
            int change = (int) (Math.random() * arrRes.length);
            int temp = arrRes[i];
            arrRes[i] = arrRes[change];
            arrRes[change] = temp;
        }
        return arrRes;
    }
    // [-range, +range]
    public static int getRangeNumber(int range){
        return (int) (Math.random() * (range + 1) - (int)(Math.random() * (range + 1)));
    }
}

点个赞呗
请添加图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/56546.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

节省50%带宽,这款媒体处理产品了解下!

视频处理技术想必大家都有所了解&#xff0c;现在每天都会涌现出大量新的视频处理模型&#xff0c;它们有的能够超分、降噪&#xff0c;有的能够做目标检测、跟踪、识别&#xff0c;加上一些前端技术就能实现很多炫酷的功能。但是现在大多数模型都是单任务模型&#xff0c;想要…

【POJ No. 2777】 颜色统计 Count Color

【POJ No. 2777】 颜色统计 Count Color 北大OJ 题目地址 【题意】 有一个长L 厘米的电路板&#xff0c;可以将板均分为L 段&#xff08;1&#xff5e;L &#xff09;&#xff0c;每段长1厘米。现在给电路板上色&#xff0c;每段只有一种颜色。可以在电路板上执行两种操作&am…

Qt扫盲-Assistant 助手使用总结

Qt Assistant助手 使用记录预备一、顶部菜单栏1. 快捷栏2. 文件、前往、帮助3. 查看-工具栏4. 编辑-首选项5. 书签二、侧边菜单栏1. 修改显示功能Bar2. 内容3. 索引4. 书签三、内容主体1. 结构总览 Content2. Properties3. Public Functions4. Reimplemented Public Functions5…

【JUC】并发编程学习笔记(三)

JUC并发编程八、ReentrantReadWriteLock 读写锁8.1、概述8.2、案例8.3、读写锁的降级九、BlockingQueue阻塞队列9.1、阻塞队列概述9.2、阻塞队列分类9.2.1、ArrayBlockingQueue(常用)9.2.2、LinkedBlockingQueue(常用)9.2.3、 DelayQueue9.2.4、 PriorityBlockingQueue9.2.5、 …

混合馈能悬架的设计与仿真(MATLAB)

目 录 摘 要 I Abstract II 第一章 绪论 1 1.1课题研究背景和意义 1 1.2国内外研究现状 2 1.3本文的主要研究内容 4 第二章 混合馈能悬架系统的工作原理 5 2.1混合馈能悬架系统的设计理念 5 2.2馈能系统的原理 6 2.3馈能系统的类型 6 2.4混合馈能悬架系统结构选型 8 2.5本章小结…

技术分享 | 如何确保API 的稳定性与正确性?你只需要这一招

现在&#xff0c;越来越多的 Web 应用转向了RESTful的架构&#xff0c;很多产品和应用暴露给用户的往往就是一组 REST API&#xff0c;这样有一个好处&#xff0c;用户可以根据需要&#xff0c;调用不同的 API&#xff0c;整合出自己的应用出来。从这个角度来讲&#xff0c;Web…

前端字体压缩(免费简单易上手)

场景&#xff1a;前端在开发过程中有时候要用到特殊字体&#xff0c;但如果引用网上下载好的字体&#xff0c;它们都是一个全的字体文件&#xff0c;这种字体文件里往往包含了大量你用不到的文字字符&#xff0c;从而导致你引入的字体文件大小高达1M以上&#xff0c;这会严重影…

C++08函数模板

1.自动推导类型 在C语言和C98中&#xff0c;auto 关键字用于修饰变量(自动存储的局部变量)。 在C11中&#xff0c;赋予了auto 全新的含义&#xff0c;不再用于修饰的变量&#xff0c;而是作为一个类型指示符&#xff0c;指示编译器在编译时推导auto声明的变量的数据类型。 在…

SpirngBoot<读完包你更上一层楼>

目录 一、SpringBoot概念 1.1 什么是SpringBoot 1.2 为什么要学习SpringBoot 1.3 SpringBoot的特点 1.4 总结 二、入门案例 2.1 创建工程 2.1.1 创建一个空工程 2.1.2 工程名为project_test&#xff1a; 2.1.3 设置jdk版本为1.8 2.1.4 新建一个module 2.1.5 填写项…

入职字节外包一个月,我离职了

有一种打工人的羡慕&#xff0c;叫做“大厂”。 真是年少不知大厂香&#xff0c;错把青春插稻秧。 但是&#xff0c;在深圳有一群比大厂员工更庞大的群体&#xff0c;他们顶着大厂的“名”&#xff0c;做着大厂的工作&#xff0c;还可以享受大厂的伙食&#xff0c;却没有大厂…

[附源码]计算机毕业设计springboot吾悦商城管理系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

老司机带带你,教你学会Java中又骚又暴力的“反射”技术

在Java中有这么一个很骚的技术&#xff0c;几乎贯穿了所有主流的框架&#xff0c;在所有主流框架的底层中你都可以看见它的身影&#xff0c;这个技术就是反射。关于反射&#xff0c;有很多小白会觉得很难&#xff0c;搞不清楚到底是怎么回事&#xff0c;也不知道该怎么用&#…

VS Code快速实现Git PR操作

注意&#xff1a;建议先学习git的基本操作。 安装插件 下图中红圈标记的插件都安装好。 Fork上游仓库 在网页上点击你想要fork的仓库&#xff0c;点击fork 然后该仓库就会fork到你的github账户下面&#xff0c;如下图。 现在可以在你账户下面的repo&#xff08;我们称为下…

[附源码]Python计算机毕业设计Django和vue的茶文化交流平台的设计与实现

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

Global Mapper 导出图层功能的妙用(重采样、设置文件类型、切片、按掩膜提取or裁剪……)

许多GIS软件都有导出的功能&#xff0c;但其中大部分的导出功能比较单一直接&#xff0c;仅仅是导出而已&#xff0c;或者最多可以改个导出的格式&#xff0c;改个坐标。但是Global Mapper 不一样&#xff0c;导出功能非常非常多&#xff0c;比如重采样&#xff08;可以设置重采…

Vue3框架的创建的两种种方案(第十二课)

1 VueCLi脚手架的安装 Home | Vue CLI (vuejs.org) 使用方法 | Yarn 中文文档 (bootcss.com) 3 Vite脚手架的安装 Vite | 下一代的前端工具链 4 使用的软件 Visual Studio Code webstorm64.exe IntelliJ IDEA 2022.2.3 HBuilder X 方案一 VueCLi脚手架的安装 1 创…

[附源码]计算机毕业设计在线招聘网站Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

MobileViT

还是vit系列啊 只不过这次是Apple团队出的轻量级、通用且移动友好的网络框架 论文地址&#xff1a;https://arxiv.org/pdf/2110.02178.pdf 轻量级卷积神经网络 (CNN) 是移动视觉任务的事实。他们的空间归纳偏差使他们能够在不同的视觉任务中以较少的参数学习表示。 轻量级卷积…

微服务自动化【集群搭建】

目录 搭建 etcd 集群 etcd构建自身高可用集群主要有三种形式: 1. 静态部署(前提) 2. 集群搭建 3. 集群测试 搭建 etcd 集群 etcd构建自身高可用集群主要有三种形式: 静态发现:预先已知etcd集群中有哪些节点&#xff0c; 在启动时通过--initial-cluster参数直接指定好etc…

[附源码]JAVA毕业设计互联网保险网站(系统+LW)

[附源码]JAVA毕业设计互联网保险网站&#xff08;系统LW&#xff09; 目运行 环境项配置&#xff1a; Jdk1.8 Tomcat8.5 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&a…