实说,我觉得要有代码出现,思路固然非常重要,但是能快速写出正确的代码也很重要。
因为我面试的时候,就有这些要求。
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);
我不是来求代码的,我是来放分的。
既然如此,那就给分吧。
说实话,现场写,的确有一定的难度。
因为我面试的时候,就有这些要求。
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