某面试题的回答

stereoMatching 2012-09-11 05:32:12
2)两个数组,长度分别为N,都有序,找到两个数组中,第N小的数字。
例如[1 2 3 4 6] [5 7 8 9 10],那么5是正确的答案。写出代码


这个问题是由healer_kx发起的

难得把解答写出来,可惜帖子已经结了

复杂度为logn,1,3两题我也解了,在之前的帖子上

以下是来自introduction to algorithm的算法


template<typename RandomItr>
RandomItr medium_equal(RandomItr first1, RandomItr last1, RandomItr first2, RandomItr last2)
{
typedef typename std::iterator_traits<RandomItr>::difference_type difference_type;
difference_type const len = std::distance(first1, last1);
if(len == 1) return *first1 > *first2 ? first2 : first1;
difference_type const mid = (len - 1) / 2;

RandomItr mid1 = first1 + mid;
RandomItr mid2 = first2 + mid;

if(*mid1 == *mid2) return mid1;

if(*mid1 > *mid2)
{
return medium_equal(first1, mid1 + 1, mid2 + (len - 1) % 2, last2);
}
else
{
return medium_equal(mid1 + (len - 1) % 2, last1, first2, mid2 + 1);
}
}

inline void sort_two_00()
{
int array_1[] = {1, 2, 3, 4, 6, 9};
int array_2[] = {5, 7, 8, 9, 10, 12};

std::cout<<*medium_equal(std::begin(array_1), std::end(array_1),
std::begin(array_2), std::end(array_2)) << std::endl;
}


比较麻烦的地方主要在这里

if(*mid1 > *mid2)
{
return medium_equal(first1, mid1 + 1, mid2 + (len - 1) % 2, last2);
}
else
{
return medium_equal(mid1 + (len - 1) % 2, last1, first2, mid2 + 1);
}


不知道还有没有其他的方法?
...全文
474 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
lxgwm2008 2012-09-15
  • 打赏
  • 举报
回复
int findN(int *arr1, int *arr2, int n)
{
int i = 0, j = 0, k = 0;
int result = 0;
while(k++ < n){
if(arr1[i] < arr2[j]){
result = arr1[i++];
}else{
result = arr2[j++];
}
}
return result;
}
stereoMatching 2012-09-15
  • 打赏
  • 举报
回复
[Quote=引用 22 楼 的回复:]

这个代码你编译没错误吗?你是什么环境,我在vc60中编译不过!
[/Quote]

我个人爱用的编译器是mingw4_6_2,有鉴于大部分的programmers都是在windows上写程式
所以这段程式码我有用vc2010编译过。C++11制定成标准后已经一年有多了
11比03好上太多了,有许多让人很兴奋的改进

vc60,这编译器太旧,对标准的支援远不如vc2010,vc2012来得好
如果不是工作需要,诚心建议还是换个编译器吧

vc60会编译不过关,大概是因为

std::begin(array_1), std::end(array_1)


把它改成

size_t const size = sizeof(array_1) / sizeof(size_t);
std::cout<<*medium_equal(array_1, array_1 + size,
array_2, array_2 + size) << std::endl;


应该就会动了。
smsgreenlife 2012-09-15
  • 打赏
  • 举报
回复
这个代码你编译没错误吗?你是什么环境,我在vc60中编译不过!
[Quote=引用 21 楼 的回复:]
抱歉,因为有用到iterator_traits 及 distance,所以需要多加一个<iterator>,请原谅我的疏忽
std::make_heap才需要用到include algorithm


C/C++ code

#include <algorithm>
#include <iterator>
#include <iostream>

