(5)寻找满足条件的两个或多个数

#include <iostream>
#include <set>
#include <vector>

using namespace std;

/*
 * 输入一个数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字
 * 要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可
 * 例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11
*/
/*
	1.二分查找:先排序后二分查找	 nlogn
	2.如果有序:首尾查找
	3.扫描一遍,映射sum-a[i]
	
	如果数组有序:
		优先两端扫描
	如果数组无序:
		先排序:	i:二分查找	
				ii:两端搜索
				iii:映射
*/

void TestFindEqualNum();

// 数组已经排好序,从两端搜索
void FindEqualNum(int arr[], unsigned n, int num, int &first, int &last);

// 二分查找方式,同样数组已经排好序
// 考虑用两个指针
void FindEqualNum_2(int arr[], unsigned n, int num, int *first, int *second);
int *BinarySearch(int arr[], unsigned n, int num);

/*
	输入两个整数 n 和 m,从数列1,2,3.......n 中 随意取几个数, 
	使其和等于 m ,要求将其中所有的可能组合列出来
*/
//bool FindEqualNum_3(int arr[], int n, int m, int *res, int &r, int *tmp, int t);
// arr 中没有重复的
//bool FindEqualNum_3(set<int> arr, int m, set<int>res);

bool FindEqualNum_3(vector<int> arr, int m, vector<int>res);

// 用链表比较好

// arr中有n个,现在要拷贝(n-1)个到res中,不拷贝第without个,without为index
//void CopyArrayWithoutN(int *arr, int n, int *res, int without);

// arr	:	数组
// n	:	个数
// m	:	和
// res	:	映射表
// cur	:	当前总和
// remain:	剩下的总和
// index:	当前的层数
// 递归版本
bool FindEqualNum_4(int arr[], int n, int m, bool res[], int cur, int remain,int index);

// 非递归版本
bool FindEqualNum_5(int arr[], int n, int m, bool res[], int cur, int remain,int index);

// 从一列数中筛除尽可能少的数使得从左往右看,这些数是从小到大再从大到小的
/*
	搜索永远都能得到结果:
		1.通过剪枝搜索,对每一个节点
			1.删除,计算剩余节点且满足条件的总数
			2.不删除,计算剩余节点的满足条件的总数

	动态规划!!!
*/
bool DeleteMinimon(int arr[], int n, bool result[], bool current[], int best, int tmp, int level);

// 不返回
void DeleteMinimon_2(int arr[], int n, bool result[], bool current[], int best, int tmp, int level);


// 只考虑res中为true的数
bool IsOK(int arr[], int n, bool res[]);

/*
	有两个序列a,b,大小都为n,序列元素的值任意整数,无序; 
	要求:通过交换a,b中的元素,使[序列a元素的和]与[序列b元素的和]之间的差最小。 
	例如: var a=[100,99,98,1,2, 3]; var b=[1, 2, 3, 4,5,40];
*/
/*
	记录best、tmp
	对于a中的每个值,与b中任意值交换
*/

// 
void SwapForMin(int *arr1, int *arr2, int n, int &x, int &y);
int SumArray(int *arr, int n);

/*
	1.n^2的最长递增序列
*/
void LIS(int *arr, unsigned n, int *prev, unsigned &m);

// max:最长的个数
void PrintLIS(int *prev, unsigned n, unsigned max);

void PrintRecursive(int *prev, unsigned m);

// 维护一个res:保存长度为i的最小的位置
void LIS_2(int *arr, unsigned n, unsigned *res, unsigned &m);

// 返回从start到end的最小的index
// 包括start,包括end
unsigned FindMin(int *arr, unsigned start, unsigned end);

void LIS_3(int *arr, unsigned n, int &m);

// 从0到n-1中寻找最大的不大于num的数的index
unsigned MyBSearch(int *arr, unsigned n, int num);


#include <algorithm>

#include "5_FindEqualNum.h"

void TestFindEqualNum()
{
	int arr[] = {1, 2, 4, 7, 11, 15};
	/*int first = -1;
	int last = -1;
	FindEqualNum(arr, 6, 15, first, last);
	cout << arr[first] << " " << arr[last] << endl;*/

	int *addr = BinarySearch(arr, 6, 4);
	cout << *addr << endl;
}

