leetcode 链表篇

leetcode. 142. 环形链表 IIhttps://leetcode.cn/problems/linked-list-cycle-ii/

遍历链表中的每个节点:遍历的时候将每个节点的标签设置为true,顺便判断一下是否遍历过(也就是检查该节点的标签是否为true),为true的话代表遍历过了,那么环就找到了。

时间复杂度:O(n)

空间复杂度:O(1)

    while(head){
        
        if(head.tag === true){
            return head;
        }
        head.tag = true;
        head = head.next;
    }
    return null;

或者可以用哈希表存储这个节点,判断是否has,和上面一样的思路。

快慢指针看明白了,独立写还是写不出来……

面试题 02.07. 链表相交  leetcode 160.链表相交https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/

用哈希表,先遍历链表A,保存在set中(Set的本质是哈希表),再去遍历链表B,遍历的时候判断链表B中的值在set中是否有,有的话就是共同链表的第一个节点。

时间复杂度:O(m+n) m是链表A中的元素个数 n是链表B中的元素个数

空间复杂度:O(m)

  // 注意一下是指针所指相等不是数值相等
    const ans = new Set();
    while(headA){
        ans.add(headA);
        headA = headA.next; 

    }
    while(headB){
        if(ans.has(headB)){
            return headB;
        }
        headB = headB.next;
    }
    return null;

19. 删除链表的倒数第 N 个结点https://leetcode.cn/problems/remove-nth-node-from-end-of-list/

双指针,第一个指针先走n步,之后两个指针一起走,直到第一个指针走到最后一个节点,那么这两个指针之间的元素就是要删除的元素。

时间复杂度:O(n)

空间复杂度:O(1)

 const dummy = new ListNode();
    dummy.next = head;
    let n1=dummy, n2=dummy;
    for(let i = 0;i<n;i++){
        n2=n2.next;
    }
    while(n2.next){
        n1 = n1.next;
        n2 = n2.next;
    }
    n1.next = n1.next.next;
    return dummy.next;

24. 两两交换链表中的节点https://leetcode.cn/problems/swap-nodes-in-pairs/lettcode:面试题 02.07. 链表相交 首先新增一个头节点,将头节点指向第2个节点,第一个节点指向第三个节点,第2个节点指向第一个节点,类似步骤。

时间复杂度:O(n)

空间复杂度:O(1)

   const dummy = new ListNode();
    dummy.next = head;
    let cur = dummy;
    while(cur.next && cur.next.next){
        // 要交换前,先把要用到的备份一下
        let tmp1 = cur.next;
        let tmp2 = cur.next.next;
        
        cur.next = tmp2;
        tmp1.next = tmp2.next;
        tmp2.next = tmp1;

        // 这里不是tmp2;因为tmp1就是cur指向的后面一个数,但是被交换了,所以还是指向它
        cur = tmp1;
    }
    return dummy.next;

206. 反转链表https://leetcode.cn/problems/reverse-linked-list/

把指向从左到右,改成从右到左即可,先设一个null。

时间复杂度:O(n)

空间复杂度:O(1)

​
    let pre = null;
    while(head){
        let tmp = head.next;
        head.next = pre;
        pre = head;
        head = tmp;
    }
    return pre;

​

203. 移除链表元素https://leetcode.cn/problems/remove-linked-list-elements/

最直接的想法没有过……

方法一:添加空节点,从头开始遍历遇到相等的就删除即可。

时间复杂度:O(n)

空间复杂度:O(1)

   const dummy = new ListNode();
    dummy.next = head;
    let cur = dummy;
    while(cur.next){
        if(cur.next.val===val){
            cur.next = cur.next.next;
        }else{
            cur = cur.next;
        }
    }
    return dummy.next;

方法二:递归

时间复杂度:O(n)

空间复杂度:O(n) 递归需要用到栈

确定递归出口,递归的内容(也就是递归什么),每一次递归需要得到什么

  //递归出口
    if(head===null){
        return head;
    }
    //递归内容,这里我们是递归每个链表节点
    head.next = removeElements(head.next, val);
    // 每一次递归得到什么:确定是否需要这个节点 
    return head.val === val ? head.next : head;
 

707. 设计链表https://leetcode.cn/problems/design-linked-list/

如果要你自己写一个链表的定义,也要会写,还有链表的一些操作。

// 定义一个节点
function LinkedList(val, next){
    this.val = (val === undefined ? 0 : val);
    this.next = (next === undefined ? null : next);
};

//初始化一个链表:长度 + 头节点
var MyLinkedList = function(){
    this.size = 0;
    this.head = new LinkedList();
};

MyLinkedList.prototype.get = function(index){
    // 因为是从0开始计数的,等于size也是超界了
    if(index<0 || index>=this.size){
        return -1;
    }
    let cur = this.head;
    for(let i=0;i<=index;i++){
        cur = cur.next;
    }
    return cur.val;
};

MyLinkedList.prototype.addAtIndex = function(index, val){
    if(index>this.size){
        return ;
    }
    //如果是负数的话,取值为0,如果是正数的话,就取本身的值
    index = Math.max(0, index);
    this.size++;
    let cur = this.head;
    for(let i=0;i<index;i++){
        cur = cur.next;
    }
    // 新建一个节点
    let newNode = new LinkedList(val);
    newNode.next = cur.next;
    cur.next = newNode;
};

MyLinkedList.prototype.addAtHead = function(val){
    this.addAtIndex(0, val);
};

MyLinkedList.prototype.addAtTail = function(val){
    this.addAtIndex(this.size, val);
};

MyLinkedList.prototype.deleteAtIndex = function(index, val){
    if(index< 0 || index>=this.size){
        return ;
    }
    this.size--;
    let cur = this.head;
    for(let i=0;i<index;i++){
        cur = cur.next;
    }
    cur.next = cur.next.next;

}

链表专题虽然结束啦~~但是感觉有些不是很熟悉,需要再啃啃。不要急于求成~加油!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值