/*
* Find ou……
[/Quote]
sjjwind 2012-09-15
  • 打赏
  • 举报
回复
用一个最大堆去维护一个优先队列,堆的大小为k,每次和堆顶元素相比,如果比堆顶元素小就pop一下,然后push这个数,扫描一遍数组,就可以从堆顶得到第k小的数,k为已知数,此算法时间复杂度为O(n)。
ryxjxyx 2012-09-15
  • 打赏
  • 举报
回复
嗯,不错的题目,顶~
stereoMatching 2012-09-15
  • 打赏
  • 举报
回复
抱歉,因为有用到iterator_traits 及 distance,所以需要多加一个<iterator>,请原谅我的疏忽
std::make_heap才需要用到include algorithm


#include <algorithm>
#include <iterator>
#include <iostream>

/*
* Find out the medium value between two sorted range
* the ranges must have the same numbers of elements
*
* complexity is log(n), n is the number of the elements
* of one of the sorted range
*/
template<typename ForwardItr>
ForwardItr medium_equal(ForwardItr first1, ForwardItr last1, ForwardItr first2, ForwardItr last2)
{
typedef typename std::iterator_traits<ForwardItr>::difference_type difference_type;
difference_type const len = std::distance(first1, last1);
if(len == 1) return *first1 > *first2 ? first2 : first1;
difference_type const mid = (len - 1) / 2;

ForwardItr mid1 = first1;
ForwardItr mid2 = first2;
std::advance(mid1, mid);
std::advance(mid1, mid);

if(*mid1 == *mid2) return mid1;

if(*mid1 > *mid2)
{
std::advance(mid1, 1);
std::advance(mid2, (len - 1) % 2);
return medium_equal(first1, mid1, mid2, last2);
}
else
{
std::advance(mid1, (len - 1) % 2);
std::advance(mid2, 1);
return medium_equal(mid1, last1, first2, mid2);
}
}

inline void sort_two_00()
{
int array_1[] = {1, 2, 3, 4, 6, 9};
int array_2[] = {5, 7, 8, 9, 10, 12};

std::cout<<*medium_equal(std::begin(array_1), std::end(array_1),
std::begin(array_2), std::end(array_2)) << std::endl;
}


>哪里,我也是最近面试才弄这些没用的东西。我自认为我扯淡,灌水比较NB,你的代码我要学习一下。
我是最近看了你的帖子才重新复习算法,再度体会到我算法学得不好,必须重头读起
我的代码只是利用template多镀上一层皮,让它变得generic而已,核心还是在算法上
healer_kx 2012-09-15
  • 打赏
  • 举报
回复
一般来说,可能缺少
《iterator》,<functional>一类的头文件。试一试。
smsgreenlife 2012-09-15
  • 打赏
  • 举报
回复
我肯定加了加了<algorithm>,但是也不行,你发一个完整的程序吧。
[Quote=引用 17 楼 的回复:]
>另外楼主的代码怎么运行不了呀,是不是缺少头文件,能不能贴一个完整的代码。
补上<algorithm>即可,里面收集了各类STL的算法,除非是特殊情况,否则想写得比
<algorithm>的算法更好,更有效率是一件非常困难的事情

13楼的思路我在一楼就已经实现
16楼的思路就是我十一楼代码



ps : STL不是C++的基础功之一吗?怎么会不晓得要补上一个algorithm……
[/Quote]
healer_kx 2012-09-15
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 的回复:]

引用 8 楼 的回复:

嗯,我结贴早了。这几天忙。

我会仔细研究你的代码的,过几天把我的代码也贴上好了。在我的Windows上呢,我懒得启动它。

你的劣势在于:。。。 。。。 。。。你的分太少了。。。我都是300分的帖子。。。

谢谢,希望看了以后能告诉我哪里错了或者写得不好
至于这第二题的解法,个人觉得不满意的地方是取余数的部分
或许有其他方法可以简化?
[/Quote]

哪里,我也是最近面试才弄这些没用的东西。我自认为我扯淡,灌水比较NB,你的代码我要学习一下。
stereoMatching 2012-09-15
  • 打赏
  • 举报
回复
>另外楼主的代码怎么运行不了呀,是不是缺少头文件,能不能贴一个完整的代码。
补上<algorithm>即可,里面收集了各类STL的算法,除非是特殊情况,否则想写得比
<algorithm>的算法更好,更有效率是一件非常困难的事情

13楼的思路我在一楼就已经实现
16楼的思路就是我十一楼代码



ps : STL不是C++的基础功之一吗?怎么会不晓得要补上一个algorithm的header?
smsgreenlife 2012-09-15
  • 打赏
  • 举报
回复
按照13楼的思想写的代码,时间复杂度为logn,我没有详细测试,大家看看有没有什么问题。
另外楼主的代码怎么运行不了呀,是不是缺少头文件,能不能贴一个完整的代码。

#include <stdio.h>

