题目链接
题目大意
需要通过数字n,获得数字k。
可以对n进行两种操作,时间都是一分钟,求最短用时。
- n–或者n++;
- n*=2;
题解
- 采用BFS:即每一步可以向左右走一步,或者去n*2;当n>k时,只执行n–;时间复杂度为o(n)
- 采用dfs:对于n>k,只执行n–;当n<k时,按k是奇数还是偶数分两种情况处理。
当k是偶数,n -> k可以通过一直加1的方式得到k,或者先使n = k/2,再通过n2一步使得n== k;
当k是奇数,n -> k可以通过一直加1的方式得到k,或者先使n== k/2,再通过n2然后n++两步使得n== k,或者先使n== k/2+1,再通过n*2然后n–两步使得n==k。
时间复杂度为O(logn);
标程
下面只给出dfs的解法
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
long DFS(long n,long k,long step)
{
//cout<<n<<" "<<k<<" "<<step<<endl;
if(n==k)
return step;
//n大于k
if(n>k)
return step+=n-k;
if(n==0)
return DFS(1,k,step+1);
//n小于k
//k是奇数
if(k%2)
{
long x=k/2+1;
return step+=min(min((k-n),DFS(n,x,0)+2),DFS(n,x-1,0)+2);
}
//k是偶数
else{
long x=k/2;
return step+=min((k-n),DFS(n,x,0)+1);
}
}
int main()
{
long n,k;
while(cin>>n>>k){
cout<<DFS(n,k,0)<<endl;}
return 0;
}
解题过程犯的错误
- 题目读错,没有读到可以进行n++的操作,只读到n–,导致刚开始思路出现问题。
- 递归求解逻辑没有理清楚,并且对于k是奇数的情况,少考虑一种情形。
相似的题目
采用bfs做法
牛客比赛
class Solution {
public:
/**
* 返回最后要输出的答案
* @param n int整型 表示牛牛的数字
* @param m int整型 表示牛妹的数字
* @return int整型
*/
int solve(int n, int m) {
// write code here
if(n>=m)
return n-m;
queue<int> Q;
Q.push(n);
int M[1000005];
M[n]=0;
memset(M, 0, sizeof(M));
while(!Q.empty())
{
int now=Q.front();
Q.pop();
int step=M[now];
//cout<<now<<" "<<step<<endl;
if(now==m)
return step;
int x=now-1;
int y=now+1;
int z=now*now;
if(x>0 && !M[x])
Q.push(x),M[x]=step+1;
if(now<m && !M[y])
Q.push(y),M[y]=step+1;
if(m>0 && now<m && z<1e6 &&!M[z])
Q.push(z),M[z]=step+1;
}
return 0;
}
};
注意事项
开两个队列就会内存超限。