先说我对第一题的想法:
很yy的思路是:第一次循环找到最大值,第二次循环找到第二大值(不是最大值而大于其他值)。总时间是2n,
算是O(n)的。
另外一个想法是用基数排序,返回排序后的第二个位置的数值。总时间为O(cn),c为这些数的最长位数。
第二题。。。
我一直用它:)
用一个union类型
+
一个变长数组
比如
http://blog.codingnow.com/2008/06/variable_length_array.html
也可以参考lua的代码
1.如何在O(n)时间内找到一个整数数组中的第二大元素?
2.如何用c语言实现一个栈:
要求:1)栈的数据类型有多种,比如int,char或者函数指针等。
2)栈的大小不确定(即能够动态的分配空间)。
用heapsort可以达到O(nlgn)
但既然是整数数组,可以用Quicksort-based selection来达到O(n)(参考<Algorithm in Java>原版
P342)
static ITEM select(ITEM [] a, int l, int r, int k)
{
while(r>l)
{
int i = partition(a, l ,r); //partition后,比a[i]小的都在i左边,比a[i]大的都在
i右边。
if(i==k) return a[k];
if(i<k) r=i-1; //从l到i-1做selection
if(i>k) l=i+1; //从i+1到r做selection
}
}
书中的证明是,对于足够大的随机数组,每次partion会把数组分成大约相等的两半,那么每次问题size缩小一般,比较次数为N+N/2+N/
4+.....+1=2N。因此为O(N)
注意select和quicksort不同,因为quicksort每次都要比较N,而select的比较次数是指数减少的,因此是O(N)而不是O
(NlgN)
在这里再推荐一下Segwick大牛的《Algorithm in Java》,真正的做到了从问题引出算法的教学形式,而不是版主说过的传统欧几里得
方法。
On 2月27日, 上午5时19分, talia <chao...@gmail.com> wrote:
> 1.如何在O(n)时间内找到一个整数数组中的第二大元素?
第二题,不是很明白题目的要求1)。我的想法,其实可以模拟C++中的stack类,只不过没有类,自己维护一个内存空间。大致实现如下:
struct stack{
size_t width; //要保存数据的宽度,比如要保存int型的话,width=sizeof(int)
void *men; //保存栈元素的空间
void *bottom, *top;
size_t size; //已经分配的空间大小
//其他可能需要的元素
}
void InitStack(size_t w){
width = w; //这个值对这个栈而言不能再修改了
//分配一个适当大小的初始空间
}
void push(void *elem, size_t width){
//先判断当前空间是否足够
memcpy(top, elem, width);
top += width;
}
void *pop(){
return (top-=width);
}
用户通过pop取数时也是通过memcpy函数。
另外,如果题目要求的是同一个栈里面可以保存不同类型的元素,那么可以这样:
struct stack{
size_t *width_array; //用来保存栈中每个元素的width,由于栈的size随时会变,所以这个数组的空间也要动态分
配
size_t index; //用来保存栈中元素的个数,在push和pop时,可以用index从width_array这个数组中存入或取
出相应的width值
size_t used_size; //累计当前栈已用的空间
//剩下的部分省略,没什么难度了吧
}
On Feb 27, 9:19 pm, talia <chao...@gmail.com> wrote:
--
Sincerely,
GongTao
2009/2/27 Stephen <step...@mail.ustc.edu.cn>:
--
Xunhao Li
A USTC Alumnus
Sent from: Edmonton Ab Canada.