2024年Web前端最新(立下flag)每日10道前端面试题-23 关于【回溯】算法题,原理解析

文末

如果30岁以前,可以还不知道自己想去做什么的话,那30岁之后,真的觉得时间非常的宝贵,不能再浪费时间在一些碎片化的事情上,比如说看综艺,电视剧。一个人的黄金时间也就二,三十年,不能过得浑浑噩噩。所以花了基本上休息的时间,去不断的完善自己的知识体系,希望可以成为一个领域内的TOP。

同样是干到30岁,普通人写业务代码划水,榜样们深度学习拓宽视野晋升管理。

这也是为什么大家都说30岁是程序员的门槛,很多人迈不过去,其实各行各业都是这样都会有个坎,公司永远都缺的高级人才,只用这样才能在大风大浪过后,依然闪耀不被公司淘汰不被社会淘汰。

269页《前端大厂面试宝典》

包含了腾讯、字节跳动、小米、阿里、滴滴、美团、58、拼多多、360、新浪、搜狐等一线互联网公司面试被问到的题目,涵盖了初中级前端技术点。

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

前端面试题汇总

JavaScript

[

[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],

[]

]

解法三:递归回溯

/**

* @param {number[]} nums

* @return {number[][]}

*/

var subsets = function(nums) {

let n = nums.length;

let tmpPath = [];

let res = [];

let backtrack = (tmpPath,start) => {

res.push(tmpPath);

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

tmpPath.push(nums[i]);

backtrack(tmpPath.slice(),i+1);

tmpPath.pop();

}

}

backtrack(tmpPath,0);

return res;

};

解法一:迭代

var subsets = function(nums) {

let ws = [[]];

for(let i=0; i < nums.length; ++i) {

for(let j=0, len = ws.length; j < len; ++j) {

ws.push(ws[j].concat([nums[i]]));

}

}

return ws;

};

解法二:位运算

/**

* @param {number[]} nums

* @return {number[][]}

*/

var subsets = function(nums) {

let res = [];

let len = nums.length;

// 2^n 获取所有状态

let resAll = 1 << len;

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

let subset = [];

// 当前数组的索引位置

let j = 0;

// 移位

let iCopy = i;

while(iCopy != 0){

//判断当前位置是否是1

if( (iCopy & 1) == 1){

subset.push(nums[j]);

}

j++;

// 右移一位

iCopy >>= 1;

}

res.push(subset);

}

return res;

};

5.组合总和


给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的数字可以无限制重复被选取。

说明:

所有数字(包括 target)都是正整数。

解集不能包含重复的组合。

示例 1:

输入: candidates = [2,3,6,7], target = 7,

所求解集为:

[

[7],

[2,2,3]

]

示例 2:

输入: candidates = [2,3,5], target = 8,

所求解集为:

[

[2,2,2,2],

[2,3,3],

[3,5]

]

/**

* @param {number[]} candidates

* @param {number} target

* @return {number[][]}

*/

var combinationSum = function(candidates, target) {

let n = candidates.length;

let res = [];

let tmpPath = [];

let backtrack = (tmpPath,target,start) => {

if(target < 0){

return;

}

if(target == 0){

res.push(tmpPath);

return;

}

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

tmpPath.push(candidates[i]);

backtrack(tmpPath.slice(),target - candidates[i],i);

tmpPath.pop();

}

}

backtrack(tmpPath,target,0);

return res;

};

最后

中年危机是真实存在的,即便有技术傍身,还是难免对自己的生存能力产生质疑和焦虑,这些年职业发展,一直在寻求消除焦虑的依靠。

  • 技术要深入到什么程度?

  • 做久了技术总要转型管理?

  • 我能做什么,我想做什么?

  • 一技之长,就是深耕你的专业技能,你的专业技术。(重点)

  • 独立做事,当你的一技之长达到一定深度的时候,需要开始思考如何独立做事。(创业)

  • 拥有事业,选择一份使命,带领团队实现它。(创业)

一技之长分五个层次

  • 栈内技术 - 是指你的前端专业领域技术

  • 栈外技术 - 是指栈内技术的上下游,领域外的相关专业知识

  • 工程经验 - 是建设专业技术体系的“解决方案”

  • 带人做事 - 是对团队协作能力的要求

  • 业界发声 - 工作经验总结对外分享,与他人交流

永远不要放弃一技之长,它值得你长期信仰持有

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

主要内容包括html,css,html5,css3,JavaScript,正则表达式,函数,BOM,DOM,jQuery,AJAX,vue 等等。

  • 23
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值