前端面试之你可能会遇到的编程题(1)

“开源(open source)”这个词,指的是事物规划为可以公开访问的,因此人们可以修改并分享。

作为一个从大型同性社交网站GitHub / Rain120上学习成长的一个前端菜鸟的我,深受大佬的感染,也希望有机会能够给同样是菜鸟的你们提供帮助,在我学习之余,留下了之前学习遇到的、网上看到的、笔试面试遇到的一些编程的解法,还请各位大佬手下留情,多多提携、指点我等菜鸟。

欢迎各位大佬留下更加简单的写法,谢谢!!

抱大腿

代码仓库: Web-Study

废话不多说,先上题吧。

1、关系型数组转换成树形结构对象(拼多多2018前端笔试真题 / 依图面试)

关系型数组

1
2
3
4
5
var obj = [
{ id:3, parent:2 },
{ id:1, parent:null },
{ id:2, parent:1 },
]

期望结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
o = {
obj: {
id: 1,
parent: null,
child: {
id: 2,
parent: 1,
child: {
id: ,3,
parent: 2
}
}
}
}

思路:

先找到它的根元素,根据idparent来判断它们之间的关系

实现源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function treeObj(obj) {
obj.map(item => {
if (item.parent !== null) {
obj.map(o => {
if (item.parent === o.id) {
if (!o.child) {
o.child = [];
}
o.child.push(item);
o.child = o.child;
}
});
}
});
return obj.filter(item => item.parent === null)[0]
}

解法2:(知乎评论区提供的方法)

1
2
3
4
function treeObj(obj) {
return obj.sort((a, b) => b.parent - a.parent)
.reduce((acc, cur) => (acc ? { ...cur, child: acc } : cur));
}

实现效果:
第一题实现效果

2、请用 javascript 实现一个函数 parseUrl(url),将一段 url字符串解析为 Object。(西洋汇笔试)

1
parseUrl("http://www.xiyanghui.com/product/list?id=123456&sort=discount#title");

期望结果:

1
2
3
4
5
6
7
8
9
10
{
protocol: "http",
host: "www.xiyanghui.com",
path: "/product/list",
params: {
id: "12345",
sort: "discount"
},
hash: "title"
}

思路:

首先我们需要了解一下URL这个概念。

URL(统一资源定位符)(或称统一资源定位器/定位地址、URL地址等,英语:Uniform Resource Locator,常缩写为URL),有时也被俗称为网页地址(网址)。

这里,我补充一点,各位不仅需要了解 URL,还需要了解 URI

URI:统一资源标识符(英语:Uniform Resource Identifier,或URI)是一个用于标识某一互联网资源名称的字符串。 该种标识允许用户对网络中(一般指万维网)的资源通过特定的协议进行交互操作。URI的最常见的形式是统一资源定位符(URL),经常指定为非正式的网址。更罕见的用法是统一资源名称(URN),其目的是通过提供一种途径。用于在特定的名字空间资源的标识,以补充网址。

URI包括了URLURN
URI

下图展示了两个 URI 例子及它们的组成部分。
URI 例子及它们的组成部分

URL一般包括协议域名端口queryparams等,我们在传入参数时是字符串,我们需要将它转换成URL,可以通过创建一个a标签来将字符串 转换成URL

