您的位置:首页 > 其它

写一段程序,找出数组中第k大小的数,输出数所在的位置。

2012-06-28 20:36 381 查看
写一段程序,找出数组中第k大小的数,输出数所在的位置。例如{2,4,3,4,7}中,第一大的数是7,位置在4。第二大、第三大的数都是4,位置在1、3随便输出哪一个均可。函数接口为:int find_orderk(const int * narry, const int n, const int k)

要求算法复杂度不能是O(n^2)

参考答案:

1

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

/***************************************

输入: n:数组元素的个数 k:第几大的数

a:待查找的数组元素

****************************************/

#define N 100

void Rand_select(int*, int, int);

int partition(int*, int, int);

int swap(int&, int&);

int k, ans;

int main()

{

int n, a
, i;

while (scanf("%d%d", &n, &k) != EOF)

{

srand(time(NULL));

k--;

for (i = 0; i < n; i++)

scanf("%d", a + i);

Rand_select(a, 0, n - 1);

printf("%d/n", ans);

}

return 0;

}

void Rand_select(int a[], int p, int q)

{

int m;

if (p <= q)

{

m = partition(a, p, q);

if (k == m)

{

ans = a[m];

return;

}

else if (k > m)

Rand_select(a, m + 1, q);

else

Rand_select(a, p, m - 1);

}

}

int partition(int a[], int p, int q)

{

int last, i;

if (q != p)

swap(a[rand() % (q - p) + p], a[p]);

for (i = p + 1, last = p; i <= q; i++)

if (a[i] >= a[p])

swap(a[i], a[++last]);

swap(a[last], a[p]);

return last;

}

int swap(int &p, int &q)

{

int temp = p;

p = q;

q = temp;

return 0;

}

2可以先用快速排序进行排序,其中用另外一个进行地址查找 代码如下,在VC++6.0运行通过。

//快速排序

#include <iostream>

using namespace std;

int Partition (int *L,int low,int high)

{

int temp = L[low];

int pt = L[low];

while (low < high)

{

while (low < high && L[high] >= pt)

--high;

L[low] = L[high];

while (low < high && L[low] <= pt)

++low;

L[low] = temp;

}

L[low] = temp;

return low;

}

void QSort (int *L,int low, int high)

{

if (low < high)

{

int pl = Partition (L,low,high);

QSort (L, low, pl - 1);

QSort (L, pl + 1, high);

}

}

int main ()

{

int narry[100],addr[100];

int sum = 1, t;

cout << "Input number:" << endl;

cin >> t;

while (t != -1)

{

narry[sum] = t;

addr[sum - 1] = t;

sum++;

cin >> t;

}

sum -= 1;

QSort (narry,1,sum);

for (int i = 1; i <= sum; i++)

cout << narry[i] << '/t';

cout << endl;

int k;

cout << "Please input place you want:" << endl;

cin >> k;

int aa = 1;

int kk = 0;

for (;;)

{

if (aa == k)

break;

if (narry[kk] != narry[kk + 1])

{

aa += 1;

kk++;

}

}

cout << "The NO." << k << "number is:" << narry[sum - kk] << endl;

cout << "And it's place is:" ;

for (i = 0;i < sum;i++)

{

if (addr[i] == narry[sum - kk])

cout << i << '/t';

}

return 0;

}

难得啊,居然在今天看到这个题。我去年笔试baidu的时候也作过,当时写的是这个答案,高手分析下:

#include <math.h>

#include <time.h>

#include <string>

#include <iostream>

#include <vector>

using namespace std;

#define n 10

#define k 5

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

{

srand( (unsigned )time(NULL) );

if ( k > n )

{

cout << "error!"<< endl;

return 1;

}

vector<int> src;

cout << "源" << n << "个数据如下:" << endl;

for ( int i = 0; i < n; i++ )

{

src.push_back( rand() );

cout << src[i] << " ";

}

vector<int> maxNum; //顺序存入最大k个数,第一个为最大的,最后一个为第k大

for ( i =0; i < k; i++ )

{

maxNum.push_back(-999999); //初始化maxNum,k个-9999999

}

for ( i = 0; i < n; i++ )

{

for ( int j = 0; j < maxNum.size(); j++ )

{

if ( src[i] >= maxNum[j]) //比当前的大,则放入当前位置,后面的数字依次后退

{

for ( int i1 = maxNum.size()-1; i1 > j; i1-- )

{

maxNum[i1] = maxNum[i1-1];

}

maxNum[j] = src[i];

break;

}

}

}

cout << endl << “第” << k << “大的数字为:” << maxNum[k-1] << endl;

return 0;

}

