javascript链表

1.什么是链表?

在这里插入图片描述

  • 链表是多个元素组成的列表
  • 元素存储不连续,用next指针连接到一起
  • JS中没有链表,但是可以用Object模拟链表

2.常用操作

  • 新增节点 append
  • 删除节点 remove
  • 插入节点 insert
  • 获取索引 indexOf
  • 链表转字符串 toString
  • 获取链表长度 size
  • 判断链表是否为空 isEmpty

3.定义链表类

class Node {  //节点类
    //构造函数
    constructor(val) { 
        this.val = val;
        this.next = null;
    }
}
class LinkedList {  // 链表类
    //构造函数
    constructor() { 
        this.head = null;
        this.length = 0;
    }
    //新增节点
    append(val) { 
        let node = new Node(val);
        let current; //暂存当前位置
        if(this.head === null) { // 如果头结点为空,当前节点作为头结点
            this.head = node;
        } else { 
            current = this.head;
            while(current.next) {     //遍历找到链表尾部
                current = current.next;
            }
            current.next = node;    //在链表尾部加入新节点
        }
        this.length++; //更新链表长度
    }
    //删除节点,并获得删除节点的值
    removeAt(index) { 
        if(index > -1 && index < this.length) { //预防下标越界
            var current = this.head;//暂存当前位置
            var previous; //暂存当前位置的前一个
            var position = 0;
            if(index === 0) {  //要删除的是第一个位置,就得改变头指针指向
                this.head = current.next;
            } else { 
                while(position++ < index) { //遍历直到current处于index位置
                    previous = current;
                    current = current.next;  //此时current处于index处,previous在index-1处
                }
                previous.next = current.next; //改变链表结构,跳过index处
            }
            this.length--; //更新链表长度
            return current.val; //返回index处的值
        } else { 
            return null;    //下标越界返回空
        }
    }
    //插入节点
    insert(index,val) {
        if(index > -1 && index <= this.length) { 
            let node = new Node(val);
            let current = this.head;
            let previous;
            let position = 0;
            if(index === 0) { 
                node.next = current;
                this.head = node;
            } else { 
                while(position++ < index) { 
                    previous = current;
                    current = current.next;
                }
                node.next = current;
                previous.next = node;
            }
            length++;
            return true; //插入成功
        } else { 
            return false; //插入失败
        }
    }
    //获取索引
    indexOf(val) { 
        let current = this.head;
        let position = 0;
        while(current) { 
            if(current.val === val) { 
                return position;
            }
            position++;
            current = current.next;
        }
        return -1; //未找到索引
    }
    //将链表转换成字符串
    toString() { 
        let current = this.head;
        let string = '';
        while(current) { 
            string += current.val + ((current.next ? ',': ''));
            current = current.next;
        }
        return string;
    }
    //链表长度
    size() { 
        return this.length;
    }
    //判断链表是否为空
    isEmpty() { 
        return this.length === 0;
    }
}

4.LeetCode

接下来使用链表这个数组结构来刷LeetCode有关链表的题目,巩固提升对链表的了解。

题号237.删除链表中的节点(简单)

题目要求:
在这里插入图片描述在这里插入图片描述

解题思路:
题目直接给了当前节点,只需用下一位节点覆盖掉当前节点,就可以删除元素

编写代码

var deleteNode = function(node) {
    node.val = node.next.val;
    node.next = node.next.next;
};

复杂度分析

  • 事件复杂度O(1)
  • 空间复杂度O(1)

题号206.反转链表(简单)

题目要求:
在这里插入图片描述

解题思路:
使用双指针遍历,在遍历链表时,将当前节点的指针改为指向前一个节点,需要存储后一个节点指针,最后返回新的头引用。
在这里插入图片描述

编写代码

var reverseList = function(head) {
    let p1 = head;
    let p2 = null;
    while(p1) { 
        const tmp = p1.next; //保存p1下一个节点
        p1.next = p2; //p1下一个改为p2
        p2 = p1; //p2指向p1当前位置
        p1 = tmp; 
    }
    return p2;
};

复杂度分析:

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

题号2.两数相加(中等)

题目要求:
在这里插入图片描述在这里插入图片描述

解题思路:

  1. 思路: 链表问题,遍历l1,l2,赋值给l3
  2. 边界条件
    * l1 或 l2 哪个先结束,结束的用0替补,不影响相加
    * 相加后是否产生进位
    * 判断最高位是否产生进位,在循环外单独实现

编写代码

var addTwoNumbers = function(l1, l2) {
    let l3 = new ListNode();
    let p1 = l1;    //不要直接操作原链表
    let p2 = l2;
    let p3 = l3;
    let carry = 0; //进位判断
    while(p1 || p2) { 
        const val1 = p1 ? p1.val : 0;
        const val2 = p2 ? p2.val : 0;
        const val = Math.floor((val1 + val2 + carry) % 10);
        carry = Math.floor((val1 + val2 + carry) / 10);
        p3.next = new ListNode(val);
        if(p1) p1 = p1.next;
        if(p2) p2 = p2.next;
        p3 = p3.next;
    }
    if(carry) { //判断最后一位是否有进位
        p3.next = new ListNode(carry);
    }
    return l3.next;
}

复杂度分析:

  • 事件复杂度: O(max(m,n)),m,n分别为两个链表的长度
  • 空间复杂度: O(1),返回值不计入空间复杂度
  • 23
    点赞
  • 75
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值