2024年Web前端最新(立下flag)每日10道前端面试题-23 关于【回溯】算法题,读完我这份《前端开发核心源码精编解析》面试至少多要3K

框架相关

原生JS虽能实现绝大部分功能,但要么就是过于繁琐,要么就是存在缺陷,故绝大多数开发者都会首选框架开发方案。现阶段较热门是React、Vue两大框架,两者工作原理上存在共通点,也存在一些不同点,对于校招来说,不需要两个框架都学得特别熟,一般面试官会针对你简历中写的框架进行提问。

在框架方面,生命周期、钩子函数、虚拟DOM这些基本知识是必须要掌握的,在学习的过程可以结合框架的官方文档

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

Vue框架

知识要点:
1. vue-cli工程
2. vue核心知识点
3. vue-router
4. vuex
5. http请求
6. UI样式
7. 常用功能
8. MVVM设计模式

React框架

知识要点:
1. 基本知识
2. React 组件
3. React Redux
4. React 路由

1.括号生成


数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例:

输入:n = 3

输出:[

“((()))”,

“(()())”,

“(())()”,

“()(())”,

“()()()”

]

方法一:深度优先遍历

我们以 n = 2 为例,画树形结构图。方法是 “做减法”。

画图以后,可以分析出的结论:

当前左右括号都有大于 0个可以使用的时候,才产生分支;

产生左分支的时候,只看当前是否还有左括号可以使用;

产生右分支的时候,还受到左分支的限制,右边剩余可以使用的括号数量一定得在严格大于左边剩余的数量的时候,才可以产生分支;

在左边和右边剩余的括号数都等于 0 的时候结算。

import java.util.ArrayList;

import java.util.List;

public class Solution {

// 做减法

public List generateParenthesis(int n) {

List res = new ArrayList<>();

// 特判

if (n == 0) {

return res;

}

// 执行深度优先遍历,搜索可能的结果

dfs(“”, n, n, res);

return res;

}

/**

* @param curStr 当前递归得到的结果

* @param left   左括号还有几个可以使用

* @param right  右括号还有几个可以使用

* @param res    结果集

*/

private void dfs(String curStr, int left, int right, List res) {

// 因为每一次尝试,都使用新的字符串变量,所以无需回溯

// 在递归终止的时候,直接把它添加到结果集即可,注意与「力扣」第 46 题、第 39 题区分

if (left == 0 && right == 0) {

res.add(curStr);

return;

}

// 剪枝(如图,左括号可以使用的个数严格大于右括号可以使用的个数,才剪枝,注意这个细节)

if (left > right) {

return;

}

if (left > 0) {

dfs(curStr + “(”, left - 1, right, res);

}

if (right > 0) {

dfs(curStr + “)”, left, right - 1, res);

}

}

}

我们运行 n = 2 的情况,得到结果 [(()), ()()] ,说明分析的结果是正确的。

基于动态规划思路

选最左边的括号(必然存在与其配对的回括号)这一对括号,可以将括号组分隔成2部分:

n对括号的组合 = ‘(’+p对括号组合+‘)’+q对括号组合, 其中p+q = n-1, 0 <= p <= n-1

在arr数组存放所有对数i(i < n)的排列结果,arr中每一项也都是个数组,是i对括号时的组合结果。

/**

* @param n

*/

function generateParenthesis(n) {

let arr = [];

// 初始值

arr[0] = [‘’]; // 为了循环能开始

arr[1] = [‘()’];

for(let i = 2; i<=n; i++) {

let tmpArr = [];

for(let p = 0; p<i;p++) {

arr[p].forEach(itemP => {

arr[i-1-p].forEach(itemQ => {

tmpArr.push(‘(’ + itemP + ‘)’ + itemQ);

})

})

}

arr.push(tmpArr);

}

return arr[n];

}。

全排列


给定一个 没有重复 数字的序列,返回其所有可能的全排列。

示例:

输入: [1,2,3]

输出:

[

[1,2,3],

[1,3,2],

[2,1,3],

[2,3,1],

[3,1,2],

[3,2,1]

]

抽象成一颗决策树

  • 第一位有3种选择,选1的话,则第二位就只能2或3,如果选2,则第三位只能选3

  • 然后回到第二位,选3,则第三位就只能选2

  • 接着回到第一位,之前选了1,现在选2,然后继续往下做决策

  • 这其实构成了一颗决策树,并且出现了回溯。如图所示:

