面试题中的回溯算法

博主分享了一次面试经历,涉及的算法题是通过+1, -1, *2操作从a到达b,要求步数最少。题目解析及解题思路被详细阐述,同时给出了完成该题目的C#代码。博主期待与读者共同学习交流。" 100128018,7459980,深入理解Python while循环,"['Python编程', '流程控制', '循环结构']
摘要由CSDN通过智能技术生成

这是博主在某一份工作面试中遇到的一个面试题,因为那会还是自己第一份工作的面试,不想白白浪费,于是问了我一个在香港大学计算机研究生的一位哥哥委屈委屈,然后我哥哥帮我做的,时隔一年了,博主还在游戏行业中翻滚,回想起这份代码觉得十分有意思,也很厉害(对博主而言),于是今天拉出来,一是为了留个纪念,二是为了能和各位大佬们互相学习。

话不多说,博主先把面试题拉出来。



一、算法题:

b=fun(a)
函数fun把a变换到b,每次任意选择下面三种方式之一:
1:b=a * 2
2:b=a - 1
3:b=a + 1


写一个算法,用最少的fun调用次数,来实现变换,并且输出变换序列
trans(2, 5)
第一次变换
4= 2 * 2
第二次变换
5= 4 + 1
然后就搞定了
***************************************************
请测试trans(43, 103)
输出结果:
43 103
need 10 steps
step 1  :       43      ->      44
step 2  :       44      ->      45
step 3  :       45      ->      46
step 4  :       46      ->      47
step 5  :       47      ->      48
step 6  :       48      ->      49
step 7  :       49      ->      50
step 8  :       50      ->      51
step 9  :       51      ->      102
step 10 :       102     ->      103

没有明白题目意思的老铁们不要着急,其实很简单,就是从 a -> b ,使用 +1, -1, *2,这3个算法的其中一个,

一直要得到b结果为止,要求步数最少,也就是最优解法

比如 2 -> 11

step 1: 2 *2 =4

step 2: 4 +1 = 5

step 3: 5 *2 =10

step 4: 10 +1 = 11

类似这种


刚开始面对这道题的我来说,是懵逼的。。那时候哪知道什么 贪心 回溯 分治 动态规划 。。。。

虽然现在也不是很懂,,哈哈哈

大家可以先不看答案,反正思路我也大概说了,大家可以自己做着玩,,


我哥哥的代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TestPro03
{
    class Program
    {
        static void Main(string[] args)
        {
            int a = 101;
            int b = 2;
            System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch();
            stopwatch.Start();
            trans(a, b);
            print(a, b);
            stopwatch.Stop();
            TimeSpan timeSpan = stopwatch.Elapsed;
            Console.WriteLine("milliSeconds : " + timeSpan.Milliseconds);
            Console.ReadKey();
        }

        static List<int> res = new List<int>(); //存储每一步变换后的元素
        static void trans(int st, int ed) //变换
        {
            Dictionary<int, int> myDic = new Dictionary<int, int>();//用三种方法的结果来当key保存之前的值
            List<int> vis = new List<int>();//存储所有出现过的结果
            List<int> que = new List<int>();//存储参与运算的值
            myDic[st] = st;
            que.Add(st); 
            vis.Add(st); 
            while (que.Count != 0) //存储
            {
                int now = que.First<int>();
                que.Remove(que.First<int>());
                //只参与一次
                int next1 = fun1(now);
                int next2 = fun2(now);
                int next3 = fun3(now);
                int next4 = fun4(now) - (int)fun4(now) == 0 ? (int)fun4(now) : st;
                if (!vis.Contains(next1)) //判断结果是否存在于集合之中
                {
                    vis.Add(next1);
                    myDic[next1] = now;
                    if (next1 == ed) break;//是否到达最终结果
                    que.Add(next1);
                }
                if (!vis.Contains(next2))
                {
                    vis.Add(next2);
                    myDic[next2] = now;
                    if (next2 == ed) break;
                    que.Add(next2);
                }
                if (!vis.Contains(next3))
                {
                    vis.Add(next3);
                    myDic[next3] = now;
                    if (next3 == ed) break;
                    que.Add(next3);
                }
                if (!vis.Contains(next4))
                {
                    vis.Add(next4);
                    myDic[next4] = now;
                    if (next4 == ed) break;
                    que.Add(next4);
                }
            }
            int k = ed;
            while (true) //最终用到的元素
            {
                if (k == myDic[k]) break;
                res.Add(k);
                k = myDic[k];
            }
        }

        static void print(int st, int ed) //输出
        {
            Console.WriteLine("need {0} steps", res.Count);
            int pre = st;
            int t = 0;
            int count = res.Count;
            for (int i = count - 1; i >= 0; i--)
            {
                int now = res[i];
                t++;
                string str = "step" + t + ":" + pre + "->" + now;
                Console.WriteLine(str);
                pre = now;
            }
        }

        static int fun1(int a) //乘
        {
            int b = a * 2;
            return b;
        }
        static int fun2(int a) //减
        {
            int b = a - 1;
            return b;
        }
        static int fun3(int a) //加
        {
            int b = a + 1;
            return b;
        }
        static double fun4(int a) //除
        {
            double b = (double)a / 2;
            return b;
        }
    }
}

其实这份代码我哥哥原本给我时候是一份C++的代码,被我硬生生的翻译成了C#,整体我已经大概实验过了,确实是最优的,有没有没有考虑的地方我就不知道了。

如果大家有什么可以教博主的地方,还请大家不吝赐教,博主是个新程序猿,很菜鸡的那种难过难过

很希望能和大家一起讨论学习

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值