一.寻找和为定值的两个数
题目:输入一个数组和一个数字,在数组中查找两个数,使得它们的和正好是输入的那个数字。
要求时间复杂度是O(n)。如果有多对数字的和等于输入的数字,输出任意一对即可。
例如输入数组1、2、4、7、11、15和数字15。由于4+11=15,因此输出4和11。
我的思路:题目要求时间复杂度是O(n),所以整个数组只可以遍历一轮。针对题目中给出的实例,对于数4,我们实际上就是要找数组中可有15-4=11这个数。将原题进行这样的转化之后,很容易想到使用hash表,只需要遍历一次数组,即可根据数值在O(1)的时间得到其的存储位置。C++ STL里面封装了hash_map的实现,编写程序如下:
#include
#include
using namespace std;
map<int, int> hash_map;
void search(int * src ,map<int,int> & map,int value,int & a,int & b,int len)
{
for(int i=0;iif(hash_map[value-src[i]]==1)
{
a = src[i];
b=value-src[i];
break;
}
}
}
博客中还给出了指针夹逼的思路,利用两个指针,从两端进行遍历。联想之前的字符串题目中,也有使用两个指针分别在两个字符串中进行遍历的操作。对于有些问题,如果涉及到两个元素的比较或者求和,使用两个指针进行遍历,往往能起到比较好的效果。实现程序如下:
void point_search(int * src,int len,int value,int & a,int & b)
{
int * pa = src;
int * pb = src+len-1;
int tmp_sum=(*pa)+(*pb);
while(paif(tmp_sum<value)
pa++;
if(tmp_sum>value)
pb--;
if(tmp_sum==value)
{
a = *pa;
b = *pb;
break;
}
}
}
二.寻找和为定值的多个数
题目描述:输入两个整数 n 和 m,从数列1,2,3…….n 中 随意取几个数,
使其和等于 m ,要求将其中所有的可能组合列出来。
我的解题思路:
首先自己举个例子,如果数组是1,2,3,4,5,要寻找和为7的元素的组合,那么人的思路自然是2+5=7,然后在对5进行分解这样,这就是递归的思想。因此,可以使用递归的程序,实现如下:
#include
#include
using namespace std;
list<int>list1;
void find_factor(int sum, int n)
{
// 递归出口
if(sum==0)
{
// 反转list
list1.reverse();
for(list<int>::iterator iter = list1.begin(); iter != list1.end(); iter++)
cout << *iter << " + ";
cout << endl;
list1.reverse();
return;
}
if(n<=0)
return;
list1.push_front(n); //典型的01背包问题
if(n-1>sum-n)
find_factor(sum-n, sum-n); //放n,n-1个数填满sum-n
else
find_factor(sum-n, n-1);
list1.pop_front();
find_factor(sum, n-1); //不放n,n-1个数填满sum
}
int main()
{
int sum, n;
sum=7;
n=4;
cout << "所有可能的序列,如下:" << endl;
find_factor(sum,n);
return 0;
}
对比我实现的程序和July实现的程序,
if(n-1>sum-n)
find_factor(sum-n, sum-n); //放n,n-1个数填满sum-n
else
find_factor(sum-n, n-1);
我在这里加了一个if语句进行判断,这样的效率会高些。比如说寻找和为20,第一次将19送入列表,接下来自然应该是find(1,1),而July实现的是find(1,18),这样会多做许多无用功。
之后的例子没有细看,应用到了动态规划,回溯法这些思想,这些算法思想之前上过课,原理基本明白,但是没有实现过。以后有时间再自己去实现。