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