2.5寻找最大的K个数
问题:有很多个无序的数,我们姑且假定它们各不相等,怎么选出其中最大的若干个数呢?
基于快速排序方法的解法:
#include<iostream>
#include<assert.h>
using namespace std;
int partition(int* a, int left, int right ){
int privotKey = a[left];
while( left< right){
while( left< right && a[right] >= privotKey )
right--;
a[left] = a[right];
while( left< right && a[left]<= privotKey )
left++;
a[right] = a[left];
}
a[left] = privotKey;
return left;
}
void bigK(int* a, int low,int n , int k){
assert(k<=n);
int privot ;
privot = partition(a, low, n-1 );
if (n- privot >k)
{
bigK(a, privot+1, n , k );
}
else if (n- privot <k)
{
bigK(a, 0, privot, k- (n- privot) );
}
else
{
return ;
}
}
int main(){
int ID[10]={50 ,10, 90, 30 ,70, 40, 80, 60, 20, 50};
int n = 10;
int k= 5;
bigK(ID, 0, n, k);
for (int i = 0; i < k; ++i)
{
cout<<ID[n- i-1]<<"\t";
}
return 0;
}
2.7最大公约数问题
#include <iostream>
using namespace std;
inline bool isEven(int a){
if (a%2 == 0)
{
return true;
}
return false;
}
int gcd(int x, int y){ //最大公约数,没有用到除法
if ( x < y)
{
return gcd(y, x);
}
if ( y == 0) //结束递归
{
return x;
}
else{
if ( isEven(x) )
{
if( isEven(y))
return 2*gcd(x>>1, y>>1);
else
return gcd(x>>1, y);
}
else{
if( isEven(y))
return gcd(x, y>>1);
else
return gcd( x-y, y);
}
}
}
int main(){
int test[10] = {5, 1, 4, 8, 62, 31, 77, 11, 120, 48};
for ( int i= 0; i < 10; i+=2)
{
cout<< gcd( test[i], test[i+1])<<'\t';
}
return 0;
}
2.12快速寻找满足条件的两个数
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
//快速寻找满足条件的两个数
bool findTwo(const vector<int>& b, int key,pair<int , int>& res){
int i= 0, j= b.size()-1;
for (;i<j; ) //俩头夹逼,或称两个指针两端扫描法,很经典的方法,O(N)
{
if (b[i]+b[j] == key )
{
res = make_pair(b[i], b[j]);
return true;
}
else if ( b[i]+b[j] < key )
{
i++;
}
else
j--;
}
return false;
}
int main(){
int a[10]= {5, 6, 1, 4, 7, 8, 9, 12, 17, 14};
vector<int> vctB;
for ( int i= 0; i< 10; i++)
{
vctB.push_back(a[i]);
}
sort(vctB.begin(), vctB.end() );
pair<int , int> res;
if (findTwo(vctB, 39, res) )
{
cout<<res.first<<'\t'<<res.second<<endl;
}
else
cout<<"Not Found!";
return 0;
}
扩展问题:把这个问题中的两个数字改为任意个数字
思路:01背包问题,可以用递归来实现。
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
using namespace std;
list<int> list1;
void findSum(vector<int>& vct, int n,int K ){
if (n>= vct.size() || vct[n]>K ) //如果大于K,说明解不可能存在
{
return ;
}
if (vct[n] == K)
{
for ( list<int>::iterator it=list1.begin(); it!=list1.end(); it++)
{
cout<<*it<<"\t";
}
cout<<vct[n];
cout<<endl;
}
list1.push_front(vct[n]);
findSum(vct, n+1, K-vct[n] );
list1.pop_front();
findSum(vct, n+1, K);
}
int main(){
int a[6]= {-5, -1, 0,2, 3, 4};
vector<int> vctB;
for ( int i= 0; i< 6; i++)
{
vctB.push_back(a[i]);
}
sort(vctB.begin(), vctB.end() );
findSum(vctB, 0, -3);
return 0;
}
2.14 求数组的子数组之和的最大值,同时输出子数组的位置
#include<iostream>
using namespace std;
//求数组的子数组之和的最大值
int maxSum(int* arr, int n, int& left, int& right)
{
int temp = arr[0];
int max = arr[0];
int left1 = 0;
int right1 = 0;
left = left1; //记录子数组之和最大值的数组的下标
right = right1;
for ( int i= 0; i < n; i++){
if ( temp < 0)
{
temp = arr[i];
left1= i;
right1 = i;
}
else
{
temp += arr[i];
right1++;
}
if ( temp > max)
{
left = left1;
right = right1;
max = temp;
}
}
if ( right > 7)
{
right = 7;
}
return max;
}
int main(){
int a[8] = {-1, -3, -3, -6, -4, -8, 0, -2};
int right, left;
cout<<"max sum:"<<maxSum(a, 8, left, right)<<"\t";
cout<<"left:"<<left<<"\t";
cout<<"right:"<<right<<endl;
system("pause");
return 0;
}