实现源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function parseUrl(url) {   
var a = document.createElement('a');
a.href = url;
return {
source: url,
protocol: a.protocol.replace(':',''),
host: a.hostname,
port: a.port,
query: a.search,
params: (() => {
var ret = {}, querys = [];
var searchQuery = a.search.replace(/^\?/,'').split('&');
for ( var i = 0;i < searchQuery.length; i++) {
if (searchQuery[i]) {
querys = searchQuery[i].split('=');
ret[querys[0]] = querys[1];
}
}
return ret;
})(),
file: (a.pathname.match(/\/([^\/?#]+)$/i) || [,''])[1],
hash: a.hash.replace('#',''),
path: a.pathname.replace(/^([^\/])/,'/$1'),
relative: (a.href.match(/tps?:\/\/[^\/]+(.+)/) || [,''])[1],
segments: a.pathname.replace(/^\//,'').split('/')
};
}
parseUrl("http://www.xiyanghui.com/product/list?id=123456&sort=discount#title");

实现效果:
第二题实现效果:

3、数组元素的排列组合问题

1
[1, 2, 3]

期望结果:

全排列:
全排列

1
[[1, 2], [1, 3], [2, 1], [2, 3], [3, 1], [3, 2]]

思路:

每次取数组中的一个数,然后将剩余的数,依次加入到该数的组合数组中
全排列思路

实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
function Permutations (target, size, origin) {
var _arr = []
function getArrange(target, nums, ret) {
if (nums === 1) {
for (var i = 0; i < target.length; i++) {
var tmp = ret.slice();
tmp.push(target[i]);
_arr.push(tmp);
}
} else {
nums -= 1;
for (var i = 0; i < target.length; i++) {
var tmp = ret.slice();
var newTarget = target.slice();
tmp.push(target[i]);
newTarget.splice(i, 1);
getArrange(newTarget, nums, tmp);
}
}
}
getArrange(target, size, origin);
return _arr;
}
Permutations([1, 2, 3], 2, [])

实现效果:
全排列实现效果

1
[1, 2, 3, 4]

排列组合:
排列组合

1
[[1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4]]

思路:

取一个数,加入到数组中,接着再取一个数加入数组,直到需要的num为0。
排列组合思路

实现代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function Permutations (arr, nums) {
var ret = [];

function getRet(origin, target, nums) {
if (nums === 0) {
ret[ret.length] = origin;
return;
}
for (var i = 0; i <= target.length - nums; i++) {
var tmp = origin.slice();
tmp.push(target[i]);
getRet(tmp, target.slice(i + 1), nums - 1);
}
}
getRet([], arr, nums);
return ret;
}
Permutations([1, 2, 3, 4], 3)

实现效果:
第三题实现效果

4、JS如何判断一组数字是否连续(百词斩笔试题)

1
2
// 当出现连续数字的时候以‘-’输出
[1, 2, 3, 4, 6, 8, 9, 10]

期望结果:

1
["1-4", 6, "8-10"]

原理:

判断前后数字是否相差为1,如果是则加入同一个数组

实现代码:

判断是否连续:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var arrange = function(arr){
var result = [],temp = [];
arr.sort(function(source, dest){
return source - dest;
}).concat(Infinity).reduce(function(source, dest){
temp.push(source);
if(dest-source > 1){
result.push(temp);
temp = [];
}
return dest;
});
return result;
};

实现效果:
判断是否连续实现效果

格式化实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var formatarr = function(arr) {
var newArr = []
var arr1 = arrange(arr)
for (var i in arr1) {
var str = '';
if (arr1[i].length > 1) {
str = arr1[i][0] + '-' + arr1[i][arr1[i].length - 1];
newArr.push(str)
} else {
newArr.push(arr1[i][0]);
}
}
return newArr;
}

实现效果:
第四题实现效果

5、创建子类Child,使用原型和构造函数的方式继承父类People的方法,并调用say函数说出姓名和年龄。(详见我的另一篇文章前端面试问题之面向对象类)

实现代码:

父类:

1
2
3
4
5
6
7
function People(name,age){
this.name=name;
this.age=age;
this.say=function(){
console.log("我的名字是:"+this.name+"我今年"+this.age+"岁!");
};
}

原型继承:(原型链相关问题请看我的另一篇文章前端面试之原型链问题)

1
2
3
4
5
6
7
function Child(name, age){
this.name = name;
this.age = age;
}
Child.prototype = new People();
var child = new Child('Rainy', 20);
child.say()

实现效果:
原型继承

构造函数继承

1
2
3
4
5
6
7
function Child(name, age){
People.call(this)
this.name = name;
this.age = age;
}
var child = new Child('Rainy', 20);
child.say()

实现效果:
构造函数继承

组合继承:

1
2
3
4
5
6
7
8
function Child(name, age){
People.call(this);
this.name = name;
this.age = age;
}
Child.prototype = People.prototype;
var child = new Child('Rainy', 20);
child.say()

实现效果:
组合继承

组合继承优化:

1
2
3
4
5
6
7
8
9
function Child(name, age){
People.call(this);
this.name = name;
this.age = age;
}
Child.prototype = Object.create(People.prototype);
Child.prototype.constructor = Child;
var child = new Child('Rainy', 20);
child.say()

实现效果:
组合继承优化

未完待续

很难接受就要和你分离了
小哥哥,小姐姐们,常来玩啊

本文标题:前端面试之你可能会遇到的编程题(1)

文章作者:小超子

发布时间:2018年08月21日 - 22:08

最后更新:2018年08月21日 - 23:08

原始链接:https://rain120.github.io/2018/08/21/Interview-programming-01/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

0%