void FindEqualNum(int arr[], unsigned n, int num, int &first, int &last)
{
	first = 0;
	last = n - 1;
	while (first < last)
	{
		int sum = arr[first] + arr[last];
		if (sum == num)
		{
			return;
		}
		else if (sum < num)
		{
			first++;
		}
		else
		{
			last--;
		}
	}
	first = -1;
	last = -1;
}

void FindEqualNum_2(int arr[], unsigned n, int num, int *first, int *second)
{
	for (unsigned i = 0; i < n; ++i)
	{
		int remain = num - arr[i];
		int *pRemain = BinarySearch(arr, n, remain);
		if (pRemain)
		{
			first = arr + i;
			second = pRemain;
			return;
		}
	}
	first = NULL;
	second = NULL;
}

int *BinarySearch(int arr[], unsigned n, int num)
{
	int start = 0;
	int last = n - 1;	
	while (start <= last)
	{
		int middle = (start + last) / 2;
		int current = arr[middle];
		if ( current == num)
		{
			//return (&arr[middle]);
			//return (int *)((int *)arr + middle);
			return (arr + middle);
		}
		else if (current > num)
		{
			last = middle - 1;
		}
		else
		{
			start = middle + 1;
		}
	}
	return NULL;
}

//bool FindEqualNum_3(int arr[], int n, int m, int *res, int &r, int *tmp)
//{
//	if (n == 1 && arr[n] == m)
//	{
//		res[r++] = arr[n];
//		return true;
//	}
//	for (int i = 0; i  < n; ++i)
//	{		
//		// 构造新的数组		
//		CopyArrayWithoutN(arr, n, tmp, i);
//		
//		if (FindEqualNum_3(tmp, n - 1, m - arr[i], res, r, arr))
//		{
//			// 假设结果中有arr[i]
//			res[r++] = arr[i];
//			
//			return true;
//		}
//				
//	}
//}
//
//// 我他妈用int用惯了!!!
//// 一定要改!!!
//void CopyArrayWithoutN(int *arr, int n, int *res, int without)
//{
//}
//
//bool FindEqualNum_3(set<int> arr, int m, set<int>res)
//{
//	return false;
//}

bool FindEqualNum_3(vector<int> arr, int m, vector<int>res)
{
	if (arr.size() == 1 && arr[0] == m)
	{
		res.push_back(arr[0]);
		return true;
	}
	else
	{
		for (unsigned i = 0; i < arr.size(); ++i)
		{
			int tmp = arr[i];
			arr.erase(arr.begin() + i);
			if (FindEqualNum_3(arr, m - tmp, res))
			{
				res.push_back(tmp);
				return true;
			}

			if (FindEqualNum_3(arr, m, res))
			{				
				return true;
			} 
			
			
			arr.insert(arr.begin() + i, tmp);				
			
		}
		return false;
	}
}

// 递归版本
bool FindEqualNum_4(int arr[], int n, int m, bool res[], int cur, int remain, int index)
{
	if (m == 0)
	{
		return true;
	}
	else
	{
		for (int i = index; i < n; ++i)
		{
			// 左边,包括arr[index];
			if (cur + arr[i] <= m)
			{
				res[i] = true;
				if (FindEqualNum_4(arr, n, m - arr[i], res, cur + arr[i], remain - arr[i], index + 1))
				{
					return true;
				}
			}
			// 右边,不包括arr[index]
			if (cur + remain - arr[i] >= m)
			{
				res[i] = false;
				if (FindEqualNum_4(arr, n, m, res, cur, remain - arr[i], index))
				{
					return true;
				}
			}
		}
		return false;
	}
}

bool FindEqualNum_5(int arr[], int n, int m, bool res[], int cur, int remain,int index)
{
	return false;
}

// 初始时,best=n,cur=0,level=0
bool DeleteMinimon(int arr[], int n, bool result[], bool current[], int best, int tmp, int level)
{
	if (IsOK(arr, n, current))
	{
		if (tmp < best)
		{
			best = tmp;
			copy(current, current + n, result);
		}
		return true;
	}
	else
	{
		bool found = false;
		for (int i = level; i < n; ++i)
		{
			// 1.arr[i]没被删除
			current[i] = true;
			
			if (DeleteMinimon(arr, n, result, current, best, tmp, level + 1))
			{
				found = true;
			}
			current[i] = false;
			if (DeleteMinimon(arr, n, result, current + 1, best, tmp, level + 1))
			{
				found = true;
			}
		}
		return found;
	}
}

// 一开始res都为true
bool IsOK(int arr[], int n, bool res[])
{
	return false;
}

