

/*************************************************************************
> File Name: 163.cpp
> Author:
> Mail:
> Created Time: 2015年11月11日 星期三 13时55分16秒
************************************************************************/
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
/*output the vector data*/
struct myclass{
void operator() (int i){
cout << i << " ";
}
}myobject;
/*recursion二分递归查找*/
int binary_search_recursion(const vector<int> &v, int low, int high, int goal)
{
if (low <= high){
int middle = (low + high) / 2;
if (goal == v[middle])
return middle;
else if (goal > v[middle])
binary_search_recursion(v, middle+1, high, goal);
else
binary_search_recursion(v, low, middle-1, goal);
}
else
return -1;
}
void input_data(int *n, int *m, vector<int> &k)
{
int val;
cout << "n = ";
cin >> *n;
cout << "m = ";
cin >> *m;
cout << "k = {";
for (int i = 0; i < *n; i++){
cin >> val;
k.push_back(val);
cin.get();
cin.get();
}
}
/*暴力枚举*/
void solve_1(int n, int m, const vector<int> &k)
{
for (int a = 0; a < n; a++)
for (int b = 0; b < n; b++)
for (int c = 0; c < n; c++)
for (int d = 0; d < n; d++){
if (k[a] + k[b] + k[c] + k[d] == m){
cout << "Yes" << endl;
return;
}
}
cout << "No" << endl;
return;
}
/*N^3*O(longN)*/
void solve_2(int n, int m, const vector<int> &k)
{
for (int a = 0; a < n; a++)
for (int b = 0; b < n; b++)
for (int c = 0; c < n; c++){
if (binary_search_recursion(k, 0, k.size()-1, m-k[a]-k[b]-k[c]) != -1){
cout << "Yes" << endl;
return;
}
}
cout << "No" << endl;
return;
}
/*N^2*O(longN)*/
void solve_3(int n, int m, const vector<int> &k)
{
vector<int> k34;
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
k34.push_back(k[i] + k[j]);
sort(k34.begin(), k34.end());
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++){
if (binary_search_recursion(k34, 0, k34.size()-1, m-k[i]+k[j]) != -1){
cout << "Yes" << endl;
return;
}
}
cout << "No" << endl;
return;
}
int main()
{
int n = 0, m = 0;
vector<int> k;
input_data(&n, &m, k);
solve_1(n, m, k);
sort(k.begin(), k.end());
solve_2(n, m, k);
solve_3(n, m, k);
return 0;
}
第一种解法:枚举法,将四次的所有的可能取值相加,如果等于m,则输出Yes,否则输出No;这个解法很简单,四个嵌套的for循环很简单就可以实现;但是时间复杂度太高,O(N^4),如果N的值比较大,那么这个程序会很耗时间;
第二种解法:目的就是为了降低时间复杂度,所以只能对那四个for循环下手,所以思路------就是减少for循环的个数;
在最后一个for循环中判断k[a]+k[b]+k[c]+k[d] == m;其实也就是在这个数组中判断是不是存在k[d] == m-k[a]-k[b]-k[c];
所以最后一个循环就可以改变为对一个数值(m-k[a]-k[b]-k[c])进行查找,如果这里用普通的查找,时间复杂度是O(N),那么整体的时间复杂度是N^3O(N),那么时间复杂度没有下降;
所以用简单的二叉查找(如果要用二叉查找,那么必须要提前对数组进行排序,排序的时间复杂度为最差的是O(N^2)),二叉查找的时间复杂度是O(logN);那么该解决方法的总的时间复杂度是 O(N^2)+N^3O(logN),也就是N^3O(logN);
第三种解法:因为第二种的时间复杂度还是比较高;所以我们还要对其进行减小;但是入手处在哪里????当然还是for循环;
我们再减少一个for循环,让第二个for循环里面进行判断 m-k[a]+k[b] == k[c]+k[d];
所以我们必须提前将k[c]+k[d]所有的情况的取值存储在一个数组kk中(必须排序,时间复杂度为N^2O(logN)),在第二个for循环里面在数组kk中二叉查找m-k[a]+k[b],二叉查找的时间复杂度是O(logN);
所以整体的时间复杂度是N^2O(logN)+N^2O(logN),也就是N^2O(logN);等于排序的时间复杂度加上for循环的时间复杂度;

浙公网安备 33010602011771号