寻找数组中缺少的整数(Find the missing integer)

数组a中含有N个元素,其元素属于[0,N]之间,且不存在重复的元素,请你找出数组中缺失的元素(因为[0,N]之间有N+1个元素,而数组只能存储N个元素,所以必然缺少一个元素)。其中对数组的操作满足下列的条件:不能在常数时间内读取数组中的元素,但是可以读取数组中元素的某一个bit值,能够在常数时间内交换数组的两个元素的位置。请设计一种算法使其能够在线性时间内找出数组中缺失的元素。(N=2^k)

An array a[] contains all of the integers from 0 to N, except 1. However, you cannot access an element with a single
operation. Instead, you can call get(i, k) which returns the kth bit of a[i] or you can call swap(i, j) which
swaps the ith and jth elements of a[]. Design an O(N) algorithm to find the missing integer. For simplicity, assume N is a power of 2

算法设计:有题设可知,[0,N]之间奇数和偶数个数之差等于1,如果缺失偶数,则奇数和偶数的数目相等,反之缺失奇数。如何判断元素的奇偶呢?题设给出只能在常数时间内访问数组元素的某个bit值,所以只需看元素的最后一个bit为0还是1即可,这样通过一次扫描数组可以排除n/2个元素。利用此法(判断0,1个数的多少)我们就可以找出缺失的元素。重复上述操作即可。

算法性能分析:

第一次扫面元素判断奇偶,需要循环n次,从而排除n/2个元素,因此第二次循环需要循环n/2次,一次类推,总共的循环次数为T

T=n+n/2+n/4+n/8+……+1=O(n),为此达到了题目的要求。

算法实现:

<span style="font-size:10px;">void swap(int* a, int i, int j)
{
	int temp = a[i];
	a[i] = a[j];
	a[j] = temp;
}
int get(int* a, int i, int k)
{
	int res = a[i]>>k & 1;
	return res;
}
int Find_the_missing_integer(int* a, int low, int high)
{
	int res = 0;
	int power = 1;
	int count0 = 0;
	int count1 = 0;
	int n = high-low+1;
	int pointer0 = 0;
	int i=0;
	while(n>0)
	{
		for(int j=low; j<=high;j++)
		{
			if(get(a,j,i) == 0)
			{
				count0++;
				swap(a,j,pointer0);
				pointer0++;
			}
			else
			{
				count1++;
			}
		}
		if(count0>count1)
		{
			res = res + power*1;
			low = pointer0;
			n = count1;
		}
		else
		{
			res = res + power*0;
			high = pointer0 - 1;
			pointer0 = low;
			n = count0;
		}
		power = power*2;
		count0 = 0;
		count1 = 0;
		i++;
	}
	return res;
}</span>

算法解释:find_the_missing_intger,函数中利用pointer记录最后一个元素的0还是1的分界点,然后每次都循环扫面满足我们要求的那一部分元素,直到最终没有元素位置。

测试代码:

#include <iostream>
using namespace std;
void swap(int* a, int i, int j);
int get(int* a, int i, int k);
int Find_the_missing_integer(int* a, int low, int high);
void main()
{
	int a[]={1,2,3,4,5,6,7,0};
	cout<<Find_the_missing_integer(a,0,7);
}

如有不清楚的地方欢迎讨论。

时间: 2024-10-01 19:56:22

寻找数组中缺少的整数(Find the missing integer)的相关文章

[ALGO-49] 寻找数组中最大值

算法训练 寻找数组中最大值 时间限制:1.0s   内存限制:512.0MB 问题描述 对于给定整数数组a[],寻找其中最大值,并返回下标. 输入格式 整数数组a[],数组元素个数小于1等于100.输出数据分作两行:第一行只有一个数,表示数组元素个数:第二行为数组的各个元素. 输出格式 输出最大值,及其下标 样例输入 3 3 2 1 样例输出 3 0 说明:蓝桥杯官网上的"样例输入"格式不对,我在这里改成了对的格式 import java.util.Scanner; public cl

第2章 数字之魅——寻找数组中的最大值和最小值