void DeleteMinimon_2(int arr[], int n, bool result[], bool current[], int best, int tmp, int level)
{
	if (IsOK(arr, n, current))
	{
		if (tmp < best)
		{
			best = tmp;
			copy(current, current + n, result);
		}		
	}
	else
	{		
		for (int i = level; i < n; ++i)
		{
			if (tmp > best)
				return;
			// 1.arr[i]没被删除
			current[i] = true;			
			DeleteMinimon(arr, n, result, current, best, tmp, level + 1);
			
			current[i] = false;
			DeleteMinimon(arr, n, result, current + 1, best, tmp, level + 1);	
		}
	}
}

void LIS(int *arr, unsigned n, int *prev, unsigned &m)
{
	int *tmp = new int[n];
	for (unsigned i = 0; i < n; ++i)
	{
		tmp[i] = 1;
		prev[i] = i;
	}

	for (unsigned i = 1; i < n; ++i)
	{
		for (unsigned j = 0; j < i; ++j)
		{
			if (arr[j] < arr[i] && tmp[i] <= tmp[j] + 1)
			{
				tmp[i] = tmp[j] + 1;
				prev[i] = j;
				m = tmp[i];
			}
		}
	}
}

void PrintLIS(int *prev, unsigned n, unsigned max)
{
	for (unsigned i = 0; i < n; ++i)
	{
		if (prev[i] == max)
		{
			unsigned j = i;
			/*while (j != 0)
			{
				cout << prev[j] << endl;
				j = prev[j];
			}*/
		}
	}
}

void PrintRecursive(int *prev, unsigned m)
{
	if (prev[m] == 0)
	{
		cout << prev[m];
		return;
	}
	else
	{
		int tmp = prev[m];
		PrintRecursive(prev, tmp);
		cout << prev[m] << " " << endl;
	}	
}

void LIS_2(int *arr, unsigned n, unsigned *res, unsigned &m)
{
	res[1] = FindMin(arr, 0, n - 1);
	unsigned current = res[1];
	unsigned index = 1;	
	while (current < n)
	{		
		unsigned tmp = FindMin(arr, current + 1, n - 1);
		res[++index] = tmp;
		current = tmp;
	}
	m = index;
}

unsigned FindMin(int *arr, unsigned start, unsigned end)
{
	unsigned min = start;
	int tmp = arr[start];
	for (unsigned index = start + 1; index < end; ++index)
	{
		if (arr[index] < tmp)
		{
			min = index;
			tmp = arr[index];
		}
	}
	return min;
}

void LIS_3(int *arr, unsigned n, unsigned *res, unsigned &m)
{
	res[1] = arr[1];
	unsigned j = 1;
	unsigned size = 1;

	for (unsigned i = 2; i < n; ++i)
	{
		if (arr[i] < res[1])
			j = 1;
		else if (arr[i] > res[size])
			j = size + 1;
		else // ress[i] < res[size]
		{
			// j = bsearch(
		}
		res[j] = arr[i];		
	}
}

void LIS_3(int *arr, unsigned n, unsigned &m)
{
	int *res = new int[n];
	m = 0;
	unsigned index = 0;
	res[0] = arr[0];
	
	for (unsigned i = 1; i < n; ++i)
	{
		if (arr[i] < res[0])
		{
			index = 0;
		}
		else if (arr[i] > res[m])
		{
			index = ++m;
		}
		else
		{
			index = MyBSearch(arr, m + 1, arr[i]);
		}
		res[index] = arr[i];
	}
}

unsigned MyBSearch(int *arr, unsigned n, int num)
{
	unsigned left = 0;
	unsigned right = n - 1;
	while (left <= right)
	{
		unsigned middle = (left + right) / 2;
		if (num > arr[middle]&& num <= arr[middle + 1])
		{
			return (middle + 1);
		}
		else if (num < arr[middle])
		{
			right = middle - 1;
		}
		else 
		{
			left = middle + 1;
		}
	}
	return 0;
}

void SwapForMin(int *arr1, int *arr2, int n, int &x, int &y)
{
	int sum1 = SumArray(arr1, n);
	int sum2 = SumArray(arr2, n);
	int sub = sum1 - sum2;
	if (sub > 0)
	{
		unsigned i = 0;
		unsigned j = 0;
		sort(arr1, arr1 + n);
		sort(arr2, arr2 + n);
		
	}
}

int SumArray(int *arr, int n)
{
	return -1;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值