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思想,尽最大可能减少对象的创建,对象的封箱拆箱,尽量使用原始数据类型,以提升性能。
-----完-----