这是一个经典的题型,比如:有1亿个数字,找出其中重复的。

最直观的写法就是双重循环了,但是效率过低。再就是先排序再遍历,又总感觉不太直接。后来偶然查到BitSet有相应的api来处理这个问题,查了下源码,还挺有意思的,记录一下。

直接上代码

public class Test05 {public static void main(String[] args) {// TODO Auto-generated method stubint[] arr = new int[10000000];for(int i = 0; i < arr.length; i++) {arr[i] = i;}arr[arr.length - 1] = arr.length - 10;//构造一个有重复数字的数组aaa(arr);}public static void aaa(int[] arr) {long time1 = System.currentTimeMillis();int max = 1;for(int i: arr) {max = i > max ? i : max;//查找最大值}long[] temp = new long[(max >> 6) + 1]; for(int i: arr) {if((temp[i >> 6] & (1l << i)) == 0) {//判断是否重复temp[i >> 6] |= 1l << i;}else {System.out.println(i + " is duplicate");//break;}}long time2 = System.currentTimeMillis();System.out.println((time2 - time1) + "ms");}}

(相对于源码,仅省略了自动扩容和校验)

全是位运算很吓人,但是实际上比冒泡排序还简单。

原理
如果说桶排序是投机取巧,那这个算法就是投机取巧上继续投机取巧。首先找到最大的数,然后除以64(也就是移6位)以确定桶的数量(源码中是动态改变桶数组的,每加入一个新数字,都会算出它所应该在的位置,如果比当前数组长度大,则复制数组进行扩容。由于与算法本身无关,写起来又很麻烦,省略掉)。对于每一个数字,它所在的桶数组的下标是除以64后的整数部分,它所对应的值是1l << 除以64的余数 。举几个例子:

对于数字3,它除以64为0,余数是3。那么它应该在桶数组下标0的位置,它的值用2进制表示为1000。
对于数字4,它除以64为0,余数是4。那么它应该在桶数组下标0的位置,它的值用2进制表示为10000。由于插入数组时用了或运算符,最终结果应该为11000。

在查找重复时也是完全一样的套路。如果我要查找数字4是否存在,则需要查出下标为0的数字,然后通过与运算符来判断第五位是否为1。

最终,上面的temp数组中的数字用2进制表示的话可能是这样的(64位太长了,用4位来表示)

[1000, 0001, 0011]

它实际表示,已经存在数字3,4,8,9。

也就是说,它就是用每一位的1来表示所对应的数字是否存在。

一些细节的解释:
为什么是移6位?因为移6位相当于除以64,而64是长整形的长度。
长整形每左移64位后值不变。1l << i 实际上相当于1l << (i % 64)

缺点:与桶排序一样,如果最大值过大,那么效率可能会很低。

java 找出重复的数字相关推荐

  1. 剑指offer答案 c语言,剑指offer之C语言不修改数组找出重复的数字

    1  题目 不修改数组找出重复的数字 在一个长度为N+1的数组里面的所有数字都在范围1~N范围内,所以数组至少有一个数字是重复的,请找出重复数字,但是不能修改输入的数组. 2  思路 思路1: 我们开 ...

  2. python查找数列中重复数字_在数组中找出重复的数字(异或法)

