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

一、有序情况

有1001个数,按照从小到大的顺序排列,其中只有两个数是重复的。当然,因为有序,装两个数也必定是挨着的。
题目的要求就是用最少的内存开销、最少的时间开销找出这个重复的数字

在 莫贝特 的 博客中,他的算法是将(1001个数字的和)- (1000个数字的和)=  重复数字,这种算法思路简单,但是时间复杂度是最高的,共进行了2000次循环,至于留言中的其他算法也基本上属于线性查找,线性查找的时间复杂度是 O(N),对于这道题目,运气最好的时候第一次就能找到,运气最差的时候,要找1000次,平均要找500次。

static void Main(string[] args){int[] list = new int[1001];for (int i = 1; i < 1001; i++){list[i - 1] = i;}Random random = new Random();list[1000] = random.Next(1, 1000);int sum1 = 0;int sum2 = 0;foreach (int i in list){sum1 = sum1 + i;}for (int i = 1; i < 1001; i++){sum2 = sum2 + i;}Console.WriteLine("重复的数字是:"+(sum1 - sum2).ToString());Console.Read();}

然而,如果我们考虑到这是一个有序数列,而且只有两个重复数,二分折半查找法就一跃而出了,对数据结构和算法有了解的人都知道,二分查找法是有序数列最好的查找算法。
具体思路是:

  1. left=0
  2. right=10001
  3. 如果 left 和 right 中间那个位置 pos 的数值等于位置编号 pos,则:
  4. left=pos,否则:
  5. right=pos
  6. 如果(right-left>1),则重复步骤 3)-6),直到 right-left=1, pos 就是要查找的数

1000个数只需查找10次,一万个数13次,十万个数17次,一百万个数20次,时间复杂度 O(logN),速度很快。

#!/usr/bin/python
# -*- coding: GBK -*-
import random# 生成数列,一万个数
arr_length=100001
list=range(1,arr_length)#插入一个随机数
rnd=random.randrange(1,arr_length)
list.insert(rnd-1,rnd)print '\n重复数为:'+ str(rnd)
print'\n开始查找'# 正式开始查找算法
left=0
right=arr_length
count=0while ((right-left)>1):pos=(left+right)/2    count=count+1print '第 %d 次定位:%d' % (count,pos)    if (list[pos]==pos):right=poselse:left=pos    print '\n查找结果:',list[left]

注:先附上原作者的Python,找个时间再转为java

二、无序情况

上面的算法是:(1001个数字的和)- (1000个数字的和)=  (1001个数字的和)- n*(n+1)/2=  重复数字,求和需要1000次循环。
这个算法之所以能成立,是因为序列由1-1000的连续数字组成,因此,不管他们怎么排列,(1000个数字的和)都是从1加到1000。但是,如果这1000个数字不是连续的,比如是从1-100000中随机选出来的互不相同的1000个数,那么这个算法就不成立了,因为我们无法知道(1000个数字的和)到底是哪1000个数字。

既然现在给出的条件是1-1000的乱序,那么就可以利用连续这一特殊性来改进算法。

最简单的方法应该是:再开辟一个1000空间的数组 list2 ,将这1001个数字从第一个开始,依次放到 list2 中他的编号位置上
比如:
list2[list[0]-1]=list[0]
list2[list[1]-1]=list[1]
依次这样做下去,直到某个要保存的数字在 list2 对应的位置上已经存在,就找到了这个数字。
但是这次我看清要求了,不能开辟新的空间。

虽然不能开辟新的空间,思路却已经有了,就是利用连续性和索引的对应关系,具体算法描述如下:
1、取出第一个位置的数字:p1=list[0]
2、将第一个位置标记:list[0]=0
3、取出 p1 位置的数字:p2=list[p1]
4、将 p1 位置标记:list[p1]=0
5、取出 p2 位置的数字:p3=list[p2]
6、将 p2 位置标记:list[p2]=0
.............
依次做下去,直到下一个要找的位置被标记过了,数字就找到了。
原因是:那个重复的数字,最终要访问他自己的位置第二次,当他访问时,发现位置已经被上一个自己访问过了,他就知道自己不是唯一的了。

这种算法叫什么名字我也不知道,能不能叫漫游算法?
在最好的情况下,他的循环次数是 1,比如[1,1,....1000]
在最坏的情况下,他的循环次数是 1000,比如[1,2,3......1000,1000]
平均情况下,他的循环次数是 N/2,虽说数量级上仍然是 O(N)级别的,但是平均来说,仍然比前面的求和法快了一倍

#!/usr/bin/python
# -*- coding: GBK -*-
import random# 生成数列
arr_length=10001
list=range(1,arr_length)#加入一个随机数
rnd=random.randrange(1,arr_length)
list.append(rnd)
print '\n重复数为:'+ str(rnd)#打乱顺序
random.shuffle(list)# 正式开始查找算法
count=0
idx=0
while (list[idx]!=0):count=count +1temp=list[idx] list[idx]=0idx=temp    print "找到:%d,循环 %d 次" % (temp,count)

注:先附上原作者的Python,找个时间再转为java

