LeetCode/转化数字的最小运算数
给定nums数组和一个初始值start,目标值goal,对start进行以下三种运算得到goal
x + nums[i]、x - nums[i]、x ^ nums[i]
返回最少运算次数
1. 广度优先+哈希去重剪枝
class Solution {
public:
int minimumOperations(vector<int>& nums, int start, int goal) {
queue<int> q;
unordered_map<int,int> m;
q.push(start);
m[start]=0;
while(q.size()){
int cur=q.front();
q.pop();
int step=m[cur];
for(auto& i:nums){
int nums[3]={cur+i,cur-i,cur^i};
for(int j=0;j<3;j++){
if(nums[j]==goal) return step+1;
if(nums[j]<0||nums[j]>1000) continue;
if(m.count(nums[j])) continue;
m[nums[j]]=step+1;
q.push(nums[j]);
}
}
}
return -1;
}
};
2. 双向广度优先
class Solution {
public:
int ans, depth1, depth2;
bool flag;
queue<int> q1, q2;
unordered_map<int, int> m1, m2;
//正向方向来回搜索
void update(const vector<int>& nums) {
int size = q1.size();
for (int i = 0; i < size; ++i) {
int cur = q1.front();
q1.pop();
for (int j = 0; j < nums.size(); ++j) {
int next[3] = {cur+nums[j],cur-nums[j],cur^nums[j]};
for(int k=0;k<3;k++){
if(m2.count(next[k])){
flag = true;
ans = depth1 + m2[next[k]] + 1;
return;
}
if((next[k]>=0&&next[k]<=1000)&&!m1.count(next[k])) q1.push(next[k]),m1[next[k]] = depth1+1;
}
}
}
++depth1;
return;
}
int minimumOperations(vector<int>& nums, int start, int goal) {
if(start==goal) return 0;
ans = depth1 = depth2 = 0;
flag = false;
q1.push(start), q2.push(goal);
m1[start] = 0, m2[goal] = 0;
bool state = 0;//默认左边扩散
while (!q1.empty() && !q2.empty()) {
if (q1.size() <= q2.size()&&state==1)
{ swap(q1,q2);swap(m1,m2);swap(depth1,depth2);state=0;}
if(q1.size()>q2.size()&&state==0)
{swap(q1,q2);swap(m1,m2);swap(depth1,depth2);state=1;}
update(nums);
if (flag) return ans;
}
return -1;
}
};