分析:算法对n个数字只访问一次,此部分的时间复杂度为O(n);但每访问一次,须与k个数字分别比较,所以总的时间渐复杂度为O(n*k)

思想:1.consider if(k>n) exit(0)

2.if number n is a big one, use pile/stack sort

3.if number n is a small one ,use quick sort;

4;find your k number and print in the screen;

find_orderk(const int* narry,const int n,const int k)

{

if(n>k) exit (0);

sort(*narry);

for(i=0;i<n;i++)

if(i=k) return narry[k]; /*the number of the k is similiar to point*/

}

=================================================================== 函数功能:返回一个第K小的元素(采用快排思想)

参数:(T a[]目标数组 || int l左边界 || int r右边界 || int k第几小元素)

================================================================= template <class T>

T select(T a[], int l, int r, int k)

{

if(l >= r) return a[l]; //参数错误直接返回

int i = l;

int j = r+1;

T pivot = a[i];

while(true)

{

do

{

i = i + 1;

}while(a[i] > pivot);

do

{

j = j - 1;

}while(a[j] < pivot);

if(i >= j)

{

break;

}

Swap(a[i], a[j]);

}

if(j - l + 1 == k) //如果当前基准适合的位置刚好是K的话,则满足了条件 返回基准值

{

return pivot;

}

a[l] = a[j];

a[j] = pivot;

if(j - l + 1 < k)

{

return select(a, j+1, r, k-j+l-1); //如果基准当前位置在K的左边则对右进行快排

}

else

{

return select(a, l, j-1, k); //如果基准当前位置在K的右边则对左进行快排

}

}

分析程序:

#include<stdio.h>

class A

{

public:

static int numA;

A()

{

num++;

};

~A()

{

num--;

};

virtual void print(void)

{

printf("class A, mum:%d/n", num);

}

void test(void)

{

printf("class A test/n");

print();

}

};

class B:public A

{

public:

static int numB;

B()

{

num--;

};

~B()

{

};

virtual void print()

{

printf("class B, num:%d/n", num);

}

void test(void)

{

printf("class B test/n");

print();

}

};

class C

{

public:

virtual void print()

{

printf("class B/n");

}

};

int A::numA = 0;

int B::numB = 0;

void main()

{

B b;

b.print();

b.test();

printf("1/n");

A *a;

B *p= new(class B);

p->print();

p->test();

printf("1/n");

a = p;

a->print();

a->test();

delete(a);

printf("sizeof(C):%d/n", sizeof(C));

}

#include <stdio.h>

class A1

{

public:

A1(){ doSth(); }

virtual void doSth(){printf("I am A/n");}

void test() {doSth();}

};

class B1:public A1

{

public:

virtual void doSth(){ printf("I am B/n");}

};

void main()

{

B1 *b = new B1;

b->test();

}

1 用C++开发的时候,用来做基类的类的析构函数一般都是虚函数。

class ClxBase

{

public:

ClxBase() {};

virtual ~ClxBase() {};

virtual void DoSomething() { cout << "Do something in class ClxBase!" << endl; };

};

class ClxDerived : public ClxBase

{

public:

ClxDerived() {};

~ClxDerived() { cout << "Output from the destructor of class ClxDerived!" << endl; };

void DoSomething() { cout << "Do something in class ClxDerived!" << endl; };

};

void main()

{

ClxBase *pTest = new ClxDerived;

pTest->DoSomething();

delete pTest;

}

的输出结果是:

Do something in class ClxDerived!

Output from the destructor of class ClxDerived!

这个很简单,非常好理解。

但是,如果把类ClxBase析构函数前的virtual去掉,那输出结果就是下面的样子了:

Do something in class ClxDerived!

也就是说,类ClxDerived的析构函数根本没有被调用!一般情况下类的析构函数里面都是释放内存资源,而析构函数不被调用的话就会造成内存泄漏。我想所有的C++程序员都知道这样的危险性。当然,如果在析构函数中做了其他工作的话,那你的所有努力也都是白费力气。

所以,文章开头的那个问题的答案就是--这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