一、栈
leetcode题目:
//方法一:栈
var isValid = function (s) {
if (s.length % 2 === 1) return false;
const stack = [];
for (var i = 0; i < s.length; i++) {
var c = s[i];
if (c === '(' || c === '[' || c === '{') {
stack.push(c);
} else {
var top = stack[stack.length - 1];
if (
(top === '(' && c === ')') ||
(top === '[' && c === ']') ||
(top === '{' && c === '}')
) {
stack.pop();
}
else {
return false;
}
}
}
return stack.length === 0;
};
二、队列
leetcode题目:
三、链表
js中没有链表,但可以用对象object来模拟链表:
const a = {
val: 'a'
}
const b = {
val: 'b'
}
const c = {
val: 'c'
}
const d = {
val: 'd'
}
a.next = b;
b.next = c;
c.next = d;
// 遍历链表
let p = a;
while (p) {
console.log(p.val);
p = p.next;
}
//插入链表
const e = {
val: 'e'
};
c.next = e;
e.next = d;
// 刪除链表
c.next = d;
- leecode题目:203. 移除链表元素
- leecode题目:24. 两两交换链表中的节点
- leecode题目:19. 删除链表的倒数第 N 个结点
- leecode题目:面试题 02.07. 链表相交
- leecode 题目:142. 环形链表 II
总结:给链表添加一个虚拟头结点
const ret = new ListNode(0, head);
return ret;
leecode题目:
解题思路:
- 无法直接获取被删除节点的上个节点。
- 将被删除的节点转移到下个节点。
解题步骤:
- 将被删除节点的值改为下个节点的值。
- 删除下个节点。
本题时间复杂度和空间复杂度均为:O(1)
leecode题目:206. 反转链表
思路:
- 反转两个节点:将n+1的next指向n.
- 反转多个节点:双指针遍历链表,重复上述操作。
步骤:
- 双指针一前一后遍历链表。
- 反转双指针。
时间复杂度:O(n) 空间复杂度:O(1)
var reverseList = function (head) {
let p1 = null;
let p2 = head;
while (p2) {
let temp = p2.next; //提前保存p2的下一个节点
p2.next = p1; //反转
p1 = p2; //把p2的值给p1,相当于p1往前移动一位
p2 = temp; //把p2.next赋值给p2,相当于p2往前移动一位
}
return p1; //循环结束后,p2指向null,返回p1即可
};
leecode题目:2. 两数相加【较难】
解题步骤:
- 新建一个空链表。
- 遍历相加的两个链表,模拟相加操作,将个位数追加到新链表上,将十位数留到下一位去相加。
时间/空间复杂度:O(max(m,n)),其中 m 和 n 分别为两个链表的长度.
var addTwoNumbers = function (l1, l2) {
const l3 = new ListNode();
let p1 = l1;
let p2 = l2;
let p3 = l3;
let carry = 0;
while (p1 || p2) {
const v1 = p1 ? p1.val : 0;
const v2 = p2 ? p2.val : 0;
const v3 = v1 + v2 + carry;
carry = Math.floor(v3 / 10);
p3.next = new ListNode(v3 % 10);
if (p1) p1 = p1.next;
if (p2) p2 = p2.next;
p3 = p3.next;
}
if (carry) {
p3.next = new ListNode(carry);
}
return l3.next;
};
leecode题目:141. 环形链表
思路:
用一快一慢两个指针遍历链表,如果指针能够相逢,说明链表有环。时间复杂度:O(n)
空间复杂度:O(1)
var hasCycle = function (head) {
let p1 = head;
let p2 = head;
while (p1 && p2 && p2.next) {
p1 = p1.next;
p2 = p2.next.next;
if(p1===p2){
return true;
}
}
return false;
};
leecode 题目:21. 合并两个有序链表
思路:双指针
- 新建一个链表,作为返回的结果。
- 用指针遍历两个有序链表,并比较两个链表的当前节点,较小者先接入新链表,并将指针后移一步。
- 时间复杂度:O(n+m),其中 n 和 m 分别为两个链表的长度。
- 空间复杂度:O(1)
var mergeTwoLists = function (l1, l2) {
let res = new ListNode(0);
let p = res;
let p1 = l1;
let p2 = l2;
while (p1 && p2) {
if (p1.val < p2.val) {
p.next = p1;
p1 = p1.next;
} else {
p.next = p2;
p2 = p2.next;
}
p = p.next;
}
if (p1) {
p.next = p1;
}
if (p2) {
p.next = p2;
}
return res.next;
};
四、集合
-
一种无序且唯一的数据结构。
-
ES6中有集合,名为set。
-
集合的常用操作:去重、判断某元素是否在集合中、求交集…
// 查看集合
const arr = [1, 1, 2, 2, 2];
const set = new Set(arr)//Set(2) {1, 2}
//查看集合的长度
console.log(set.size);//2// 去重
const arr = [1, 1, 2, 2, 2];
const arr2 = […new Set(arr)];
console.log(arr2); //[ 1, 2 ]// 判断元素是否在集合中
const set = new Set(arr);
const has = set.has(3);
console.log(has); //false//求交集
const set2 = new Set([2, 3]);
const set3 = new Set([…set].filter(item => set2.has(item)));
console.log(set3); //{ 2 }
ES6中的set:
let mySet = new Set();
mySet.add(1);
mySet.add(5);
mySet.add(5);
mySet.add('some text');
let o = { a: 1, b: 2 };
mySet.add(o);
mySet.add({ a: 1, b: 2 });
const has = mySet.has(o);
mySet.delete(5);
for(let [key, value] of mySet.entries()) console.log(key, value);
const myArr = Array.from(mySet);
const mySet2 = new Set([1,2,3,4]);
const intersection = new Set([...mySet].filter(x => mySet2.has(x)));
const difference = new Set([...mySet].filter(x => !mySet2.has(x)));
leecode题目:
var intersection = function (nums1, nums2) {
nums1 = new Set(nums1);
nums2 = new Set(nums2);
let res = [...nums1].filter(item=>nums2.has(item));
return res;
};
//时间复杂度:O(m*n)
//空间复杂度:O(m), m为去重后的数组长度
五、字典
-
与集合类似,字典也是一种存储唯一值的数据结构,但它是以键值对的形式来存储的。
-
ES6中有字典,名为Map。
-
字典的常用操作:键值对的增删改查。
const m = new Map();
// 增
m.set(‘a’, ‘aa’);
m.set(‘b’, ‘bb’);//查看字典m:
//Map(2) {“a” => “aa”, “b” => “bb”}
//字典的长度
console.log(m.size);//2// 删
m.delete(‘b’);
// m.clear();// 改
m.set(‘a’, ‘aaa’);//查
m.get(‘a’); //‘aaa’//判断a是否存在字典中
m.has(‘a’); //true
leecode题目:
var intersection = function (nums1, nums2) {
let map = new Map(),
arr = [];
nums1.forEach(n => {
map.set(n, true);
});
nums2.forEach(n => {
if (map.get(n)) {
map.delete(n);
arr.push(n);
};
});
return arr;
};
//时间复杂度:O(m+n)
//空间复杂度:O(m)
leecode题目&#x