几个别人的面试题

实说,我觉得要有代码出现,思路固然非常重要,但是能快速写出正确的代码也很重要。
因为我面试的时候,就有这些要求。

1)一个数组,长度为N,为循环有序的。找出其中的最小值
所谓循环有序就是 [ 4 5 6 1 2 3] 这种,1是我们要找的。
时间复杂度你们肯定比我清楚。写出代码
顺序遍历一遍o(n);
使用折半查找 o(lgn);  


2)两个数组,长度分别为N,都有序,找到两个数组中,第N小的数字。
例如[1 2 3 4 6] [5 7 8 9 10],那么5是正确的答案。写出代码
用折半查找法,重复使用,接近o(lgn)


3)一个数组长度为N,找出其中K个最大的数字。写出代码。
方法一:利用折半查找,o(n*klgk);
方法二:利用小根堆,不考虑建堆的过程,只考虑调整是 o(n*lgk);   

我不是来求代码的,我是来放分的。
既然如此,那就给分吧。
说实话,现场写,的确有一定的难度。

(像改进的折半查找,小根堆的算法,以前,写过,直接搬了过来)。


#include <iostream>

using namespace std;


//使用折半查找法,使问题规模不断缩小
int binarySearchMin(int list[], int n) {
	int low = 0;
	int high = n -1;
	int mid;

	if(list[low] < list[high]) return  list[low];

	//low 始终位于循环数组的大的部分,high始终位于数组循环数组的小的部分
	while(low <= high) {		
		if(low + 1 == high && list[low] >= list[high]){
			return list[high];
		}
		
		mid = low + ((high - low) >> 1);		
		//cout << low << ", " << mid << ", " << high << endl;
		if(list[low] <= list[mid]) {
			low = mid;
		}else if( list[low] > list[mid]) {
			high = mid;
		}
	}

}

int modifiedBinarySearch(int list[], int n, int target) {
	int low = 0;
	int high = n - 1;
	int mid;

	while(low <= high) {
		mid = low + ( (high - low) >> 1);
		
		if(list[mid] > target) {
			high = mid -1;
		} else if(list[mid] < target) {
			low = mid + 1;
		} else {
			break;
		}
	}
	
	if(list[mid] <= target) { 
		while(mid < n && list[mid] <= target) ++mid;

		return mid;
	} 
	
	if(list[mid] > target) {
		while(mid >= 0 && list[mid] > target) --mid;

		return mid + 1;
	}
}

// 可以查找任意两个有序数组的中的第K大的数;
int  find_kth(int list1[], int len1, int list2[], int len2, int k) {
	int i = 0;
	int j = 0;

	while(len1 > 0 && len2 > 0) {
		i = modifiedBinarySearch(list1, len1, list2[j]);
		if(i >= k)  {
			return list1[k-1];
		} else if( i < k){
			k -= i;
			j = modifiedBinarySearch(list2, len2, list1[i]);
			if(j >= k){
				return list2[k-1];
			}

			list1 += i;
			len1  -= i;
			list2 += j;
			len2  -= j;
			k     -= j;			
		}
	}
	
	if(len1 > 0) {
		return list1[k-1];
	}

	if(len2 >0) {
		return list2[k-1];
	}
	
}


int compare(const void *first, const void *second) {
	return *(int *)first - *(int *)second; 
}

// 使用改进的二分查找
void maxiumKNums(int list[], int len, int nums[], int k) {
	for(int i = 0; i < k; ++i) {
		nums[i] = list[i];
	}
	qsort(nums, k, sizeof(nums[0]), compare);		

	for(int i = k; i < len; ++i) {		
		if(list[i] <= nums[0]) continue;
		int j = modifiedBinarySearch(nums, k, list[i]);		
		--j;
		for( int t  = 0; t < j; ++t) {
			nums[t] = nums[t + 1];
		} 
		nums[j] = list[i];		
	}

}


#define left(i)   (((i)<<1) + 1)  
#define right(i)  (((i)<<1) + 2)

void exchange(int* a, int* b) {  
    int tmp;  
  
    tmp = *a;  
    *a = *b;  
    *b = tmp;  
}  

void minHeapify(int a[], int i, int len) {  
    int l;  
    int r;  
    int least;  
    int tag;    //to indicate the changeable.  
  
    do{  
        tag = 0;  
        l = left(i);  
        r = right(i);  
        least = i;  
  
  
        if(l<len && a[least]>a[l]) least = l;  
        if(r<len && a[least]>a[r]) least = r;  
  
        if(least!=i) {  
            exchange(a+least, a+i);  
            i = least;  
            tag = 1;  
        }  
    }while(tag);  
  
} 

void buildMinHeap(int a[],  int len) {  
    int i;  
    int half = (len>>1) -1;  
    for(i= half; i >= 0; i--) {  
        minHeapify(a, i, len);          
    }  
}  

//使用小根堆处理
void maxiumKNums2(int list[], int len, int nums[], int k) {
	for(int i = 0; i < k; ++i) {
		nums[i] = list[i];
	}
	buildMinHeap(nums, k);
	

	for(int i = k; i < len; ++i) {		
		if(list[i] <= nums[0]) continue;
		nums[0] = list[i];
		minHeapify(nums, 0, k);			
	}

}



int main(int argc, char *argv[]) {

	cout << " test for question 1" << endl;
	int list[] = {4, 5, 6, 1, 2, 3, 4,};
	int len = sizeof(list)/sizeof(list[0]);
	cout<< binarySearchMin(list, len) << endl;

	cout << "test for question 2:" << endl;
	int list1[] = {1, 2, 3, 4, 6, 10, 12, 15};
	int list2[] = {4, 5, 7, 8, 9, 11, 13, 14, 16};
	int len1 = sizeof(list1)/sizeof(list1[0]);
	int len2 = sizeof(list2)/sizeof(list2[0]);
	int k = len1 + len2;
	for(int i = 1; i <= k; ++i) {
		cout << i << "th = " << find_kth(list1, len1, list2, len2, i) << endl;
	}

	
	int list3[] = {5, 3, 2, 1, 6, 8, 9, 7, 4, 10, 15, 16, 18, 17, 14, 12, 11, 13};
	int nums[100];
	int len3 = sizeof(list3) / sizeof(list3[0]);

	cout << "test for question 3 (1): using modifiedBinary search" << endl;
	for(int i = 1; i <= len3; ++i) {
		maxiumKNums(list3, len3, nums, i);		
		cout << i << " big nums :" ;
		for(int j = 0; j < i; ++j) {
			cout << nums[j] << ", "; 
		}  
		cout << endl;
	}
	
	cout << "test for question 3 (2): using heap " << endl;
	for(int i = 1; i <= len3; ++i) {
		maxiumKNums2(list3, len3, nums, i);
		//qsort(nums, i, sizeof(nums[0]), compare);
		cout << i << " big nums :" ;
		for(int j = 0; j < i; ++j) {
			cout << nums[j] << ", "; 
		}  
		cout << endl;
	}
	

	return 0;
}


运行结果:





关于这几个问题的更多讨论, 请参阅:http://topic.csdn.net/u/20120908/22/66283a86-1ed5-43d3-b99b-9a8126488dc4.html


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值