整数A变换整数B

1、整数变换1

给定数字A和B,A<B,A可以进行两种变换,A+=1或者A*=2,也就是A可以加一也可以翻倍,请问,最少多少步A变换到B。

逆向思维:B可以通过B/=2或者B-=1最少的步数得到A,但是B只有是偶数的时候才能B/=2,如果B是奇数,B先减1,然后再B/=2,直到A的值大于B/2的时候,B不能再B/=2,否则B永远无法到A,这个时候只能B一直减减。

#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
class Solution {
public:
  int convert_num(int a, int b){
    int res=0;
    while(a<b){
      if(a>b/2){
        res+=b-a;
        break;
      }else {
        if(b%2==1){
          res+=2;
          b--;
        }else{
          res++;
        }
        b/=2;
      }
    }
    return res;
  }
private:
};
int main()
{
  Solution so;
  int a=2,b=11;
  cout<<so.convert_num(a,b)<<endl;
  return 0;
}

2、整数变换2

给定数字A和B,A可以进行两种变换,A=A*10+1或者A*=2,也就是A可以乘10加一也可以翻倍,请问,最少多少步A变换到B。

我们可以采用逆向思维,从整数B出发,反向推导到A。这样可能在某些情况下更高效,尤其是当B较大时。允许的逆向操作如下:

  1. 逆向操作1:若当前数是偶数,则前一步可能是当前数除以2(对应正向的乘以2)。
  2. 逆向操作2:若当前数减1后能被10整除,则前一步可能是(当前数-1)除以10(对应正向的乘以10加1)。

方法思路

  1. 初始检查:如果A等于B,直接返回0步。
  2. 队列初始化:使用队列存储当前数值及其对应的步数,起始点为B,步数为0。
  3. 访问记录:使用哈希集合记录已访问的数值,避免重复处理。
  4. 逆向BFS遍历:每次从队列中取出当前数值,生成两种可能的逆向操作:
    • 逆向操作1:若当前数为偶数,则生成当前数除以2的结果。
    • 逆向操作2:若当前数减1能被10整除,则生成(当前数-1)除以10的结果。
  5. 目标检查:若生成的数值等于A,返回当前步数加1。
  6. 边界处理:生成的前驱数值必须大于等于A,否则跳过。
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
using namespace std;
class Solution {
public:
  int convert_num(int a, int b){
    if(a==b) return 0;
    queue<pair<int,int>> q; // 存储当前数字和步数
    set<int> visited;
    q.push(pair<int,int>(b,0));
    visited.insert(b);
    int res=-1;
    while(!q.empty()){
      int step=q.front().second;
      int cur=q.front().first;
      q.pop();
      // 逆向操作1: 当前数是偶数时,尝试除以2
      if(cur%2==0){
        int next=cur/2;
        if(next==a){
          if(res!=-1){
            res=min(res,step+1);
          } else {
            res=step+1;
          }
        }else if(next>=a && visited.find(next)==visited.end()){
          q.push(pair<int,int>(next,step+1));
          visited.insert(next);
        }
      }
      // 逆向操作2: 当前数减1后能被10整除时,尝试除以10
      if((cur-1)%10==0){
        int next=(cur-1)/10;
        if(next==a){
          if(res!=-1){
            res=min(res,step+1);
          } else {
            res=step+1;
          }
        }else if(next>=a&&visited.find(next)==visited.end()){
          q.push(pair<int,int>(next,step+1));
          visited.insert(next);
        }
      }
    }
    return res;
  }
};
int main()
{
  Solution so;
  int a=2,b=129;
  cout<<so.convert_num(a,b)<<endl;
  return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值