写一段程序,找出数组中第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
#include
#include
/***************************************
输入: 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[N], 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
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
#include
#include
#include
#include
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
cout << "源" << n << "个数据如下:
for ( int i = 0; i < n; i++ )
{
src.push_back( rand() );
cout << src[i] << " ";
}
vector
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
}
=================================================================== 函数功能:返回一个第K小的元素(采用快排思想)
参数:(T a[]目标数组 || int l左边界 || int r右边界 || int k第几小元素)
================================================================= template
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
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
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++程序员都知道这样的危险性。当然,如果在析构函数中做了其他工作的话,那你的所有努力也都是白费力气。
所以,文章开头的那个问题的答案就是--这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用。