记一次手撕算法面试

前言

  • 常网IT源码上线啦!
  • 本篇录入吊打面试官专栏,希望能祝君拿下Offer一臂之力,各位看官感兴趣可移步🚶。
  • 有人说面试造火箭,进去拧螺丝;其实个人觉得问的问题是项目中涉及的点 || 热门的技术栈都是很好的面试体验,不要是旁门左道冷门的知识,实际上并不会用到的。
  • 接下来想分享一些自己在项目中遇到的技术选型以及问题场景。

辛苦了一年,咱也不是身无分纹还有抬头纹鱼尾纹法令纹。

一、前言

现在还是金三银四,去找虐,很多大厂都喜欢让候选人手写算法题,她也不例外。

其实给的题不难,但是要看你怎么优雅的写出如诗一般的代码。

那么,请看题目。

输入一个字符串,打印出该字符串中,所有字符的排列组合。

哦,看着还行啊。

二、分析

盲猜递归。

要打印出字符串中所有字符的排列组合,可以使用递归的方法。

于是,如诗一般的代码就写出来了。

java 复制代码
function permute(str, memo = [], result = []) {  
    // 如果memo的长度等于str的长度,说明找到了一个完整的排列,将其添加到结果数组中  
    if (memo.length === str.length) {  
        result.push(memo.join(''));  
        return;  
    }  
  
    // 遍历字符串中的每个字符  
    for (let i = 0; i < str.length; i++) {  
        // 如果当前字符已经在memo中,则跳过以避免重复  
        if (memo.includes(str[i])) continue;  
  
        // 将当前字符添加到memo中,并递归调用permute函数继续处理剩余字符  
        memo.push(str[i]);  
        console.log(memo, 'meno', i)
        permute(str, memo, result);  
          
        // 回溯,将当前字符从memo中移除,以便尝试其他排列  
        memo.pop();  
        console.log(memo, 'pop', i)
    }  
  
    return result;  
}  
  
// 示例用法  
const inputString = "abc";  
const permutations = permute(inputString);  
  
// 打印所有排列组合  
permutations.forEach(permutation => {  
    console.log(permutation);  
//         abc
// VM84:30 acb
// VM84:30 bac
// VM84:30 bca
// VM84:30 cab
// VM84:30 cba
});

代码看着有点少,但接下来我的分析,想要细点。

我们好好来分析,要了解好递归思想。

首先,我们执行permute方法,进行for循环

此时i = 0;memo为空。

push第一个,a

接着进入递归permute(str, memo = [a], result);

  • 我们调用,来到for循环,此时memo = [a]

    • 接着momo开始push个b,memo = [a, b]

      • 进入递归permute(str, memo = [a, b], result);

        • 调用,来到for循环,此时memo = [a, b]

        • 接着momo开始push个c,memo = [a, b, c]

          • 进入递归permute(str, memo = [a, b, c], result); 走进if,result添加第一个完整的数组
        • 后面还有个memo.pop(); 此时的memo = [a, b, c]

      • 他后面还有个memo.pop(); 此时的memo = [a, b]

    • 接着momo开始push个c,memo = [a, c]

    • 进入递归permute(str, memo = [a, c], result);

      • 调用,来到for循环,此时memo = [a, c]

      • 接着momo开始push个b,memo = [a, c, b]

        • 进入递归permute(str, memo = [a, c, b], result); 走进if,result添加第2个完整的数组
      • 后面还有个memo.pop(); 此时的memo = [a, c, b]

    • 他后面还有个memo.pop(); 此时的memo = [a, c]

别忘记了后面memo.pop(); 此时的memo = [a]

这是给大家详细的演示i = 0的情况。

接着后面还有i = 1和i = 2的情况,就不带大家走了,相信看完i = 0就懂了,多看几遍。

另外i = 1,b的情况;i = 2,c的情况,打印也列出来了,大家看看自己做的时候,对下答案。

三、递归

他们说:想要自己真的懂,就要讲给别人也懂,这个过程,你会更通透这个知识点。

刚好最近考软考,也有一些算法思想在里面。

递归算法通过​​分治思想​ ​将问题分解为子问题:​​固定一个字符,递归排列剩余字符​​。当剩余字符排列完成时,与已固定的字符组合形成完整排列。

递归三要素:

  1. ​终止条件​​:当前排列长度等于原字符串长度,存入结果集。

  2. ​子问题拆分​​:每次选择一个未被使用的字符加入当前排列。

  3. ​回溯机制​​:递归完成后撤销当前选择,尝试其他可能性

空间复杂度O(n),递归调用栈深度为n。

至此撒花~

后记

递归虽好,但要小心使用。

很多初学者,用了之后,可能会进入死循环,递归终止的边界,防止无限调用。

还记得刚开始学递归的时候,是斐波那契数列中,F(n) = F(n-1) + F(n-2),这玩意会被重复计算,如fib(3)。

未优化的递归时间复杂度为指数级,恐怖如斯。

优化的点可以有:

缓存中间结果,避免重复计算。

尾递归优化。

还有快排、阶乘

如果想要最优解,才是最难的。

如果看得不是很明白,可以多看几遍,一通则通,接下来的算法题像是打通这道门。

我们在实际项目中或多或少遇到一些奇奇怪怪的问题。

自己也会对一些写法的思考,为什么不行🤔,又为什么行了?

最后,祝君能拿下满意的offer。

我是Dignity_呱,来交个朋友呀,有朋自远方来,不亦乐乎呀!深夜末班车

👍 如果对您有帮助,您的点赞是我前进的润滑剂。

以往推荐

决定我的offer:问了我3个websocket的问题

几分钟写一个插件

前端哪有什么设计模式(12k+)

为什么没人用mixin(7k+)

小小导出,我大前端足矣!

靓仔,说一下keep-alive缓存组件后怎么更新及原理?

面试官问我new Vue阶段做了什么?

前端仔,快把dist部署到Nginx上

多图详解,一次性啃懂原型链(上万字)

Vue-Cli3搭建组件库

Vue实现动态路由(和面试官吹项目亮点)

VuePress搭建项目组件文档

原文链接

juejin.cn/post/749725...

相关推荐
DC...19 分钟前
vue滑块组件设计与实现
前端·javascript·vue.js
Mars狐狸27 分钟前
AI项目改用服务端组件实现对话?包体积减小50%!
前端·react.js
H5开发新纪元36 分钟前
Vite 项目打包分析完整指南:从配置到优化
前端·vue.js
嘻嘻嘻嘻嘻嘻ys37 分钟前
《Vue 3.3响应式革新与TypeScript高效开发实战指南》
前端·后端
云格~43 分钟前
Leetcode:1. 两数之和
数据结构·算法·leetcode
几点才到啊1 小时前
C语言实现冒泡排序:算法原理与代码解析
c语言·算法·排序算法
xxjiaz1 小时前
水果成篮--LeetCode
java·算法·leetcode·职场和发展
恋猫de小郭1 小时前
腾讯 Kuikly 正式开源,了解一下这个基于 Kotlin 的全平台框架
android·前端·ios
binary思维1 小时前
C语言实现贪心算法
c语言·算法·贪心算法