首页 最新 热门 推荐

  • 首页
  • 最新
  • 热门
  • 推荐

前端大厂手写题面试真题,面试通过率90%

  • 24-12-16 12:45
  • 4139
  • 6110
juejin.cn

导读:在本系列文章中,我整理了大量常见前端面试的手写体,以及详细的答案和代码示例。

如果需要更多完整版笔记或者前端资料,请看置顶文章评论区,无偿分享给大家

1.JavaScript面试真题 (35题)

2.CSS面试真题(20题)

3.ES6面试真题 (10题)

4.Vue2面试真题 (29题)

5.Vue3面试真题 (6题)

6.React面试真题 (31题)

7.Node.js面试真题 (14题)

8.小程序面试真题 (8题)

9.HTTP面试真题 (14题)

10.Typescript面试真题 (12题)

。。。。。。。。。。。。。。。。。。

手写题:

  1. 字节

1.1 两数之和

给定⼀个整数数组nums 和⼀个⽬标值target ,请你在该数组中找出和为⽬标值的那两个整数,并返回他们的数组下标。

你可以假设每种输⼊只会对应⼀个答案。但是,你不能重复利⽤这个数组中同样的元素。

⽰例:

ini
代码解读
复制代码
给定 nums = [2, 7, 11, 15], target = 9 因为 nums[0] + nums[1] = 2 + 7 = 9所以返回 [0, 1]

解题思路:

• 初始化⼀个map = new Map()

• 从第⼀个元素开始遍历nums

• 获取⽬标值与nums[i] 的差值,即k = target - nums[i] ,判断差值在map 中是否存在

◦ 不存在(map.has(k) 为false ),则将nums[i] 加⼊到map 中(key为nums[i] ,value为i ,⽅便查找map中是否存在某值,并可以通过get ⽅法直接拿到下标)

◦ 存在(map.has(k) ),返回[map.get(k), i] ,求解结束

• 遍历结束,则nums 中没有符合条件的两个数,返回[]

时间复杂度:O(n)

代码实现:

ini
代码解读
复制代码
const twoSum = function(nums, target) { let map = new Map() for(let i = 0; i< nums.length; i++) { let k = target-nums[i] if(map.has(k)) { return [map.get(k), i] } map.set(nums[i], i) } return []; };

1.2 N数之和

请⽤算法实现,从给定的⽆需、不重复的数组A中,取出N个数,使其相加和为M。并给出算法的时间、空间复杂度,如:

ini
代码解读
复制代码
var arr = [1, 4, 7, 11, 9, 8, 10, 6]; var N = 3; var M = 27; Result: [7, 11, 9], [11, 10, 6], [9, 8, 10]

解题思路:利⽤⼆进制

根据数组⻓度构建⼆进制数据,再选择其中满⾜条件的数据。

我们⽤1 和0 来表⽰数组中某位元素是否被选中。因此,可以⽤0110 来表⽰数组中第1 位和第2 位被选中了。 所以,本题可以解读为:

• 数组中被选中的个数是N 。

• 被选中的和是M 。

我们的算法思路逐渐清晰起来:遍历所有⼆进制,判断选中个数是否为N ,然后再求对应的元素之和,看其是否为M 。

  1. 从数组中取出N个数

例如:

ini
代码解读
复制代码
var arr = [1, 2, 3, 4]; var N = 3; var M = 6;

如何判断N=3 是,对应的选取⼆进制中有⼏个1 喃?

最简单的⽅式就是:

dart
代码解读
复制代码
const n = num => num.toString(2).replace(/0/g, '').length

这⾥我们尝试使⽤⼀下位运算来解决本题,因为位运算是不需要编译的(位运算直接⽤⼆进制进⾏表⽰,省去了中间过程的各种复杂转换,提⾼了速度),肯定速度最快。

我们知道1&0=0 、1&1=1 , 1111&1110=1110 ,即15&14=14 ,所以我们每次& ⽐⾃⾝⼩1 的数都会消除⼀个1 ,所以这⾥建⽴⼀个迭代,通过统计消除的次数,就能确定最终有⼏个1了:

dart
代码解读
复制代码
const n = num => { let count = 0 while(num) { num &= (num - 1) count++ } return count }

2. 和为M

现在最后⼀层判断就是选取的这些数字和必须等于M ,即根据N ⽣成的对应⼆进制所在元素上的和是否为M

⽐如1110 ,我们应该判断arr[0] + arr[1] + arr[2] 是否为M 。