寻找数组中的最大值和最小值 问题描述 对于一个由N个整数组成的数组,需要比较多少次才能把最大和最小的数找出来呢? 分析与解法 [解法一] 可以把寻找数组中的最大值和最小值看成是两个独立的问题,我们只要分别求出数组的最大值和最小值即可解决问题.最直接的做法是先扫描一遍数组,找出最大的数以及最小的数.这样,我们需要比较2*(N-1)次才能找出最大的数和最小的数.代码如下: 1 package chapter2shuzizhimei.findminmax; 2 /** 3 * 寻找数组中的最大值和最小

[经典算法题]寻找数组中第K大的数的方法总结

[经典算法题]寻找数组中第K大的数的方法总结 责任编辑:admin 日期:2012-11-26 字体:[大 中 小] 打印复制链接我要评论 今天看算法分析是,看到一个这样的问题,就是在一堆数据中查找到第k个大的值. 名称是:设计一组N个数,确定其中第k个最大值,这是一个选择问题,当然,解决这个问题的方法很多,本人在网上搜索了一番,查找到以下的方式,决定很好,推荐给大家. 所谓"第(前)k大数问题"指的是在长度为n(n>=k)的乱序数组中S找出从大到小顺序的第(前)k个数的问题.

2.10 用最少次数寻找数组中的最大值和最小值[find min max of array]

[本文链接] http://www.cnblogs.com/hellogiser/p/find-min-max-of-array.html [题目] 对于一个由N个整数组成的数组,需要比较多少次才能把最大和最小的数找出来呢? [分析] 1. 遍历两次数组,分别找出最大值和最小值,需要进行 2N 次比较. 2. 将数组中的元素分组,按顺序将数组中相邻的两个数分在同一组,用Max和Min来存储最大值和最小值.同一组比较完之后,较小的数与当前的最小值比较,如该数小于当前最小值,更新Min:较大的数与当

寻找数组中重复次数最多的数

#include<iostream> #include<map> using namespace std; int helper(const int a[],const int n) { map<int,int> m; for(int i = 0;i<n;i++) m[a[i]]++; map<int,int>::iterator comp = m.begin(); for( map<int,int>::iterator it = comp

c语言:将数组中n个整数按相反顺序存放。

将数组中n个整数按相反顺序存放. 解:程序1: #include<stdio.h> int inv(int x[], int n) { int temp, i, j, m = (n - 1) / 2; for (i = 0; i <= m; i++) { j = n - 1 - i; temp = x[i]; x[i] = x[j]; x[j] = temp; } return; } int main() { int i, a[10] = { 1,2,3,4,5,6,7,8,9,10 }

寻找数组中的第K大的元素,多种解法以及分析

遇到了一个很简单而有意思的问题,可以看出不同的算法策略对这个问题求解的优化过程.问题:寻找数组中的第K大的元素. 最简单的想法是直接进行排序,算法复杂度是O(N*logN).这么做很明显比较低效率,因为不要求别的信息只要计算出第K大的元素.当然,如果在某种情况下需要频繁访问第K大的元素就可以先进行一次排序在直接得出结果. 第一种方式是这样,用选择排序,冒泡法,或者交换排序这类的排序,对前K个元素进行排序.这三种算法也许不是最快的排序算法.但是都有个性质:计算出最大(小)的元素的算法复杂度是O(N

编程之美2.10 寻找数组中的最大值和最小值

这个问题其实很容易解决,就是循环遍历一遍数组,然后找到数组中存在的最大值和最小值就可以了,书中主要讨论的问题是比较次数较小的方法,不过,书中已经证明了,无论用什么方法最少的比较次数也就是循环遍历一遍的比较,结果是O(1.5N)的,所以,很容易的可以解决这个问题. 第一种方法: 函数声明: void DutFindMaxAndMinInArray_1(int*, int, int&, int&); 源代码如下: /*基本的解法寻找最大值和最小值*/ bool _DutFindMaxAndMi

编程之美3:寻找数组中的最大值和最小值以及最大值和次大值

很开心,这是今天的第三篇文章啦!下午健身也感觉非常过瘾,托付宿舍妹子从日本代购的护肤品也到了.耳边漂浮着Hebe田馥甄的<魔鬼中的天使>文艺的声线,一切都好棒,O(∩_∩)O哈哈~.爱生活,爱音乐,爱运动,额,当然还有要爱学习啦!加油(^ω^) 额,扯远了.第三篇是关于寻找数组中的最大值和最小值.第一次看到这个题目的时候,楼主稍微鄙视了一下,因为觉得这个题目有什么好做的.但是楼主还是看了看<编程之美>上的写的,发现还是有必要记录一下,不一样的思考方式.很赞!大家和楼主一起哦,Are