【跟着labuladong刷力扣】力扣刷题-----数据结构之链表

前言

刷题学框架,刷题学思想.跟着labuladong刷链表。
labuladong链接:labuladong代码小抄
刷题插件链接(来源labuladong公众号):
链接:https://pan.baidu.com/s/1glrZjyFCG4bXual3gzTvvw
提取码:un2k



一、双指针技巧秒杀七道链表题目

1.力扣21题:合并两个有序链表(简单)

比较两个链表当前值的大小,选择小的,连接到p的后面。当有一个链表空了的时候,就把另一个链表都连接到p后面。

var mergeTwoLists = function(list1, list2) {
    var margin = new ListNode()
    var p = margin
    while(list1!=null && list2!=null){
        if(list1.val < list2.val){
            p.next = list1
            list1 = list1.next
        }
        else{
            p.next = list2
            list2 = list2.next
        }
        p = p.next
    }
    if(list1 == null){
        p.next = list2
    }
    else{
        p.next = list1
    }
    return margin.next
};

2.力扣23题:合并K个升序链表(困难)

在这里插入图片描述
labuladong中给出的Java代码用的是优先队列,JS中没有这种结构(也可能是我不知道),因此我使用的是先排序,再构造的方法,代码很好理解,如下:

var mergeKLists = function(lists) {
    var margin = new ListNode()
    var p = margin
    var arr = []
    for(list of lists){
        while(list != null){
            arr.push(list.val)
            list = list.next
        }
    }
    arr.sort(function(a,b){return a-b})
    for(a of arr){
        var newa =  new ListNode(a)
        p.next = newa
        p = p.next
    }
    return margin.next
};

3.力扣19题:删除链表的倒数第 N 个结点(中等)

在这里插入图片描述
利用的双指针中的快慢指针,其中快指针先走n个结点,然后再快慢指针一起走,当快指针走到最后一个的时候,慢指针正好走到要删除结点的前一个结点,只需要对当前的结点的next=next.next即可,对于n等于链表的长度这种情况,可以直接删除第一个结点,即取head.next即可。

var removeNthFromEnd = function(head, n) {
    var rNode = head
    var lNode = head
    for(var i=0;i<n;i++){
        rNode = rNode.next
    }
    if(!rNode){      //处理n等于链表长度的情况
        return head.next
    }
    while(rNode.next != null){
        lNode = lNode.next
        rNode = rNode.next
    }
    lNode.next = lNode.next.next
    return head
};

4.力扣876题:链表的中间结点(简单)

在这里插入图片描述
使用双指针的话,可以直接让快指针每次走两个,慢指针每次走一个,这样的话当快指针走到最后一个的时候,慢指针正好在中间。(最好还是自己画图确认,因为有中间有两个数的情况)

var middleNode = function(head) {
    var fast = new ListNode()
    var slow = new ListNode()
    fast = head,slow = head
    while(fast != null && fast.next != null ){
        fast = fast.next.next
        slow = slow.next
    }
    return slow
};

5. 力扣141和142题:环形链表(中等)

在这里插入图片描述
在这里插入图片描述

  1. 判断链表中是否有环:设置快指针每次走2个,慢指针每次走1个,如果有一瞬间快指针==慢指针,证明有环,如果有一瞬间快指针为空了,那么就没有环。
var hasCycle = function(head) {
    var fast = new ListNode()
    var slow = new ListNode()
    fast = head,slow = head
    while(fast != null && fast.next != null){
        fast = fast.next.next
        slow = slow.next
        if(slow == fast) return true
    }
    return false
};
  1. 找出链表中环的起点:当快指针==慢指针的瞬间,令慢指针回到头结点,快慢指针相同步调走,再次相遇的时候,就是环的起点。
var detectCycle = function(head) {
    var fast = new ListNode()
    var slow = new ListNode()
    fast = head,slow = head
    while(fast != null && fast.next != null){
        fast = fast.next.next
        slow = slow.next
        if(slow == fast){
            slow = head
            while(slow != fast){
                slow = slow.next
                fast = fast.next
            }
            return fast
        }
    }
    return null
};

