一个单调递增的数组 被人随机拿出一个数 你怎么找到这个数

就以 1,2,3,4,5,6,7,8,9… 100为例吧 小强把88这个数拿了出来 我怎么能很快找到?

1. 循环遍历 实现

以为的思维,我是想到了循环遍历,比较后一个数字是不是比前一个数字大1 不是的话 那就是少了当前比较值的后一个值 。

貌似可能解决问题,但是如果随机剔除两个呢? 那就废了 需要无休止的加if else

/*** @author 木子的昼夜*/
public class ConcurrnetTest {public static void main(String[] args){ConcurrnetTest test = new ConcurrnetTest();Integer[] arr = test.get();System.out.println(test.findByFor(arr));// 或者是直接比较下标System.out.println(test.findByFor02(arr));}// 遍历找数private Integer findByFor(Integer[] arr) {Integer res = null;// 头尾处理  如果剔除的是1或者100if(arr[0] != 1) {return 1;}if (arr[arr.length-1] != 100) {return 100;}for (int i = 0; i < arr.length-1; i++) {// 如果后一个不等于前一个+1 那就是被剔除了if (arr[i]+1 != arr[i+1]) {res = arr[i]+1;break;}}return res;}// 遍历找数private Integer findByFor02(Integer[] arr) {Integer res = null;// 100如果被剔除 检测不到 需要特殊处理if (arr[arr.length-1] != 100) {return 100;}for (int i = 0; i < arr.length; i++) {// 下标+1 不等于对应下表元素 就是有问题// 0:1 1:2 2:3 ....if (arr[i] != (i+1)) {res = i+1;break;}}return res;}/*** 获取 1 到 100  剔除88* @return*/public Integer[] get(){List<Integer> list = new ArrayList<>();for (int i = 1; i <= 100; i++) {if (i != 88) {list.add(i);}}return list.toArray(new Integer[0]);}
}
2. BitSet 实现

可以想一下 1到100 是有序的单调递增的 我们可以这样表示吗 ?

我们用一个bit数组来标识是否出现数据,bit为0 表示数据没出现,bit为1 表示数据出现

这样我们就可以遍历arr 然后设置bit对应的位(为1) , 最后遍历bit 看看那个位是0 那就是缺少这个数据

伪代码:

// 为什么101个  因为包含0   bit数组默认都是0
bit[] bits = new bit[101];
// 遍历数组 数组中有1到100 剔除88
for (int i = 0; i < arr.length; i++) {// 设置对应的下标为1 bits[arr[i]] = 1;
}

java中bit数组不好实现 我们可以用int 或者 long 的某一个二进制位表示

为什么要自己写? 难道大佬没有给我们提供轮子 ?

有的 : java.util.BitSet

实现代码:

/*** @author 木子的昼夜*/
public class ConcurrnetTest02 {public static void main(String[] args){ConcurrnetTest02 test = new ConcurrnetTest02();Integer[] arr = test.get();// 循环方式获取System.out.println(test.findByBitSet(arr));}// 遍历找数private Integer findByBitSet(Integer[] arr) {// 从0 到 100BitSet bitSet = new BitSet(101);for (int i = 0; i <arr.length ; i++) {bitSet.set(arr[i]);}// 从1 开始 到100  看哪个位是false 那就是哪个位没有值// 这里的1 100 都可以写成参数 或者是配置  具体看自己实现for (int i = 1; i <=100 ; i++) {if (!bitSet.get(i)){return i;}}return null;}/*** 获取 1 到 100  剔除88* @return*/public Integer[] get(){List<Integer> list = new ArrayList<>();for (int i = 1; i <= 100; i++) {if (i != 88) {list.add(i);}}return list.toArray(new Integer[0]);}
}

使用BitSet 不管随机摘除几个数据,逻辑都很简单 set get 两个方法就够

这里BitSet用着简单,主要考虑的是这个BitSet知识点 BitSet还可以对海量数据统计 等

3、简单了解一下BitSet
3.1 构成
private long[] words;

用的long数组来标记的 一个long类型 = 8字节 = 8*8 位 = 64 能表示64个数

3.2 构造函数
// 指定默认大小
public BitSet(int nbits) {// 不能是负数  0也是可以的if (nbits < 0)throw new NegativeArraySizeException("nbits < 0: " + nbits);// 初始化大小initWords(nbits);// 标记一下是否用户指定了大小 sizeIsSticky = true;
}
private void initWords(int nbits) {// 算一下需要多少个64  也就是多少个long 然后初始化数据库 words = new long[wordIndex(nbits-1) + 1];
}
/**
* ADDRESS_BITS_PER_WORD : 6
*/
private static int wordIndex(int bitIndex) {// >> 6 相当于 除以64  2^6=64return bitIndex >> ADDRESS_BITS_PER_WORD;
}
3.3 set方法

设置指定数值为true

