编程之美读书心得(二)

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;
}

    原文作者:jxkongyue
    原文地址: https://blog.csdn.net/jxkongyue/article/details/10392049
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