6.力扣160题:相交链表(简单)

在这里插入图片描述
可以让两个指针都走一遍两个链表,就是当A到头的时候,指针指到B上,当B走到头的时候,指针指到A上,这样两个指针可以同时到达相交点,如果没有相交点,两个指针也能同时到null,返回即可。

var getIntersectionNode = function(headA, headB) {
    var nodeA = new ListNode()
    var nodeB = new ListNode()
    nodeA = headA,nodeB = headB
    while(nodeA != nodeB){
        if(nodeA == null){
            nodeA = headB
        }else{
            nodeA = nodeA.next
        }
        if(nodeB == null){
            nodeB = headA
        }else{
            nodeB = nodeB.next
        }
    }
    return nodeA
};

二、递归反转链表的一部分

1.力扣206题:反转链表(简单)

在这里插入图片描述
先给出代码,再给出解释

var reverseList = function(head) {
    if(head == null || head.next == null){
        return head
    }
    var last = new ListNode()
    last = reverseList(head.next)
    head.next.next =  head
    head.next = null
    return last
};

给出reverseList的定义,就是反转以head为头结点的链表。
在这里插入图片描述

2.力扣92题:反转链表Ⅱ(中等)

在这里插入图片描述
这里涉及到反转前N个结点和反转区间结点的知识,我觉得我解释的没有labuladong解释的好,最好直接看原文吧,下面给出js的实现代码。

var reverseBetween = function(head, left, right) {
    successor = new ListNode()
    if(left == 1){
        return reverseN(head,right)
    }
    head.next = reverseBetween(head.next,left-1,right-1)
    return head
};

var reverseN = function(head,n){
    if(n == 1){
        successor = head.next
        return head
    }
    var last = new ListNode()
    last = reverseN(head.next,n-1)
    head.next.next = head
    head.next = successor
    return last
}

三、如何K个一组反转链表

1.力扣25题:K 个一组翻转链表(困难)

在这里插入图片描述

  1. 反转链表的常规做法,即不使用递归的话,反转过程是这样的
var reverse = function(head,b){
    var pre = new ListNode()
    var cur = new ListNode()
    var nxt = new ListNode()
    pre = null
    cur = head
    nxt = head
    while(cur != b){
        nxt = cur.next
        cur.next = pre
        pre = cur
        cur = nxt
    }
    return pre
}
  1. 接下来就使用迭代的方式,K个K个的翻转链表
var reverseKGroup = function(head, k) {
    if(head == null){
        return null
    }
    var a = new ListNode()
    var b = new ListNode()
    a = head
    b = head
    for(var i=0;i<k;i++){
        if(b == null){
            return head
        }
        b = b.next
    }
    var newHead = new ListNode()
    newHead = reverse(a,b)
    a.next = reverseKGroup(b,k)
    return newHead
};

四、如何判断回文链表

1.力扣234题:回文链表

在这里插入图片描述
最直接的方案就是把链表反转,然后逐个比较;但这里我们使用双指针的方法,先找到链表终点,再把后半部分反转,与前半部分比较。

var isPalindrome = function(head) {
    var slow = new ListNode()
    var fast = new ListNode()
    slow = head
    fast = head
    while(fast != null && fast.next!=null){
        slow = slow.next
        fast = fast.next.next
    }
    if(fast != null){
        slow = slow.next
    }
    var left = new ListNode()
    var right = new ListNode()
    left = head
    right = reverse(slow)
    while(right != null){
        if(left.val != right.val){
            return false   
        }
        left = left.next
        right = right.next
    }
    return true
};

var reverse = function(head){
    var pre = new ListNode()
    var cen = new ListNode()
    pre = null
    cen = head
    while(cen != null){
        var nxt = new ListNode()
        nxt = cen.next
        cen.next = pre
        pre = cen
        cen = nxt
    }
    return pre
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值