算法数据结构面试分享(十一)火眼金睛,从队伍里迅速找出那唯一的一个双胞胎
题目:假设你有一个用1001 个整数组成的数组,这些整数是任意排列的,但是你知道所有的整数都在1 到1000(包括1000)之间。此外,除一个数字出现两次外,其他所有数字只出现一次。假设你只能对这个数组做一次处理,用一种算法找出重复的那个数字。如果你在运算中使用了辅助的存储方式,那么你能找到不用这种方式的算法吗?
仔细分析
看过我之前文章或者我视频教程的同学可以已近发现了除了排序的算法之外,还可以通过牺牲空间换取时间的方法来解决它。那现在我们就把可能的方法都先列出来,然后我们再比较一下优缺点。
1. 排序: 那么唯一重复的两个数肯定排列在了一起,我们再扫描这个数组,如果当前元素和上一个元素相等的话,这个元素应该就是我们要找的。那排出来的结果可能是: 1,2,3,4..., 888, 888, 889,... 1000
- 优点:看起来很清晰,
- 缺点:排序最好的复杂度能做到n logn(牺牲空间的方法先不讨论哈)
2. 计数
我们之前做过一个计数排序对吧,大概的思路是我们已知了数组元素的取值范围。这道题中,我们申明1000个空间的素组, 1对应下标0, 2对应下标1, 1000对应下标999, 当然1001个空间会更加方便。扫描原来的数组一遍,遇到一个元素我们在新的数组中对应下标位置中加1,最后必定有一个元素的次数是两次。所以统计好了只有,我们扫描计数数组也就自然得到了结构。
核心伪代码如下:
int[] count = new int[1001];
for(int index = 0; index <input.length; index++
{
count[input[index]]++;
}
for(int index = 0; index < count.length; index++)
{
if(count[index] >1) return index;
}
- 优点:线性复杂度
- 缺点:有辅助存储空间,题目当中提到应该有更好的办法
3. 借助于数学方法
严格来说,很多计算机问题最后都是数学问题。大家设想下,1-1000里每个元素出现一次,乱序的,我们对它怎么求和呢? Sum = (1+1000)*1000/2, 等差数列对吧。现在这里多出了一个元素,那我们是否知道该如何求出这个数了呢? 这个target = Sum(element in array from 0 to 1000) - (1+1000) * 1000 / 2;对吧?
看来求和就可以了?但是大家在仔细想一想,求和可能会出现什么问题吗?可能会越界,我没有去论证它,但是大家想想,如果我们把1000再放大一点,这个越界问题终究会出现的对吧?我们需要改加法为减法。避免越界
- 优点:用数学问题帮助解决,扫描一遍即可,没有辅存空间,O(n)的复杂度
- 缺点:加法可能越界,需要改加法为减法操作
伪代码:
我们现在就看着个被我们优化过的数学方法,怎么解决哈,我们已经假设输入的数组是满足条件的了哈,不做额外的检查了,大家看伪代码:
public int Find(int[] input)
{
int target = 0;
for(int index = 0; index < input.length; index++)
{
target = target + input[index] - index -1;
}
return target + input.length;
}
算法分析:
我们一起分析下上面的伪代码哈。 我们再对原数组求和的过程中,做了一点事情,每次加一个我们就减掉一个N。我们做这样一个假设,数组是排好序的(帮助大家理解), 里面有5个元素, 1, 2, 3,4,5,5。
当我们的index = 0时,target 开始等于0, target = 0 + 1 -(0) -1 = 0
当我们的index = 1时, target 还是等于 0 ,target = 0 + 2 -(1)-1 = 0,
当我们的index =2 时, target还是0, target = 0 + 3 - (2) - 1 = 0,
当我们的index = 3时, target还是0, target = 0 +4 - (3)-1=0,
当我们的index = 4时, target还是0, target = 0+5-(4)-1 = 0,
当我们的index = 5时,target之前是0, 接下来 target = 0 +5 -5-1 = -1
这个时候我们就会发现,我们要找的数 应该是 -1 +N = -1 +6 = 5.
大家可以在这个假设中,我们把顺序调整一下。这个规律是不是也满足,那我们把N放大一点,这个算法是不是也成立呢?
源代码:
public static int Find(int[] input){int target = 0;for(int index = 0; index<input.Length; index++){target += input[index] - index - 1;}return target + input.Length;}
测试方法:
好了,欢迎大家关注我的公众号,还有我的系列视频教程, 数据结构与算法 和 微软经典算法面试题辅导。大家有什么更好的解法,也欢迎讨论哈。
算法数据结构面试分享(十一)火眼金睛,从队伍里迅速找出那唯一的一个双胞胎相关推荐
- 银行信息科技岗:中原银行算法工程师面试分享
本专栏分享 计算机小伙伴秋招春招找工作的面试经验和面试的详情知识点 专栏首页:秋招算法类面经分享 主要分享计算机算法类在面试互联网公司时候一些真实的经验 Bert的模型架构讲一下? BERT模型的全称 ...
- 2023秋招中原银行算法工程师面试分享
本专栏分享 计算机小伙伴秋招春招找工作的面试经验和面试的详情知识点 专栏首页:秋招算法类面经分享 主要分享计算机算法类在面试互联网公司时候一些真实的经验 这位小伙伴 985硕 :从投简历到拿到offe ...
- 面试:如何从大量的 URL 中找出相同的 URL?
点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 来源 | http://8rr.co/FR7V 赠书:聊 ...
- 面试:如何从 100 亿 URL 中找出相同的 URL?
题目描述 给定 a.b 两个文件,各存放 50 亿个 URL,每个 URL 各占 64B,内存限制是 4G.请找出 a.b 两个文件共同的 URL. " 推荐一个艿艿写的 6000+ Sta ...
- 精选微软等公司数据结构+算法经典面试100题[1-80题]
原文转自:http://topic.csdn.net/u/20101126/10/b4f12a00-6280-492f-b785-cb6835a63dc9.html 精选微软等数据结构+算法面试100 ...
- 精选微软等公司数据结构+算法经典面试100题及答案
1.把二元查找树转变成排序的双向链表 题目: 输入一棵二元查找树,将该二元查找树转换成一个排序的双向链表. 要求不能创建任何新的结点,只调整指针的指向. 10 / \ 6 14 / \ / \ 4 8 ...
- 数据结构面试100题
引言 无私分享造就开源的辉煌. 今是二零一一年十月十三日,明日14日即是本人刚好开博一周年.在一周年之际,特此分享出微软面试全部100题答案的完整版,以作为对本博客所有读者的回馈. 一年之前的10月1 ...
- Python|每日一练|素数对|优化算法|素数|素数对:找出素数对
找出素数对 任意输入一个大于10的偶数,编程找出所有和等于该偶数的素数对 以下程序实现了这一功能,请你填补空白处内容: h = 0 def a(h): x = 0 for j in range(2, ...
- 秋招在即,你准备好了吗?BAT算法工程师面试经验分享。
本文 GitHub https://github.com/Jack-Cherish/PythonPark 已收录,有技术干货文章,整理的学习资料,一线大厂面试经验分享等,欢迎 Star 和 完善. 一 ...
最新文章
- CentOS 7 Galera Cluster安装全攻略
- http headers详解
- 卡特兰数 BZOJ3907 网格 NOIP2003 栈
- 【初赛】概率与期望学习笔记
- 【学习笔记】第一章——操作系统的中断和异常
- HTML+CSS+JS实现 ❤️圣诞抓礼物小游戏❤️
- 清华大学团队夺冠AAAI 2021国际深度元学习挑战赛
- OSChina 周日乱弹 —— 七哥的北漂日记
- HTTPS传输协议原理
- SSH中直接运行php文件
- 微信小程序API之request
- Scala基础-01-Scala环境安装及基础语法(变量,函数)
- python+selenium 处理alert弹出框
- 一台计算机连接两个投影,台式机怎么同时连接两个投影仪
- 云服务综合解决方案——云桌面
- 恒指赵鑫:04.11今日恒指早盘思路
- 这个年代,你还不知道的小白用卡攻略!!!
- 到底什么是国土空间规划?
- 固定IP地址及其重启后地址更改的解决方法
- mysql dba 工资,好大夫高级mysql dba工资待遇怎么样 - 好大夫在线 - 职友集