http://www.lintcode.com/en/problem/find-the-missing-number/#

Find the Missing Number

Given an array contains N numbers of 0 .. N, find which number doesn't exist in the array.

 
Example

Given N = 3 and the array [0, 1, 3], return 2.

Challenge

Do it in-place with O(1) extra memory and O(n) time.

题意:这是一道面试题目,题意是说给你个数组0-n,让你找出里面唯一缺少的那个数。

思路:我的第一思路是二叉堆,但好像南辕北辙了。可以直接利用快排,少于nlgn的时间就可以找到那个数。利用数值与数组下标的对应关系,数组的数排好序后分两段,左端数值与下标相同,右端则数值比下标大一。不需要排序,只需要借助快排,就可以不断的递归二分这个数组,找出那个奇点。

可以参考两篇类似的博文:

http://www.cnblogs.com/jiu0821/p/4138558.html

http://www.cnblogs.com/jiu0821/p/4505480.html

代码:tle

 class Solution {
public:
/**
* @param nums: a vector of integers
* @return: an integer
*/
int j18(vector<int> &nums,int i,int j){
int x=nums[i];
while(){
while(i<j&&nums[j]>x) j--;
if(i<j) nums[i]=nums[j];
else{
nums[i]=x;
return i;
}
while(i<j&&nums[i]<x) i++;
if(i<j) nums[j]=nums[i];
else{
nums[j]=x;
return j;
}
}
}
int findMissing(vector<int> &nums) {
// write your code
int i=,j=nums.size()-,y;
while(y=j18(nums,i,j),){
if(nums[y]==y) i=y+;
else j=y-;
if(i>j) return i;
}
}
};

之所以tle是因为原题目给有特殊数据,代码里默认快排是x为第一个数,遇到最坏情况,复杂度n*n。下面把x改为最后一个数,就ac了。

ac 279ms

 class Solution {
public:
/**
* @param nums: a vector of integers
* @return: an integer
*/
int j18(vector<int> &nums,int i,int j){
int x=nums[j];
while(){
while(i<j&&nums[i]<x) i++;
if(i<j) nums[j]=nums[i];
else{
nums[j]=x;
return j;
}
while(i<j&&nums[j]>x) j--;
if(i<j) nums[i]=nums[j];
else{
nums[i]=x;
return i;
}
}
}
int findMissing(vector<int> &nums) {
// write your code
int i=,j=nums.size()-,y;
while(y=j18(nums,i,j),){
if(nums[y]==y) i=y+;
else j=y-;
if(i>j) return i;
}
}
};

当然,这只是投机取巧,也会遇到最坏情况。相对好的方法是取中间或者取随机数。下面是取中间的实现例子:214ms

 class Solution {
public:
/**
* @param nums: a vector of integers
* @return: an integer
*/
int j18(vector<int> &nums,int i,int j){
int x=nums[(i+j)>>];
nums[(i+j)>>]=nums[i];
while(){
while(i<j&&nums[j]>x) j--;
if(i<j) nums[i]=nums[j];
else{
nums[i]=x;
return i;
}
while(i<j&&nums[i]<x) i++;
if(i<j) nums[j]=nums[i];
else{
nums[j]=x;
return j;
}
}
}
int findMissing(vector<int> &nums) {
// write your code
int i=,j=nums.size()-,y;
while(y=j18(nums,i,j),){
if(nums[y]==y) i=y+;
else j=y-;
if(i>j) return i;
}
}
};

最后,说下最直接简单的办法,以空间换时间,加一个bool数组再哈希就可以了。135ms

 class Solution {
public:
/**
* @param nums: a vector of integers
* @return: an integer
*/
int findMissing(vector<int> &nums) {
// write your code
int len=nums.size();
bool numb[len+];
memset(numb,,sizeof(numb));
for(int i=;i<len;i++) numb[nums[i]]=true;
for(int i=;i<=len;i++){
if(numb[i]==false)
return i;
}
}
};

经好心博友提醒,最优雅的法子横空出世--异或。两个相同的数异或为0。故而把原数组与0-n异或和就为最后的结果。131ms

 class Solution {
public:
/**
* @param nums: a vector of integers
* @return: an integer
*/
int findMissing(vector<int> &nums) {
// write your code
int len=nums.size(),x=;
for(int i=;i<len;i++) x^=nums[i];
for(int i=;i<=len;i++) x^=i;
return x;
}
};

看到了官方给的答案---借助桶排序。思路是:从0开始遍历到n-1,每次当a[i]!=i的时候,将a[i]与a[a[i]]交换,大于边界的话,就丢掉,直到无法交换位置。那个特殊值有两种情况,一种是在0~n-1之间,那么经过a[i]与a[a[i]]交换,最后以特殊值为下标的位置上一定为n;另一种是特殊值为n,那么a[i]与a[a[i]]交换对于0~n-1都满足。故而只要跟踪边界值n即可,跟踪值x应初始化为n,以对应第二种情况。详情见代码:

 class Solution {
public:
/**
* @param nums: a vector of integers
* @return: an integer
*/
int findMissing(vector<int> &nums) {
// write your code
int len=nums.size(),x=len;
for(int i=;i<len;i++){
while(nums[i]!=i){
if(nums[i]==len){
x=i;
break;
}else{
int tmp=nums[nums[i]];//注意这个地方,不能用三个异或来交换值,因为nums[nums[i]]里的nums[i]是变量。
nums[nums[i]]=nums[i];
nums[i]=tmp;
}
}
}
return x;
}
};

