链表简介
链表是什么?
- 多个元素组成的列表。
- 元素存储不连续,用next指针连在一起
数组 vs 链表
- 数组:增删非首尾元素时往往需要移动元素
- 链表:增删非首尾元素,不需要移动元素,只需要更改next的指向即可。
JS中的链表
- JavaScript中没有链表
- 可以用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.val;
}
//插入
const e = {val:'e'};
c.next = e;
e.next = d;
//删除
c.next = d;
LeetCode:237.删除链表中的节点
解题思路
- 无法直接获取被删除节点的上个节点。
- 将被删除节点转移到下个节点。 解题步骤
- 将被删节点的值改为下个节点的值。
- 删除下个节点。 代码题解:
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} node
* @return {void} Do not return anything, modify node in-place instead.
*/
var deleteNode = function(node) {
node.val = node.next.val;
node.next = node.next.next;
};
LeetCode206:反转链表
解题思路
- 反转两个节点:将n+1的next指向n
- 反转多个节点:双指针遍历链表,重复上述操作 解题步骤
- 双指针一前一后遍历链表
- 反转双指针 题解coding:
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var reverseList = function(head) {
let p1 = head;
let p2 = null;
while(p1){
let temp = p1.next;
p1.next = p2;
p2 = p1;
p1 = temp;
}
return p2;
};
LeetCode2:两数相加
解题思路
- 小学数学题,模拟相加操作
- 需要遍历链表 解题步骤
- 新建一个空链表
- 遍历被相加的两个链表,模拟相加操作,将个位数追加到新链表上,将十位数留到下一位去相加 题解coding:
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} l1
* @param {ListNode} l2
* @return {ListNode}
*/
var addTwoNumbers = function(l1, l2) {
let l3 = new ListNode(0);
let p1 = l1, p2 = l2, p3 = l3;
let carry = 0;
while(p1 || p2){
const v1 = p1 ? p1.val : 0;
const v2 = p2 ? p2.val : 0;
const val = v1 + v2 + carry;
carry = Math.floor(val/10);
p3.next = new ListNode(val%10);
if(p1) p1 = p1.next;
if(p2) p2 = p2.next;
p3 = p3.next;
}
if(carry){
p3.next = new ListNode(carry);
}
return l3.next;
};
LeetCode83:删除排序链表中的重复元素
解题思路
- 因为链表是有序的,所以重复元素一定相邻
- 遍历链表,如果发现当前元素和下个元素值相同,就删除下个元素值 解题步骤
- 遍历链表,如果发现当前元素和下个元素值相同,就删除下个元素值
- 遍历结束后,返回原链表的头部 题解Coding:
/**
* Definition for singly-linked list.
* function ListNode(val, next) {
* this.val = (val===undefined ? 0 : val)
* this.next = (next===undefined ? null : next)
* }
*/
/**
* @param {ListNode} head
* @return {ListNode}
*/
var deleteDuplicates = function(head) {
let p = head;
while(p && p.next){
if(p.val === p.next.val){
p.next = p.next.next;
}else{
p = p.next;
}
}
return head;
};
Leetcode141:环形链表
解题思路
- 两个人在圆形操场上的起点同时起跑,速度快的人一定会超过速度慢的人一圈
- 用一快一慢两个指针遍历链表,如果指针能够相逢,那么链表就有圈 解题步骤
- 用一快一慢两个指针遍历链表,如果指针能够相逢,就返回true
- 遍历结束后,还没有相逢就返回false 题解coding:
/**
* Definition for singly-linked list.
* function ListNode(val) {
* this.val = val;
* this.next = null;
* }
*/
/**
* @param {ListNode} head
* @return {boolean}
*/
var hasCycle = function(head) {
let p1 = head ,p2 = head;
while(p1 && p2 && p2.next){
p1 = p1.next;
p2 = p2.next.next;
if(p1 === p2){
return true;
}
}
return false;
};