 public void set(int bitIndex) {// 非法bit位置if (bitIndex < 0)throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);// 算一下这个位置对应long数组的哪个下标  bitIndex/64 int wordIndex = wordIndex(bitIndex);// 检查是否需要扩容 需要的话直接扩容  默认扩展2*words.length // 如果wordIndex>2*words.length 那就扩展到wordIndex大小expandTo(wordIndex);// 就是这个操作 设置了对应位置为1  // 1L << bitIndex 这句话就是把bitIndex转换为程序想要的bitindex// 比如 : 10 ==》 10000000000 // 然后 或运算  或就是只要一个为1 就为1  words[wordIndex] |= (1L << bitIndex); // Restores invariantscheckInvariants();
}

3.3 get方法

获取指定数值是否存在 存在返回true 不存在返回false

 public boolean get(int bitIndex) {// 非法判断if (bitIndex < 0)throw new IndexOutOfBoundsException("bitIndex < 0: " + bitIndex);// 检测了个什么东西checkInvariants();// 获取下标int wordIndex = wordIndex(bitIndex);// 小于wordsInUse(在用数组最大下标) 这里用的&  对应下标是1 才返回true return (wordIndex < wordsInUse)&& ((words[wordIndex] & (1L << bitIndex)) != 0);}
3.4 其他方法
clear() 清空所有 设置所以位为false
clear(int bitIndex) 设置指定下标为false
BitSet get(int fromIndex, int toIndex) 获取某个范围的值 返回BitSet
set(int bitIndex, boolean value) 设置指定位置true或 false
set(int fromIndex, int toIndex) 设置某个范围数据为true
set(int fromIndex, int toIndex, boolean value) 设置某个范围数据为true或false
clear(fromIndex, toIndex); 设置指定范围为false
and(BitSet set) 合并BitSet到自己  用的& 对应位置都为1 结果:就是1
or(BitSet set)合并BitSet到自己  用的| 对应位置只要有一个是1 结果:就是1
xor(BitSet set) 合并BitSet到自己  用的^  对应位置一个位1 一个为0 结果:就是1
andNot(BitSet set)   合并BitSet到自己  用的& ~ 原位置为1 set对应位置为0 结果:就是1

欢迎关注公众号:

一个单调递增的数组 被人随机拿出一个数 你怎么找到这个数相关推荐

  1. 输出一个为递增排序数组的旋转数组中的最小元素——8

    把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转.输入一个递增排序的数组的一个旋转,输出旋转数组的最小元素.例如数组{3,4,5,1,2}为数组{1, 2,3, 4, 5}的一个旋转, ...

  2. Golang 生成分布式单调递增 UUID

    要想生成单调递增的 UUID,唯有使用带时间戳的 UUID V1 版. 众所周知,UUID 的前 4 个字节存放的是时间戳低位,而时间戳低位是随着时间的变化而时刻不断地进行 "随机" ...

  3. 20220323-738.单调递增的数字

    链接: 738. 单调递增的数字 - 力扣(LeetCode) (leetcode-cn.com) class Solution {public int monotoneIncreasingDigit ...

  4. 算法实验-最长单调递增子序列长度

    问题描述 解决思路 O(n^2) 首先考虑使用动态规划的方法解决该问题.首先将原问题分解为子问题.对于长度为n的序列(从下标1开始),假设前n-1个元素形成了n-1个以arr[i]结尾的单调递增最长子 ...

  5. 动态规划作业 最长单调递增子序列

    动态规划作业 1.最长单调递增子序列 设计一个 O(n2)时间的算法,找出由 n 个数组成的序列 a 的最长单调递增子序列. 提示: 用数组 b[0:n]纪录以 a[i] (0<= i< ...

  6. 力扣刷题-python-单调栈(单调递减栈、单调递增栈)

    文章目录 1.单调栈 2.单调递减栈 3.单调递增栈 4.总结 1.单调栈 通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,要用单调栈. 2.单调递减栈 单调递减栈,栈 ...

  7. 最长单调递增子序列(时间复杂度O(nlogn))

    写在前面:仅为个人代码/总结,未必标准,仅供参考!如有错误,还望指出交流,共同进步! 最长单调递增子序列 [题目描述] 找出由n个数组成的序列中的最长单调递增子序列及其长度. [O(n*n)算法解题思 ...

  8. NYOJ 单调递增子序列(二)

    单调递增子序列(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长子序 ...

  9. NYOJ 214 单调递增子序列(二)

    单调递增子序列(二) 时间限制:1000 ms  |  内存限制:65535 KB 难度:4 描述 给定一整型数列{a1,a2...,an}(0<n<=100000),找出单调递增最长子序 ...

  10. 求出所有这些四位数是素数的个数cnt,再把所有满足此条件的四位数依次存入数组b中,然后对数组b中的四位数按从小到大的顺序进行排序

    已知数据文件IN14.DAT中存有300个四位数,并已调用读函数readDat()把这些数存入数组a中.请编制一个函数jsValue(),其功能是:求出所有这些四位数是素数的个数cnt,再把所有满足此 ...

最新文章

  1. 优酷智能档在大型直播场景下的技术实践
  2. 固定资产拆分比例怎么计算_财税知识:固定资产处置增值税是怎么计算的?涉及哪些计算公式?...
  3. .NET Core微服务之路:不断更新中的目录 (v0.42)
  4. 第一节:网页概述 学习目标 怎样才能学好前端
  5. Altium Designer PCB快速布局
  6. legend3---阿里云如何多个域名指向同一个网站
  7. css命名规范和书写规范
  8. Apache 2,4版本 编译与安装 RedHat enterprises 6.2
  9. 分享一个.NET平台开源免费跨平台的大数据分析框架.NET for Apache Spark
  10. LinkedList原码分析(基于JDK1.6)
  11. 捷联惯导算法(一)程序简单实现
  12. Alexa Top 1000 在中国的访问情况
  13. 历年考研计算机专业英语平均分,历年考研英语平均分及难度分析(截止至2020年)...
  14. 不用邀请照样申请Gmail免费邮箱
  15. Ubuntu18.04配置运行Kintinuous
  16. Xcelsius 访问webservice 需要配置
  17. java实验常见错误_求高手点拨一个Java SWING的IM系统实验的错误解决方案。
  18. C#网络TCP客户端的实现
  19. 南工院计算机答辩,人工智能与计算机学院举行“智能之星”评选答辩会
  20. linux配置防火墙白名单(限制某个IP段)

热门文章

  1. 申请计算机助理的英语作文,各位帮我找一篇英文申请信大学英语作文,申请助理..._口译笔译考试_帮考网...
  2. 现在公开一个DHT网络爬虫网络爬虫供大家一起交流
  3. Word文档最后一页总是删除不掉怎么办?
  4. 老路教你用得上的商学课_系列笔记
  5. 一直很火的steam汇率差赚钱项目详解,如何月入过万
  6. 【工程光学】平面与平面系统
  7. 如何批量缩小图片尺寸大小?
  8. 数学证明方法介绍(演绎推理、数学归纳法)
  9. 4874: 筐子放球
  10. 大数据技术之Hadoop(入门)