面试题-在一本书的乱序页码中找缺失的页码

这是我面试A公司时碰到的算法题,题目大意是一本书缺了一页,然后书页顺序被打乱,问如何迅速找到缺失的那一页?

思路:其实就是在乱序数组里面找缺失的一个数,有以下方法

1、直接排序,然后遍历一次  时间复杂度O(NlogN),不需要额外空间

2、用bitmap思想,开一个大数组,可以用bitset以节省空间,遍历一遍该数组,出现的数字置位为1,遍历完毕后,没有置位的那一位对应的数就是缺失的数字,时间复杂度O(N),但是需要O(N)的额外空间

3、原地桶排序思想,遍历数组,如果脚标与值相等不做任何处理;否则交换该数到其值索引的那个位置,对于被占用位置的数字,采用同样的方法放到其值索引的位置,直到数组末尾,此时只有空缺的那个数为脚标的那个数的值不等于其脚标。复杂度O(N),且没有额外空间,是最佳算法

关于该算法的复杂度分析存在疑问,有一种观点认为是O(N)-O(N^2)之间,见 http://topic.csdn.net/u/20120317/16/879e94ef-a873-4de3-ba9a-5efb47f5e51b.html?seed=138344854&r=77943877#r_77943877

4、巧妙的数学方法,这是我和一个同学讨论得到的,由于知道书本的总页数,于是利用求和公式直接可以计算出不缺页的情况下的页码之和sum,缺的页码就是sum减去实际所有页码之和,妙哉。利用数组特殊性,可以避免排序的考虑,真是独辟蹊径。

算法3实现如下,以10个数字为例

#include <iostream>
using namespace std;

int main(){
	int a[10] = {3,2,4,9,6,1,0,8,7,-1};
	int temp;
	int temp_val;
	for(int i = 0; i < 10; i++){
		if(a[i] != i){
			temp_val = temp = a[a[i]];//临时变量先存储需要更换的值
			a[a[i]] = a[i];
			a[i] = temp;
			}
		while(a[temp_val] != temp_val){
			temp = a[temp_val];
			a[temp_val] = temp_val;
			temp_val = temp;
			if(temp_val == -1) break;
		}
	}
	for(int j = 0; j < 10; j++){
		cout<<a[j]<<endl;
		if(a[j] != j) cout<<"the miss number is"<<j<<endl;
	}
	return 0;
}

程序可以在O(N)时间内找到缺失的数字5,且不占用额外空间。


你可能感兴趣的:(算法,面试,存储)