一开始想用递归的方法求解,但是搜索空间太大,超时。
class Solution {
public:
// target 长度有限,但是内部元素比较大。
// target与顺序无关,只要有这些数字就可以了
// 如果当前和超越了target最大数据,那么就是不可能的
// 不需要逐次出现target里面的数字,可以不断迭代寻找。
// 感觉充斥着递归的思想
bool cmp(map<int, int>& targetmap, map<int, int>& inputmap){
for(auto it=inputmap.begin();it!=inputmap.end();it++){
if (inputmap[it->first]==0||inputmap[it->first]==targetmap[it->first]){
continue;
}
else{
return false;
}
}
return true;
}
bool dfs(map<int, int>& targetmap, map<int,int>& inputmap, int sum, int maxsum){
// for debug
/*
for(auto it=inputmap.begin();it!=inputmap.end();it++){
cout<<it->first<<" "<<it->second<<endl;
}
cout<<"*****************************"<<endl;*/
if (cmp(targetmap, inputmap)){
return true;
}
if (sum>maxsum){
return false;
}
// must out of time
for(auto it=inputmap.begin();it!=inputmap.end();it++){
if (it->second==0){
continue;
}
else{
inputmap[it->first] --;
inputmap[sum] ++;
bool res = dfs(targetmap, inputmap, 2*sum-it->first, maxsum);
if (res==true){return true;}
inputmap[it->first] ++;
inputmap[sum] --;
}
}
return false;
}
bool isPossible(vector<int>& target) {
int maxnum = 0;
map<int, int> targetmap;
for(int i=0;i<target.size();i++){
targetmap[target[i]] ++;
maxnum = max(maxnum, target[i]);
}
map<int,int> inputmap;
inputmap[1] = target.size();
return dfs(targetmap, inputmap, target.size(), maxnum);
}
};
看了别人的解法,才发觉是这么个解法。需要考虑好多关键点以内bad case。
// 关键点1:从后往前推,减少分支数目
// 关键点2:建立恒等关键[mx, a1,a2,a3] a1+a2+a3=others mx是最大
// 则其等价为[mx%others,a1,a2,a3]。因为总可以从这个状态=> [mx, a1,a2,a3]
// 关键点3:采用优先队列,快速找到最大值。
// 关键点4:防止数据超范围。用long
class Solution {
public:
// 关键点1:从后往前推,减少分支数目
// 关键点2:建立恒等关键[mx, a1,a2,a3] a1+a2+a3=others mx是最大
// 则其等价为[mx%others,a1,a2,a3]。因为总可以从这个状态=> [mx, a1,a2,a3]
// 关键点3:采用优先队列,快速找到最大值。
// 关键点4:防止数据超范围。用long
bool isPossible(vector<int>& target) {
if (target.size()==1){
return target[0]==1;
}
long sum = 0;
priority_queue<long> myqueue;
for(int i=0;i<target.size();i++){
sum += long(target[i]);
myqueue.push(long(target[i]));
}
// 如果top是1,说明最大的也就1,可以停止了。
while(!myqueue.empty()&&myqueue.top()>1&&2*myqueue.top()-sum>=1){
long mx = myqueue.top(); //2
myqueue.pop();
long others = sum - mx;//1=>further process
if (others<=0){
return false;
}//>=0
else if (others==1){
return true;
}
else{
long newval = mx%others;//
if (newval==0){return false;}
myqueue.push(newval);
sum = sum-mx+newval;
}
}
return sum==target.size();
}
};