一道面试题Lintcode196-Find the Missing Number的更多相关文章

  1. Leetcode-268 Missing Number

    #268.  Missing Number Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find ...

  2. Missing number

    Missing number 题目: Description There is a permutation without two numbers in it, and now you know wh ...

  3. 【LeetCode】268. Missing Number

    Missing Number Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one ...

  4. PHP递归创建多级目录(一道面试题的解题过程)

    今天看到一道面试题,要写出一个可以创建多级目录的函数: 我的第一个感觉就是用递归创建,具体思路如下: function Directory($dir){ if(is_dir($dir) || @mkd ...

  5. 关于Java类加载双亲委派机制的思考(附一道面试题)

    预定义类加载器和双亲委派机制 JVM预定义的三种类型类加载器: 启动(Bootstrap)类加载器:是用本地代码实现的类装入器,它负责将 <Java_Runtime_Home>/lib下面 ...

  6. 一道面试题比较synchronized和读写锁

    一.科普定义 这篇博文的两个主角“synchronized”和“读写锁” 1)synchronized 这个同步关键字相信大家都用得比较多,在上一篇“多个线程之间共享数据的方式”中也详细列举他的应用, ...

  7. 一道面试题:按照其描述要求用java语言实现快速排序

    回来想了想,写出了如下的程序: /** * 一道面试题,按照其描述要求进行快速排序(英文的,希望理解是对的..) * 要求:和一般的快速排序算法不同的是,它不是依次交换pivot和左右元素节点(交换2 ...

  8. hdu 5166 Missing number

    题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5166 Missing number Description There is a permutatio ...

  9. <转>一道面试题比较synchronized和读写锁

    一.科普定义(原文:http://903497571.iteye.com/blog/1874752) 这篇博文的两个主角“synchronized”和“读写锁” 1)synchronized 这个同步 ...

随机推荐

  1. matlab 中的function定义. 用最简单的例子说明.

    function y=myfunction(a,b)其中a,b是输入函数的参数,y是函数返回的值.当需要返回多个值时,可以将y看作一个数组,或者直接将函数的开头写成如function [x,y]=my ...

  2. 配置 VS Code 调试 JavaScript

    原文:配置 VS Code 调试 JavaScript 1. 安装 Debugger for Chrome 扩展.Open in Browser  扩展.View In Browser 扩展 2.用v ...

  3. c++深拷贝/浅拷贝

    拷贝构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构建及初始化.其唯一的参数(对象的引用)是不可变的(const类型).此函数经常用在函数调用时用户定义类型的值传递及返 ...

  4. Centos6.5 恢复误删的系统面板

    在CentOS6.5下往面板上拖应用程序时,手贱了,点了"Delete This Panel".结果就悲剧了~面板不见了! 从网上搜了一下解决方法,列举一下. 1.新建面板 如果下 ...

  5. Data_Structure01-绪论作业

    一.作业题目 仿照三元组或复数的抽象数据类型写出有理数抽象数据类型的描述 (有理数是其分子.分母均为整数且分母不为零的分数). 有理数基本运算: 构造有理数T,元素e1,e2分别被赋以分子.分母值 销 ...

  6. 谈谈对zynq的浅显理解

    zynq并不能说是一个嵌入arm核的FPGA.从它的启动过程就可以发现,绝对是arm主导的,所以称它为以高性能FPGA为外设的双核arm或许更为合适.以下是优势: 第一个:开发环境的大集成.从hls到 ...

  7. Django模板输出Dict所有Value的效率问题

    一次跑偏之旅!   对于一个惯用C++的人来说,使用Python这种语言的一大障碍就是许多集合类型的操作效率并不如传统的经典数据结构那样直观可见,以及许多实际上涉及到内存分配.对象复制之类的耗时操作被 ...

  8. bzoj2184: 任意图的匹配

    Description 每天都要考,每天都要讲,大家注意力都集中不起来了,每天听解题报告时都有人交头接耳(也包括我,呵呵).这样做大大的影响的学习效率(可能吧).于是,有些好奇心重的同学就开始研究,怎 ...

  9. 一次hadoop集群机器加内存的运维过程

    由于前期的集群规划问题,导致当前Hadoop集群中的硬件并没有完全利用起来.当前机器的内存CPU比例为2G:1core,但一般的MapReduce任务(数据量处理比较大,逻辑较复杂)的MR两端都需要将 ...

  10. Oracle调优之buffer pool相关

    一个oracle block与data buffer中的一个buffer对应.用户进程(server process)负责读取磁盘上的block到data buffer cache中,DEWn进程负责 ...