那么问题也就转化成了如何判断数组下标是否在1110 中呢?如何在则求和

其实也很简单,⽐如下标1 在,⽽下标3 不在。我们把1 转化成0100 ,1110 & 0100 为0100 ,⼤于0 ,因此下标1 在。⽽1110 & 0001 为0 ,因此下标3 不在。

所以求和我们可以如下实现:

ini
代码解读
复制代码
let arr = [1,2,3,4] // i 为满⾜条件的⼆进制 let i = 0b1110 let s = 0, temp = [] let len = arr.length for (let j = 0; j < len; j++) { if ( i & 1 << (len - 1 - j)) { s += arr[j] temp.push(arr[j]) } } console.log(temp) // => [1, 2, 3]

最终实现

scss
代码解读
复制代码
// 参数依次为⽬标数组、选取元素数⽬、⽬标和 const search = (arr, count, sum) => { // 计算某选择情况下有⼏个 1,也就是选择元素的个数 const getCount = num => { let count = 0 while(num) { num &= (num - 1) count++ } return count } let len = arr.length, bit = 1 << len, res = [] // 遍历所有的选择情况 for(let i = 1; i < bit; i++){ // 满⾜选择的元素个数 === count if(getCount(i) === count){ let s = 0, temp = [] // 每⼀种满⾜个数为 N 的选择情况下,继续判断是否满⾜ 和为 M for(let j = 0; j < len; j++){ // 建⽴映射,找出选择位上的元素 if(i & 1 << (len - 1 -j)) { s += arr[j] temp.push(arr[j]) } } // 如果这种选择情况满⾜和为 M if(s === sum) { res.push(temp) } } } return res }

1.3 编写⼀个程序,找到两个单链表相交的起始节点

编写⼀个程序,找到两个单链表相交的起始节点。

如下⾯的两个链表:

image.png

在节点c1开始相交。

⽰例1:

image.png

ini
代码解读
复制代码
输⼊:intersectVal = 8, listA = [4,1,8,4,5], listB = [5,0,1,8,4,5], skipA = 2, sk 输出:Reference of the node with value = 8 输⼊解释:相交节点的值为 8 (注意,如果两个列表相交则不能为 0)。从各⾃的表头开始算起,链表

⽰例2:

image.png

ini
代码解读
复制代码
输⼊:intersectVal = 2, listA = [0,9,1,2,4], listB = [3,2,4], skipA = 3, skipB = 输出:Reference of the node with value = 2 输⼊解释:相交节点的值为 2 (注意,如果两个列表相交则不能为 0)。从各⾃的表头开始算起,链表

⽰例3:

image.png

css
代码解读
复制代码
输⼊:intersectVal = 0, listA = [2,6,4], listB = [1,5], skipA = 3, skipB = 2 输出:null 输⼊解释:从各⾃的表头开始算起,链表 A 为 [2,6,4],链表 B 为 [1,5]。由于这两个链表不相交, 解释:这两个链表不相交,因此返回 null。

注意:

• 如果两个链表没有交点,返回null.

• 在返回结果后,两个链表仍须保持原有的结构。

• 可假定整个链表结构中没有循环。

• 程序尽量满⾜O(n)时间复杂度,且仅⽤O(1)内存。

⽅法:遍历

• 先将两个链表转换成数组结构

• 对其中⼀个数组进⾏遍历,每次遍历判断另⼀个数组是否含有该值

• 遍历结束后如果没有找到就返回null

scss
代码解读
复制代码
function intersectNode( head1, head2 ) { var arr1 = [], arr2 = [], theValue = null; transformToArray( head1, arr1 ); transformToArray( head2, arr2 ); for (var i = 0; i < arr1.length; i++) { if( arr2.indexOf(arr1[i]) !== -1 ){ theValue = arr1[i]; return 'Reference of the node with value = ' + theValue; } } return theValue; /* arr1.some( value => { if ( arr2.includes(value) ){ theValue = value; return true; } }) if( theValue ){ return 'Reference of the node with value = ' + theValue; } return null; */ } function transformToArray( head, arr ) { while( head ){ arr.push(head.val); head = head.next; } }

测试代码:

