lisa的个人博客

慢慢理解世界,慢慢更新自己

0%

编程题(二)

平时喜欢做一些编程题,来扩展思维,把我平时练习中遇到的比较经典的题目以及我的解题思路放上来,大家可以一起学习交流,就当做是我的一个学习笔记吧!题目数量较多我会分批记录到我的博客上面来,文笔粗糙,只记录干货,这是编程题第二期分享.

绝对值最小

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
var a = [-98, -22, -8, -3, 5, 9, 33];

function findMinAbsOfArr(arr) {
let newArr = [];
for (let i = 0; i < a.length; i++) {
newArr.push(Math.abs(a[i]));
};
let num = Math.min(...newArr);
let index;
for (let i = 0; i < a.length; i++) {
if (Math.abs(a[i]) == num) {
index = a.indexOf(a[i]);
}
};
return a[index];
}
console.log(findMinAbsOfArr(a));

获取两个日期之间的有效日期

求两个日期中间的有效日期,如2015-2-8到2015-3-3

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function rangeDays(day1, day2) {
const time1 = new Date(day1).getTime(); // 获取给定日期的毫秒数
const time2 = new Date(day2).getTime();

const range = time2 - time1; // 计算两个日期之间间隔毫秒数
const dayTimes = 24 * 60 * 60 * 1000; // 获取一天的毫秒数
const result = []
let total = 0;
while (total <= range && range > 0) {
result.push(new Date(time1 + total).toLocaleDateString().replace(/\//g, '-'));
total += dayTimes;
};
return result;
}
rangeDays("2015,2,8", "2015,3,3");

这里有一个new Date().toLocalDateString()方法,返回返回该日期对象日期部分的字符串.
我还发现new Date(2015, 2, 8).getTime() 和new Date(‘2015, 2, 8’).getTime() 这两种写法返回的毫秒数不一样,经过试验,只有字符串日期返回的日期才是标准日期,大家可以试一下。

下面是对于js获取时间new Date()的相关介绍

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
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
// 获取指定月份天数,new一个日期对象时候传入(年份,月份,0)获取几号就可以了!
let days = new Date(2020, 2, 0).getDate(); // 29

let myDate = new Date();
myDate.getYear(); //获取当前年份(2位)
myDate.getFullYear(); //获取完整的年份(4位,1970-????)
myDate.getMonth(); //获取当前月份(0-11,0代表1月) // 所以获取当前月份是myDate.getMonth()+1;
myDate.getDate(); //获取当前日(1-31)
myDate.getDay(); //获取当前星期X(0-6,0代表星期天)
myDate.getTime(); //获取当前时间(从1970.1.1开始的毫秒数)
myDate.getHours(); //获取当前小时数(0-23)
myDate.getMinutes(); //获取当前分钟数(0-59)
myDate.getSeconds(); //获取当前秒数(0-59)
myDate.getMilliseconds(); //获取当前毫秒数(0-999)
myDate.toLocaleDateString(); //获取当前日期 "2020/6/12"
let mytime = myDate.toLocaleTimeString(); //获取当前时间 "上午1:17:20"
myDate.toLocaleString(); //获取日期与时间 "2020/6/12 上午1:17:45"

JS获取当前时间戳
let date = new Date().getTime();

将字符串形式的日期转换成日期对象
var strTime = "2011-04-16"; //字符串日期格式
var date = new Date(Date.parse(strTime.replace(/-/g, "/"))); // Date.parse(dateString) 隐式调用 new Date(dateString).getTime();

new Date() 参数说明:
new Date(); //参数可以为整数; 也可以为字符串; 但格式必须正确

new Date(2009, 1, 1); //正确

new Date("2009/1/1"); //正确

new Date("2009-1-1"); //错误

new Date(year, month, date, hrs, min, sec) //按给定的参数创建一日期对象

日期对象比较两个日期
var myDate = new Date();
myDate.setFullYear(2020, 6, 6);
var today = new Date();
if (myDate > today) {
// do something
};

字符串数组排序

题目描述:
在一个字符串中有红、黄、蓝三种颜色的球,且个数不相等,顺序不一致,请为该数组排序。使得排序后数组中球的顺序为:黄、红、蓝。
例如:红蓝蓝黄红黄蓝红红黄红,排序后为:黄黄黄红红红红红蓝蓝蓝。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
方法一:
let arr = ["红", "蓝", "蓝", "黄", "红", "黄", "蓝", "蓝", "蓝"];
const res = [];
const yellow = [],
red = [],
blue = [];
for (let i = 0; i < arr.length; i++) {
if (arr[i] === "黄") {
yellow.push(arr[i])
} else if (arr[i] === "红") {
red.push(arr[i])
} else {
blue.push(arr[i]);
}
};
res.push(...yellow, ...red, ...blue);
console.log(res);
1
2
3
4
5
6
7
8
9
方法二:
let arr = ["红", "蓝", "蓝", "黄", "红", "黄", "蓝", "蓝", "蓝"];
let obj = {
"黄": 0,
"红": 1,
"蓝": 2
};
arr.sort((a, b) => obj[a] - obj[b]);
console.log(arr);

方法一是我写的,方法二是看了别人的解题思路,果然是高级,其实一开始我也想通过hash对象映射,通过数字大小进行排序,但是没有深入去想,直接写了一个,性能上面肯定不如方法二,大家可以自己试着做一下。

求多个数组之间的交集

例子:let a = [1, 2, 3]; let b = [3, 4, 5]; 交集 = [3];

1
2
3
4
5
方法一:
let a = new Set([1, 2, 33]); // 先去重
let b = new Set([2, 23, 4]);
let res = [...a].filter(item => b.has(item));
console.log(res)

方法二:

1
2
3
4
5
6
7
8
9
10
let a = [1, 2, 3];
let b = [2, 3, 4];
let c = [3, 4, 5];
const handle = (...arr) => {
return arr.reduce((acc, cur) => {
return acc.filter(item => cur.includes(item));
})
};
// console.log(handle(a, b, c))
handle(a, b, c);

数字分割

题目描述:
将 ‘1000000000’形式的字符串,以每3位进行分割展示 ‘1000.000.000’, 多种实现方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1000000000..toLocaleString(); // 1000,000,000
1000000000..toLocaleString('de-DE'); // 1000.000.000 德国通过 .分割金钱

1000000000..toLocaleString().replace('/,/g', '.'); // 1000.000.000

// 下面这种实现方式有些繁琐,不推荐,思路放上来供大家参考
const _splitNumber = (num) => {
let nums = num.toString();
let len = ~~(nums.length / 3);
let res = '';
for (let i = 0; i < len; i++) {
res = '.' + nums.slice(-3) + res;
nums = nums.slice(0, nums.length - 3);
};
if (nums) {
res = nums + res;
};
return res;
};
var newNum = _splitNumber(1000000000);
console.log(newNum); // 1000.000.000

实现对象深拷贝

浅拷贝:也就是拷贝A对象里面的数据,但是不拷贝A对象里面的子对象。

深拷贝:会克隆出一个对象,数据相同,但是引用地址不同(就是拷贝A对象里面的数据,而且拷贝它里面的子对象)。

做这道题首先要明白什么是深拷贝,什么是浅拷贝,实现深拷贝和浅拷贝都有哪些方法,若自己手动实现一个深拷贝,不假思索直接写就是下面这样:

代码示例(错误示范):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
function deepcopy(obj) {
const res = {};
if (typeof obj === 'object') {
for (let key in obj) {
res[key] = obj[key]
}
} else {
res = obj;
};
return res;
};

let obj = {
a: 1,
b: 2,
c: {
d: 1
}
};
const newobj = deepcopy(obj);
newobj.a = 2;
console.log(obj, newobj); // obj {a:1,b:2,c:{d:1}} newobj {a:2,b:2,c:{d:1}};

看起来貌似实现了,然而并没有,试着改一下d的值看一下,是不是发现跟你预想的不太一样,其中一个d的值改动影响了另一个对象中的d, 这并不是咱们想要的结果,深拷贝只实现了一层,相当于Object.assign({}, obj)这种方法拷贝的对象,只会拷贝一层,这个地方需要注意哦,那我们看一下如何手写实现真正的深拷贝。

代码实现 (正确示范):

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 deepcopy(obj) {
let res = {};
// 判断参数类型是否为对象类型
if (typeof obj !== 'object') {
res = obj;
} else {
// 通过递归实现
for (let key in obj) {
res[key] = typeof obj[key] === 'object' ? deepcopy(obj[key]) : obj[key];
}
};
return res;
};

let obj = {
a: 1,
b: 2,
c: {
d: 3
}
};
const newobj = deepcopy(obj);
newobj.c.d = 4;
console.log(newobj);

实现深拷贝应该还有很多好的方式,大家可以自己写一下,换一种思路试试看!