一万个数查找两个重复数,快速二分查找法 O(logN)(转)相关推荐

  1. 二分查找python实现代码_二分查找——Python实现

    一.排序思想 二.python实现 def binarySearchDemo(arr, key): """ python二分查找非递归方式 :param arr:待排序列 ...

  2. [Leedcode][JAVA][第287题][寻找重复数][HashSet][二分查找][快慢指针]

    [问题描述][中等] 给定一个包含 n + 1 个整数的数组 nums,其数字都在 1 到 n 之间(包括 1 和 n),可知至少存在一个重复的整数.假设只有一个重复的整数,找出这个重复的数.输入: ...

  3. LeetCode 1099. 小于 K 的两数之和(二分查找)

    文章目录 1. 题目 2. 解题 2.1 暴力 2.2 二分查找 1. 题目 给你一个整数数组 A 和一个整数 K,请在该数组中找出两个元素,使它们的和小于 K 但尽可能地接近 K,返回这两个元素的和 ...

  4. 51Nod-1090 3个数和为0【排序+二分查找】

    1090 3个数和为0 基准时间限制:1秒 空间限制:131072KB 分值:5难度:1级算法题 给出一个长度为N的无序数组,数组中的元素为整数,有正有负包括0,并互不相等.从中找出所有和 = 0的3 ...

  5. 如何写出正确的二分查找?——利用循环不变式理解二分查找及其变体的正确性以及构造方式...

    序言 本文以经典的二分查找为例,介绍如何使用循环不变式来理解算法并利用循环不变式在原始算法的基础上根据需要产生算法的变体.谨以本文献给在理解算法思路时没有头绪而又不甘心于死记硬背的人. 二分查找究竟有 ...

  6. php二分查找算法时间复杂度,一个运用二分查找算法的程序的时间复杂度是什么...

    一个运用二分查找算法的程序的时间复杂度是"对数级别".二分查找是一种效率较高的查找方法,算法复杂度即是while循环的次数,时间复杂度可以表示"O(h)=O(log2n) ...

  7. c语言函数调用排序用插入法,C语言:编写查找和排序函数(二分查找,冒泡排序,选择排序法,插入排序)...

    任务代码: 二分查找数组的一个数字:(函数法) #include int binarySearch(int a[],int len,int key) { int low=0,high=len-1,mi ...

  8. c语言数据结构对学生信息折半查找,数据结构实训报告-二分查找学生管理实训报告.doc...

    数据结构实训报告-二分查找学生管理实训报告 吉林工业职业技术学院 ( 数据结构实训 ) ( 20~ 2012 学年第 学期) 指导教师: 专业班级: 计算机3101 学生姓名: 2011年月日实训项目 ...

  9. java数组二分查找_java 13-1 数组高级二分查找

    查找: 1.基本查找:数组元素无序(从头找到尾) 2.二分查找(折半查找):数组元素有序 pS:数组的元素必须有顺序,从小到大或者从大到小.以下的分析是从小到大的数组 二分查找分析: A:先对数组进行 ...

最新文章

  1. POJ 1661 Help Jimmy(递推DP)
  2. selenium2与python自动化6-select下拉框
  3. python init函数可以外部调用么,如何从python类中调用外部函数
  4. 游戏安全资讯精选 2017年第十期 英国彩票网遭遇DDoS攻击,中断90分钟 DNSMASQ多高危漏洞公告 阿里云协助警方破获国内最大黑客攻击案,攻击峰值690G...
  5. lingo解题报告内容解释
  6. idea mybatis generator插件_SpringBoot+MyBatis+Druid整合demo
  7. c语言统计字母数字符号个数程序,请问这个用c怎么做:输入一串字符,分别统计其中数字和字母的个数...
  8. 基于上下文的访问控制与基于区域策略的防火墙
  9. APACHE服务器出现No input file specified.解决方案
  10. 分子重构技术_4. 串珠模型重构
  11. PHP中巧用curl 并发减少获取第三方网页内容时间
  12. 修改Linux里的hosts文件
  13. 影响宝宝脾胃健康的3个“真凶”,难怪孩子脾胃总是调不好!
  14. Jenkins集成GitHub
  15. Storm-kafka【接口实现】4 - KafkaSpout
  16. 电脑上的计算机可以加密码,如何给电脑上的文件夹加密
  17. 2022海南最新消防设施操作员模拟考试试题及答案
  18. cf网络不稳定或服务器异常,电脑玩穿越火线为什么提示网络环境异常 - 卡饭网...
  19. 打印系统开发(27)——WinForm开发(49)——c# winform 打印图像,PrintDialog打印并且设置打印纸张大小
  20. RepLKNet代码解读(31大小的卷积核)

热门文章

  1. H3CTE讲师分享H3C实验7 PPP
  2. 云原生分布式操作系统营造法式-云平台提供商视角
  3. Damask和abaqus晶体塑性联合仿真培训通知
  4. orecal python_python之oracle
  5. Android可以使用的直播流播放器Vitamio5.2.3
  6. 电子计算机工程专业学什么,电子与计算机工程专业主要学什么 未来从事什么工作...
  7. 专业函数绘图软件Origin
  8. 常用于教学的计算机软件,常用计算机软件对化学教与学的重要性
  9. 风控中的文本相似方法之余弦定理
  10. 最强PPT:现代化智能仓储物流解决方案