这个系列没啥花头,就是纯 leetcode 题目拆解分析,不求用骚气的一行或者小众取巧解法,而是用清晰的代码和足够简单的思路帮你理清题意。让你在面试中再也不怕算法笔试。
65. 分隔链表 (partition-list)
标签
- 链表
- 中等
题目
这里不贴题了,leetcode打开就行,题目大意:
给你一个链表的头节点 head 和一个特定值 x ,请你对链表进行分隔,使得所有 小于 x 的节点都出现在 大于或等于 x 的节点之前。
你应当 保留 两个分区中每个节点的初始相对位置。
输入:head = [1,4,3,2,5,2], x = 3
输出:[1,2,2,4,3,5]
基本思路
- 新构造 2 个链表,一个链表专门存储比 x 小的结点,另一个专门存储比 x 大的结点。
- 在原链表头部开始扫描一遍,依次把这两类点归类到 2 个新建链表中。
- 由于是从头开始扫描的原链表,所以原链表中的原有顺序会依旧被保存下来。
- 最后 2 个新链表里面会存储好各自的结果,把这两个链表,比 x 小的链表拼接到 比 x 大的链表的前面,就能得到最后的答案了。
基本步骤
- 建立两个链表,big && small
- 建立两个列表的虚拟头结点,处理空的边界条件
- 开始遍历,分类大小
- 大小数组拼接,尾部置空,返回小数组头结点。
写法实现
var partition = function(head, x) {
// 建立两个链表,分别为大于 x 的和小于 x 的链表
let [small, big] = [new ListNode(0), new ListNode(0)]
// 建立两个链表的虚拟头结点,处理头节点为空的边界条件更方便
let [smallPreHead, bigPreHead] = [small, big]
// 开始区分,形成 small , big 链表
while (head !== null) {
if (head.val < x) {
small.next = head;
small = small.next;
} else {
big.next = head;
big = big.next;
}
head = head.next;
}
// big 数组尾部置空
big.next = null;
// 数组链接
small.next = bigPreHead.next;
return smallPreHead.next;
}
66. 合并两个有序数组 (merge-sorted-array)
标签
- 数组
- 简单
题目
这里不贴题了,leetcode打开就行,题目大意:
给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
初始化 nums1 和 nums2 的元素数量分别为 m 和 n 。你可以假设 nums1 的空间大小等于 m + n,这样它就有足够的空间保存来自 nums2 的元素。
示例:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
相关知识
Array.prototype.splice()
splice() 方法通过删除或替换现有元素或者原地添加新的元素来修改数组,并以数组形式返回被修改的内容。此方法会改变原数组。
// 删除 0 个 并在 index === 1 的位置添加 'Feb'
const months = ['Jan', 'March', 'April', 'June'];
months.splice(1, 0, 'Feb');
// inserts at index 1
console.log(months);
// expected output: Array ["Jan", "Feb", "March", "April", "June"]
// 在 index === 4 的位置 删除 1 个元素("June") 并添加 'May'
months.splice(4, 1, 'May');
// replaces 1 element at index 4
console.log(months);
// expected output: Array ["Jan", "Feb", "March", "April", "May"]
语法
array.splice(start[, deleteCount[, item1[, item2[, ...]]]])
参数
-
start- 指定修改的开始位置(从0计数)。
- 如果超出了数组的长度,则从数组末尾开始添加内容;
- 如果是负值,则表示从数组末位开始的第几位(从-1计数,这意味着-n是倒数第n个元素并且等价于array.length-n);
- 如果负数的绝对值大于数组的长度,则表示开始位置为第0位。
-
deleteCount 可选- 整数,表示
要移除的数组元素的个数。 - 如果 deleteCount 大于 start 之后的元素的总数,则从 start 后面的元素都将被删除(含第 start 位)。
- 如果 deleteCount 被省略了,或者它的值大于等于array.length - start(也就是说,如果它大于或者等于start之后的所有元素的数量),那么start之后数组的所有元素都会被删除。
- 如果 deleteCount 是 0 或者负数,则不移除元素。这种情况下,至少应添加一个新元素。
- 整数,表示
-
item1, item2, ... 可选- 要添加进数组的元素
- 从
start位置开始。如果不指定,则 splice() 将只删除数组元素。
返回值
- 由
被删除的元素组成的一个数组。 - 如果只删除了一个元素,则返回只包含一个元素的数组。如果没有删除元素,则返回空数组。
注意 如果添加进数组的元素个数不等于被删除的元素个数,数组的长度会发生相应的改变。
Array.prototype.sort()
sort() 方法用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的UTF-16代码单元值序列时构建的。
const months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);
// expected output: Array ["Dec", "Feb", "Jan", "March"]
// 注意 1 ,100000 的顺序,并不是我们想的那样
const array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1);
// expected output: Array [1, 100000, 21, 30, 4]
语法
arr.sort([compareFunction])
参数
compareFunction 可选- 用来指定按某种顺序进行排列的
函数。 - 如果省略,元素按照转换为的字符串的各个字符的Unicode位点进行排序。
- 用来指定按某种顺序进行排列的
返回值
排序后的数组。 请注意,数组已原地排序,并且不进行复制。
注意
-
如果没有指明
compareFunction,那么元素会按照转换为的字符串的诸个字符的Unicode位点进行排序。- 例如 "Banana" 会被排列到 "cherry" 之前。
- 当数字按由小到大排序时,9 出现在 80 之前,但因为(没有指明 compareFunction),比较的数字会先被转换为字符串,所以在Unicode顺序上 "80" 要比 "9" 要靠前。
-
如果指明了 compareFunction ,那么数组会按照调用该函数的返回值排序。即 a 和 b 是两个将要被比较的元素:
- 如果 compareFunction(a, b) 小于 0 ,那么 a 会被排列到 b 之前;
- 如果 compareFunction(a, b) 等于 0 , a 和 b 的相对位置不变。备注: ECMAScript 标准并不保证这一行为,而且也不是所有浏览器都会遵守(例如 Mozilla 在 2003 年之前的版本);
- 如果 compareFunction(a, b) 大于 0 , b 会被排列到 a 之前。
- compareFunction(a, b) 必须总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的。 所以,比较函数格式如下:
function compare(a, b) {
if (a < b ) { // 按某种排序标准进行比较, a 小于 b
return -1;
}
if (a > b ) {
return 1;
}
// a must be equal to b
return 0;
}
要比较数字而非字符串,比较函数可以简单的以 a 减 b,如下的函数将会将数组升序排列
function compareNumbers(a, b) {
return a - b;
}
sort 方法可以使用 函数表达式 方便地书写:
var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
return a - b;
});
console.log(numbers);
也可以写成:
var numbers = [4, 2, 5, 1, 3];
numbers.sort((a, b) => a - b);
console.log(numbers);
// [1, 2, 3, 4, 5]
对象可以按照某个属性排序:
var items = [
{ name: 'Edward', value: 21 },
{ name: 'Sharpe', value: 37 },
{ name: 'And', value: 45 },
{ name: 'The', value: -12 },
{ name: 'Magnetic' },
{ name: 'Zeros', value: 37 }
];
// sort by value
items.sort(function (a, b) {
return (a.value - b.value)
});
// sort by name
items.sort(function(a, b) {
var nameA = a.name.toUpperCase(); // ignore upper and lowercase
var nameB = b.name.toUpperCase(); // ignore upper and lowercase
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
});
由此我们可以各种组合使用排序。
基本思路
- 改写数组nums1,相当于合并
- 然后排序就行
写法实现
// 注意它是原地修改 nums1
var merge = function(nums1, m, nums2, n) {
nums1.splice(m, nums1.length - m, ...nums2);
nums1.sort((a, b) => a - b);
};
当然本题也可以用双指针,但我们这种简单题不浪费时间,过!
另外向大家着重推荐下这位大哥的文章,非常深入浅出,对前端进阶的同学非常有作用,墙裂推荐!!!核心概念和算法拆解系列
今天就到这儿,想跟我一起刷题的小伙伴可以加我微信哦
搜索我的微信号infinity_9368,可以聊天说地
加我暗号 "天王盖地虎" 下一句的英文,验证消息请发给我
presious tower shock the rever monster,我看到就通过,暗号对不上不加哈,加了之后我会尽我所能帮你,但是注意提问方式,建议先看这篇文章:提问的智慧