BAT面试之数字跳跃

有这样一个段子:”假设有一滴水,从几千米高空垂直落下,砸到人身上,会怎么样?“

不知道,这算不算一个嘲笑中国应试教育下的新时代年轻人智商的段子。

中国软件行业GDP总值,傲视全球。然而,中国没有纯国产的浏览器,没有纯国产的操作系统,甚至没有一门拿得出手的纯国产的计算机语言,当然网络喷子自行脑补发明的除外。

特殊体制下商人的急功近利,追名逐利,摧毁了原本引以为傲的工匠精神,在这种环境下,少有人会去用心学习、思考、创新,人心变得虚荣、浮躁、缺乏修养。

下游产业虽然创建了不俗的GDP,但技术仍然掌握在别人手里。别人发明了种子,而我们只是多收了三五斗而已。

鉴于中京闭关锁网,单以百度为例,搜索一个技术问题,100篇技术帖子,其中有97篇是搬砖,如此种种,可见一斑。

围绕于软件行业的教育产业,依然任重而道远。

有这样一道百度笔试题目(2021校招):

牛牛很喜欢在数字序列中跳跃,现在他正站在1号位置,每次跳跃,他可以向后跳一步(即从i跳到i+1),也可以跳到该位置往后的任意一个与该位置上的数字相同的位置,请问他最少需要跳多少步才能跳到N号位置?

当你看到这道题目时,如果第一件想到的事是去百度查一下,那么,正如《美丽心灵》中的纳什所说:你们这么做就是浪费时间。

因为有可能你看到的80%的帖子都是一个错误引发的谬误转载链,与其如此,不如坐下来,沉下心里,仔细用心想一想。

说什么深度优先,嚷什么动态规划,其实就是考察你的编程基本功和一点点思维想像力而已。

话不多说,直接上码:

        int[] array = new int[] {1, 2, 3, 4, 5, 6, 7, 6, 8, 0, 4, 6, 1, 7, 4};
        // 记录某个自然数可以最少步数达到的位置,即在array中的索引,为了处理方便,假设这个索引是从1开始的
        int[] pos = new int[10];
        // 到达某个指定数字所需要的最小步数。
        // 这里有一个公式,此最小步数=min(第一次出现此相同数字的最小步数,前一个相邻数字的最小步数)+1
        int[] minSteps = new int[array.length];

        // 初始化数据,避免在循环中反复判断,便利循环可从1开始
        // 由于数组默认值均为0,为简化程序,假设pos中记录的索引位置从1开始,不然的话,就需要将整个数组初始化为-1
        pos[array[0]] = 1;
        minSteps[0] = 0;

        // 只进行一次遍历,无递归,无回溯,无遍历查找,时间复杂度为O(n)
        for (var i = 1; i < array.length; i++) {
            int lastMeetIdx = pos[array[i]];// 当前数字,可以最少步数到达的位置

            if (lastMeetIdx == 0) {// 表示此数字未出现过
                minSteps[i] = minSteps[i - 1] + 1;
                pos[array[i]] = i + 1;// 修正可以最少步数到达的位置
            } else {
                int lastSameNumberMinSteps = minSteps[lastMeetIdx - 1];
                if (lastSameNumberMinSteps < minSteps[i - 1]) {
                    minSteps[i] = lastSameNumberMinSteps + 1;
                } else {
                    minSteps[i] = minSteps[i - 1] + 1;
                    pos[array[i]] = i + 1;// 修正可以最少步数到达的位置
                }
            }
        }

        // 获取结果路径,时间复杂度近似为O(0)
        int[] router = new int[minSteps[array.length - 1] + 1];
        int routerIdx = router.length - 1;

        int p = array.length - 1;// 输出路径右指针
        for (var i = minSteps[array.length - 1]; i >= 0; i--) {
            if (minSteps[p] == i) {
                router[routerIdx--] = array[p];
                p--;
            } else if (minSteps[pos[array[p + 1]] - 1] == i) {
                router[routerIdx--] = array[pos[array[p + 1]] - 1];
                p = pos[array[p]] - 2;
            }
        }

        // 显示最终结果,时间复杂度近似为O(0)
        for (var i = 0; i < router.length; i++) {
            if (i == router.length - 1) {
                System.out.print(router[i]);
            } else {
                System.out.print(router[i] + "->");
            }
        }

 

注意:

1.以上只是给出问题的解决思路,任何语言皆可参照实现(可采用各自语言的特点和长处)。

2.由于隶属算法题目,以上虽然使用的是java,但使用的是c思想,尽最大可能减少对象的创建,对象的封箱拆箱,尽量使用原始数据类型,以提升性能。

 

-----完-----

 

posted @ 2021-04-03 15:19  一千堆雪  阅读(71)  评论(0编辑  收藏  举报