1种“排列组合” 可看作 1条路径

  • 从根节点开始,path 路径数组为空,代表状态是还没选择,它面临3个选择

  • 每个子节点又有3个选择,从上往下作出决策,选择就像走过一个点,组成了一条路径

  • 遍历到树的底部就结束遍历,没有可选的数字,此时path的长度和nums一样,它就是全排列之一

  • 定义dfs函数,它

  • 参数接收的是:当前path数组的状态,比如根节点的path为[]。

要有出口:当path的长度达到了和nums的长度一样,意味着路径已走完,一种排列组合已生成,推入res数组

遍历nums数组,每个数字都是一种选择,如果path数组中已经存在,则不推入path,否则推入path,就好似选择了走这一节点

然后递归调用dfs,在当前节点基础上继续往下dfs,遇到了出口就会调用结束

关于回溯

  • path.pop() 做的就是回溯,回溯就是撤销选择,回到之前的状态

  • 这样path路径的最后一个选择就被撤销了,继续下一次迭代,考察上一层的别的选择

  • 然后继续dfs,继续回溯

  • 最后你发现穷举整个决策树是不可避免的,这是回溯算法的一个特点

代码

var permute = (nums) => {

let res = []

dfs([])

function dfs(path) {

if (path.length===nums.length) {

res.push(path.slice())

}

for (const num of nums) {

if (path.includes(num)) continue

path.push(num)

dfs(path)

path.pop()

}

}

return res

}

3.电话号码的字母组合


给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

示例:

输入:“23”

输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].

说明:

尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。

解法一:递归

回溯

var letterCombinations = function(digits) {

if(!digits){

return [];

}

var len = digits.length;

var map = new Map();

map.set(‘2’,‘abc’);

map.set(‘3’,‘def’);

map.set(‘4’,‘ghi’);

map.set(‘5’,‘jkl’);

map.set(‘6’,‘mno’);

map.set(‘7’,‘pqrs’);

map.set(‘8’,‘tuv’);

map.set(‘9’,‘wxyz’);

var result = [];

function _generate(i,str){

// terminator

if(i == len){

result.push(str);

return;

}

// process

// drill down

var tmp = map.get(digits[i]);

for(var r = 0;r<tmp.length;r++){

_generate(i+1,str+tmp[r]);

}

}

_generate(0,‘’);

return result;

};

4.子集


给定一组不含重复元素的整数数组 nums,返回该数组所有可能的子集(幂集)。

说明:解集不能包含重复的子集。

示例:

输入: nums = [1,2,3]

输出:

[

[3],

[1],

[2],

[1,2,3],

[1,3],

[2,3],

[1,2],

[]

]

解法三:递归回溯

框架相关

原生JS虽能实现绝大部分功能,但要么就是过于繁琐,要么就是存在缺陷,故绝大多数开发者都会首选框架开发方案。现阶段较热门是React、Vue两大框架,两者工作原理上存在共通点,也存在一些不同点,对于校招来说,不需要两个框架都学得特别熟,一般面试官会针对你简历中写的框架进行提问。

在框架方面,生命周期、钩子函数、虚拟DOM这些基本知识是必须要掌握的,在学习的过程可以结合框架的官方文档

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

Vue框架

知识要点:
1. vue-cli工程
2. vue核心知识点
3. vue-router
4. vuex
5. http请求
6. UI样式
7. 常用功能
8. MVVM设计模式

React框架

知识要点:
1. 基本知识
2. React 组件
3. React Redux
4. React 路由

生JS虽能实现绝大部分功能,但要么就是过于繁琐,要么就是存在缺陷,故绝大多数开发者都会首选框架开发方案。现阶段较热门是React、Vue两大框架,两者工作原理上存在共通点,也存在一些不同点,对于校招来说,不需要两个框架都学得特别熟,一般面试官会针对你简历中写的框架进行提问。

在框架方面,生命周期、钩子函数、虚拟DOM这些基本知识是必须要掌握的,在学习的过程可以结合框架的官方文档

开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】

Vue框架

知识要点:
1. vue-cli工程
2. vue核心知识点
3. vue-router
4. vuex
5. http请求
6. UI样式
7. 常用功能
8. MVVM设计模式

[外链图片转存中…(img-gCqki0ZZ-1715471840215)]

React框架

知识要点:
1. 基本知识
2. React 组件
3. React Redux
4. React 路由

[外链图片转存中…(img-Jf3lF3wK-1715471840216)]

  • 13
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值