scss
代码解读
复制代码
function CreateNode(val){ this.val = val; this.next = null; } function CreateList(...nodes){ this.head = nodes[0]; this.length = nodes.length; for( var i = 0; i < nodes.length - 1; i++ ){ if( nodes[i+1] ){ nodes[i].next = nodes[i+1]; } } } function intersectNode( head1, head2 ) { var arr1 = [], arr2 = [], theValue = null; transformToArray( head1, arr1 ); transformToArray( head2, arr2 ); for (var i = 0; i < arr1.length; i++) { if( arr2.indexOf(arr1[i]) !== -1 ){ theValue = arr1[i]; return 'Reference of the node with value = ' + theValue; } } return theValue; } function transformToArray( head, arr ) { while( head ){ arr.push(head.val); head = head.next; } } const node1 = new CreateNode(1); const node2 = new CreateNode(2); const node3 = new CreateNode(3); const node4 = new CreateNode(4); const node5 = new CreateNode(5); const nodeA = new CreateNode('A'); const nodeB = new CreateNode('B'); const nodeC = new CreateNode('C'); const nodeD = new CreateNode('D'); const nodeE = new CreateNode('E'); const list1 = new CreateList(node1, node2, node3, node4, node5); const list2 = new CreateList(nodeA, nodeB, node3, nodeC, nodeD); intersectNode(list1.head, list2.head);

1.4 翻转字符串⾥的单词

给定⼀个字符串,逐个翻转字符串中的每个单词。

⽰例1:

arduino
代码解读
复制代码
输⼊: "the sky is blue" 输出: "blue is sky the"

⽰例2:

makefile
代码解读
复制代码
输⼊: " hello world! " 输出: "world! hello" 解释: 输⼊字符串可以在前⾯或者后⾯包含多余的空格,但是反转后的字符不能包括。

⽰例3:

makefile
代码解读
复制代码
输⼊: "a good example" 输出: "example good a" 解释: 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含⼀个。

说明:

• ⽆空格字符构成⼀个单词。

• 输⼊字符串可以在前⾯或者后⾯包含多余的空格,但是反转后的字符不能包括。

• 如果两个单词间有多余的空格,将反转后单词间的空格减少到只含⼀个。

解法⼀:正则+JSAPI

javascript
代码解读
复制代码
var reverseWords = function(s) { return s.trim().replace(/\s+/g, ' ').split(' ').reverse().join(' ') };

解法⼆:双端队列(不使⽤API)

双端队列,故名思义就是两端都可以进队的队列

解题思路:

• ⾸先去除字符串左右空格

• 逐个读取字符串中的每个单词,依次放⼊双端队列的对头

• 再将队列转换成字符串输出(以空格为分隔符)

画图理解:

image.png

image.png

image.png

代码实现:

sql
代码解读
复制代码
var reverseWords = function(s) { let left = 0 let right = s.length - 1 let queue = [] let word = '' while (s.charAt(left) === ' ') left ++ while (s.charAt(right) === ' ') right -- while (left <= right) { let char = s.charAt(left) if (char === ' ' && word) { queue.unshift(word) word = '' } else if (char !== ' '){ word += char } left++ } queue.unshift(word) return queue.join(' ') };

.....................

需要完整版的可以看置顶文章评论区

注:本文转载自juejin.cn的前端高端面试小组的文章"https://juejin.cn/post/7435851146979000329"。版权归原作者所有,此博客不拥有其著作权,亦不承担相应法律责任。如有侵权,请联系我们删除。
复制链接
复制链接
相关推荐
发表评论
登录后才能发表评论和回复 注册

/ 登录

评论记录:

未查询到任何数据!
回复评论:

分类栏目

后端 (14832) 前端 (14280) 移动开发 (3760) 编程语言 (3851) Java (3904) Python (3298) 人工智能 (10119) AIGC (2810) 大数据 (3499) 数据库 (3945) 数据结构与算法 (3757) 音视频 (2669) 云原生 (3145) 云平台 (2965) 前沿技术 (2993) 开源 (2160) 小程序 (2860) 运维 (2533) 服务器 (2698) 操作系统 (2325) 硬件开发 (2492) 嵌入式 (2955) 微软技术 (2769) 软件工程 (2056) 测试 (2865) 网络空间安全 (2948) 网络与通信 (2797) 用户体验设计 (2592) 学习和成长 (2593) 搜索 (2744) 开发工具 (7108) 游戏 (2829) HarmonyOS (2935) 区块链 (2782) 数学 (3112) 3C硬件 (2759) 资讯 (2909) Android (4709) iOS (1850) 代码人生 (3043) 阅读 (2841)

热门文章

101
推荐
关于我们 隐私政策 免责声明 联系我们
Copyright © 2020-2025 蚁人论坛 (iYenn.com) All Rights Reserved.
Scroll to Top