    购买本课程后,可以加51CTO学院李宁老师官方交流群:550369460注意,该群只允许购买李宁老师课程的学员进行技术交流,加群时需要提供在51CTO购买李宁老师课程的订单编号(任何一个课程的订单编号 ...

  3. 不修改数组找出重复的数字

    在长度为n+1的数组里的所有数字都在1~n的范围内,所以数组中至少有一个数字是重复的.请找出数组中任意一个重复的数字,但不能修改输入的数组. 思路: 一.把1~n的数字从中间的数字m分成两部分,前面一 ...

  4. java 找出重复的数据_java 查找list中重复数据实例详解

    java 查找list中重复数据实例详解 需求: 查找一个list集合中所有重复的数据,重复的数据可能不止一堆,比如:aa, bb, aa, bb, cc , dd, aa这样的数据.如果有重复数据, ...

  5. 14. 不修改数组找出重复的数字【难度: 一般 / 知识点: 抽屉原理 二分】

    第一种方法: 开了map计数,多用了空间,map: logn,时间复杂度O(nlogn) class Solution {public:int duplicateInArray(vector<i ...

  6. 找出重复的数java_剑指offer:1.找出数组中重复的数(java版)

    数组中重复的数: 题目:找出数组中重复的数, 题目描述: 在一个长度为n的数组里的所有数字都在0到n-1的范围内. 数组中某些数字是重复的,但不知道有几个数字是重复的. 也不知道每个数字重复几次.请找 ...

  7. 找出重复的那个数字的异或算法

    假如你有一个用1001个整数组成的数组,这些整数是任意排列的,但是你知道所有的整数都在1到1000之间(包括1000).此外,除了一个数字出现两次外,其他的数字只出现了一次.假设你对数组做一次处理,用 ...

  8. java 4位数,java 找出4位数的所有吸血鬼数字

    java 找出4位数的所有吸血鬼数字 /** * 找出四位数所有的吸血鬼数字 * 吸血鬼数字:位数为偶数的数字可以由一对数字相乘而得,这对数字包含乘积一半的位数 * 如:1260 = 21*60 */ ...

  9. Java中找出缺失的数字

    给定一组连续的整数,例如:10,11,12,--,20,但其中缺失一个数字,试找出缺失的数字1 import java.util.*;2 3 public class Main {4 public s ...

  10. java数组找出重复元素及次数_Java查找数组重复元素,并打印重复元素、重复次数、重复元素位置...

    面试题查找重复元素并打印重复次数和重复位置,一顿懵逼,回来死磕写下来,打印指定重复次数和最大次数,其他在此基础上可以再更新 package sort; import org.testng.annota ...

最新文章

  1. 开发日记-20190513 关键词 汇编语言(六)
  2. python3.7.2安装教程-CentOS 7安装Python教程
  3. PowerSploit-CodeExecution(代码执行)脚本渗透实战
  4. HDU2255(带权二分图的最大匹配)
  5. vue脚手架依赖包安装不成功_Windows下vue-cli的搭建
  6. Sona(NBUT-1457)
  7. C++连接MySQL(Windows)
  8. 以xml html编写的的学生管理系统,基于.NET和XML的学生中心数据库管理系统的研究与实现...
  9. 什么是MySQL视图
  10. add php support,WordPress add_theme_support() 函数详解
  11. 小时候很喜欢看的一些卡通片的主题曲(绝对经典)
  12. HBuilder X 连接逍遥Android模拟器
  13. 研发人员的工时为何需要管理?
  14. 好看的table css样式
  15. 【ReentrantLock】
  16. 最近爆火chatGTP是人工智能还是人工智障?
  17. 05-云数据中心IT基础设施层概述
  18. 学习笔记 | 产品报告
  19. 怎么修复Win11中的AMD驱动程序崩溃?修复win11驱动崩溃方法
  20. Blog5 无监督深度关键短语生成——关键代码分析3

热门文章

  1. Foxmail发送邮件,发送邮件工具类
  2. MySQL基础查询语句练习题
  3. 使用视频追踪算法研究物体运动轨迹
  4. 计算机应用研究参考文献格式,参考文献编写规则-计算机应用研究.PDF
  5. 算法实践:波兰表达式
  6. K8s简述NodePort
  7. word自动添加标题以及批量生成图片题注
  8. 局域网传文件_跨平台传输文件方案大汇总(中篇)——可能全网最全的传输方案了...
  9. 浙江大学14届计算机学院孙晓宇,郑州外国语学校2011年保送生录取名单
  10. linux lefse分析,科学网-linux本地化进行lefse分析-林国鹏的博文