int search_mid(int *a1, int *a2, int len)
{
if(len==1)
{
return (*a1<*a2)?*a1:*a2;
}
if(len==2)
{
if(*a1<*a2)
{
return (a1[1]<*a2)?a1[1]:*a2;
}
else
{
return (a2[1]<*a1)?a2[1]:*a1;
}
}

int mid = len/2;
if(a1[mid]==a2[mid])
{
return a1[mid];
}

if(a1[mid]<a2[mid])
{
return search_mid(a1+mid, a2, (len+1)/2);
}
else
{
return search_mid(a2+mid, a1, (len+1)/2);
}
}

void main()
{
int a1[5] = {11,112,113,114,1116};
int a2[5] = {15,17,18,91,110};
printf("%d\n", search_mid(a1, a2, 5));
}
npuhuxl 2012-09-13
  • 打赏
  • 举报
回复
应该有个log(n)的算法:
比较两个数组N/2位置的数
如果 a[N/2] > b[N/2]
那么第N个数肯定是在 b[N/2~N]和a[0~N/2]这两个区间内;因为b[0~N/2]小于b[N/2],这个区间内的数肯定不是第N个数。而去掉b[0~N/2]之后,所求数正好是两个N/2区间的第N/2数。
如果 a[N/2] == b[N/2] 那么这个数正好是所求数
如果 a[N/2] < b[N/2] 和大于的情况相反。
算法大致是这样,因为N不一定2的倍数,所以可能需要考虑一些细节问题。
smsgreenlife 2012-09-13
  • 打赏
  • 举报
回复
我有时间复杂度为logn平方的算法。
stereoMatching 2012-09-13
  • 打赏
  • 举报
回复
3)一个数组长度为N,找出其中K个最大的数字。写出代码。
之前的实做有使用buffer,最近看了STL的partial_sort后才知道有更好的解法
STL的演算法中,跟跟排序有关的地方我之前还没读到,趁现在好好的读一读


template<typename RandomItr>
void nth_max(RandomItr first, RandomItr last, size_t number)
{
if(first == last) return;
if(static_cast<size_t>((last - first)) < number ) return;

typedef typename std::iterator_traits<RandomItr>::value_type value_type;
std::make_heap(first, first + number, std::greater<value_type>() );

RandomItr current = first + number;

while(current != last)
{
if(*first < *current)
{
std::swap(*first, *current);
std::make_heap(first, first + number, std::greater<value_type>() );
}
++current;
}
}


这其实是sgi stl中partial_sort的思路
最大的不同是我最后没有调用sort_heap,以及采用的不是maximum heap而是minimum heap
stereoMatching 2012-09-13
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 的回复:]

嗯,我结贴早了。这几天忙。

我会仔细研究你的代码的,过几天把我的代码也贴上好了。在我的Windows上呢,我懒得启动它。

你的劣势在于:。。。 。。。 。。。你的分太少了。。。我都是300分的帖子。。。
[/Quote]
谢谢,希望看了以后能告诉我哪里错了或者写得不好
至于这第二题的解法,个人觉得不满意的地方是取余数的部分
或许有其他方法可以简化?
hackbuteer1 2012-09-12
  • 打赏
  • 举报
回复
如果题目的时间复杂度要求是log(n), 那么这个题的解题思路应该是要用跟二分搜索相关的思路吧
hackbuteer1 2012-09-12
  • 打赏
  • 举报
回复
如果题目的时间复杂度要求是log(n), 那么这个题的解题思路应该是要用跟二分搜索相关的思路吧
stereoMatching 2012-09-12
  • 打赏
  • 举报
回复
归并排序?merge sort?
merge sort的时间复杂度是O(n)
可是这题的时间复杂度,要求是log(n)
必须跟binary search一样,每次都prune掉一半左右的数据
lzjamao 2012-09-12
  • 打赏
  • 举报
回复
不明白
healer_kx 2012-09-12
  • 打赏
  • 举报
回复
嗯,我结贴早了。这几天忙。

我会仔细研究你的代码的,过几天把我的代码也贴上好了。在我的Windows上呢,我懒得启动它。

你的劣势在于:。。。 。。。 。。。你的分太少了。。。我都是300分的帖子。。。
加载更多回复(4)

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