7队面对一个可怕的敌人。他只能被特殊的击败 强度的四重组合攻击(1 <= S <= 10 ^ 9)。 火影忍者,佐助,樱花和卡卡西必须同时攻击 执行组合。它们中的每一个可以选择N(1≤N≤1000)攻击,每个具有强度si(0 <= i
他们可以使用有效的组合吗?请注意相同 所有人都可以获得攻击。
您需要编写一个输入如下的输入函数 - An 整数
N
为攻击次数,整数向量为s[]
N
攻击的强度和整数S
作为所需的强度 组合。将输出变量设置为distinct有效数 连击。如果它们的强度至少不同,则两种组合是不同的 使用了一次攻击。
输入:1 {1} 4
输出:1 ===>{1,1,1,1}
输入:2 {1,2} 5
输出:1 ===> {1,1,1,2}
以下是我的代码,它只通过了10个测试用例。我不知道测试用例,因为这是一些在线代码提交。
我的算法: 1)创建一个散列,其中索引作为输入数组和值的对的总和,作为对sum有贡献的单个元素 2)迭代哈希,看看哈希中是否有k-i 3)计算上面的索引并返回计数/ 2,因为我们计算H(i)和H(k-i)
请查看代码并告诉我您认为代码无法生成的场景o / p。
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<map>
#include<set>
const int noOfPalyers = 4;
int validCombo(int input1,int input2[],int input3)
{
//Write code here
int count = 0;
std::vector<int> vec;
int size =input1*noOfPalyers;
for(int i = 0; i < input1; i++)
{
for(int j = 0; j < noOfPalyers;j++)
{
vec.push_back(input2[i]);
}
}
std::vector< std::set< std::pair<int, int> > > vecHash;
//vecHash.reserve(size*size);
for(int i =0; i < (size*size); i++)
{
vecHash.push_back(std::set< std::pair<int, int> >());
}
for(int i =0; i < size; i++)
{
for(int j =1; j < size; j++)
{
int key = vec[i] + vec[j];
if(vec[i]<= vec[j])
vecHash[key].insert(std::make_pair(vec[i], vec[j]));
else
vecHash[key].insert(std::make_pair(vec[j], vec[i]));
}
}
for(int i = 0; i < input3; i++)
{
if(vecHash[i].size() > 0 && i < input3)
{
if(vecHash[input3-i].size() > 0)
{
std::set< std::pair<int, int> >::iterator iter, iter2;
for(iter=vecHash[i].begin(); iter!=vecHash[i].end();++iter)
{
for(iter2=vecHash[input3-i].begin(); iter2!=vecHash[input3-i].end();++iter2)
{
std::cout<<(*iter).first<<","<< (*iter).second<<",";
std::cout<<(*iter2).first<<","<< (*iter2).second;
std::cout<<"\n";
count++;
}
}
}
}
}
return (count ==1 ? count: count/2);
}
int main()
{
int i = 3;
int arr[] = {1,2,3};
int j = 7;
int arr1[] ={1};
std::cout <<"o/p == " << validCombo(i, arr, j)<< "\n";
std::cout <<"o/p == " << validCombo(1, arr1, 4);
//getch();
return 0;
}
答案 0 :(得分:0)
<强> UPD 即可。我的上帝,现在我已经理解了你的评论:)并且看到你试图像我写的那样解决它。无论如何,我希望你能找到一些有用的解释。首先,你不使用哈希函数(我知道身份函数是一个哈希函数,但在我们的例子中不是好的函数)。
我也不理解你的{{1} } logic ...我想你需要再次阅读count
部分并检查你的Two combinations are different if they differ in strength of at least one attack used.
逻辑。
只是我的第一个想法。希望它可能会有所帮助。
==================================
你知道,这个问题是关于从集合中得到4个数字的特定总和。让我们想象一下,我们只有2个英雄(总和中有两个词):
count
其中a,b是来自N个数字组的攻击强度(让我们将其命名为T)。不同a + b = S,
和的数量是N ^ 2。简单计算所有这些总和,然后搜索那些等于S的那些并不能给我们提供很好的解决方案。这个问题可以通过更好的复杂性来解决。
如果我们能找到一个快速的功能:
a + b
我们会预先计算所有F(S - b),然后循环遍历所有F(a) = F(S - b)
并找到哪些满足上述等式。你提到哈希。散列函数可以做到这一点。我们需要这样的哈希函数来将集合a
中的所有数字映射到范围[0,N]。因为我们只有不超过N个T
&#39; s。
但我们在这里遇到一些问题:
a
只是意味着F(a) = F(S - b)
可以等于a
。幸运的是,这不是一个大问题,S - b
表示F(a) != F(S - b)
。好的,正如您所见,我们有解决a != S - b
问题的算法,以及摊销的O(N)复杂性。听起来不错,很有希望,对吧? :)
==================================
现在回到你的问题:
a + b = S
我想用O(N ^ 2)预先计算所有a + b + c + d = S
并将它们存储起来(警告!只是伪代码):
f(a + b)
我们保持对(a,b)能够恢复初始总和的条款。然后,如果我们的OurHashFunc是加法的,那么转换我们的初始问题如下:
vector<int> hash = new vector<int>(with size N)
foreach (a in T)
foreach (b in T)
{
int x = OurHashFunc(a + b); // a + b <= 2 * 10^9 so it never overflows int
if (hash[x] == null)
hash[x] = new vector<pair<int,int>>
hash[x].push_back(new pair<int, int>(a, b));
}
现在,4项和问题已经减少到2项和问题,其中O(N ^ 2)开销。 我认为这种减少可以继续:2 ^ k-terms总和问题应该有平均O(N ^ k)解。