刷算法Leetcode---2(链表篇)

前言

        本文是第二篇跟Leetcode算法相关的文章,题目顺序是根据代码随想录刷的 代码随想录

        其他文章链接:刷算法Leetcode文章汇总 

链表篇

203.移除链表元素

        ①设置空头节点,从头遍历链表

        ②不设置空头结点,先对头节点判空,再看next

707.设计链表

自己设计ListNode类

记得设置字段size,链表长度,用于判断index是否越界,注意add时size++,delete时size--

        ①单向链表,不使用空头结点,每次要判断head是否为null或者size是否为0

        ②单向链表,使用空头节点,直接在空头节点后操作即可

        ③双向链表,头尾节点不空,条件判断复杂,没成功实现

        ④双向链表,头尾节点为空节点,初始化时将头尾节点链接,add时改变指向用一行代码即可,如

temp.pre.next = temp.pre = new Node(val,temp.pre,temp);

206.反转链表

        ①迭代,三指针,前两个指针用于改向,最后一个用于保留后边的链表

        ②递归,创建成员变量记录最深递归的节点为新头节点,每次return head,即新链表的尾节点,逐步回溯将指针改向

class Solution {
    ListNode newHead;
    public ListNode reverseList(ListNode head) {
        reverse(head);
        return newHead;
    }
    public ListNode reverse(ListNode node){
        if(node == null || node.next == null){
            newHead = node;
            return node;
        }
        reverse(node.next).next = node;
        node.next = null;
        return node;
    }
}

        ③递归,每次return newHead,即新链表的头节点,获得头之后,再将当前head.next的指针改向

public ListNode reverseList(ListNode head) {
    if(head == null || head.next == null) return head;
    ListNode newHead = reverseList(head.next);
    head.next.next = head;
    head.next = null;
    return newHead;
}

24.两两交换链表中的节点

        ①迭代,使用空头节点记录新头。三指针,第一个记录已完成链表的末尾,后两个分别为待交换链表的前两个。注意改向顺序,先将第一个指向第三个,再将第二个指向第三个的next,再将第三个指向第二个,最后更新第一个指针

        ②递归,类似于反转整个链表,先保存新头节点newHead,再更新head.next,将head.next.next用于递归,再更新newHead.next

public ListNode swapPairs(ListNode head) {
    if(head == null || head.next == null) return head;
    ListNode newHead = head.next;
    head.next = swapPairs(head.next.next);
    newHead.next = head;
    return newHead;
}

19.删除链表的倒数第n个节点

        ①第一遍记录长度,第二遍找到要删除的位置

        ②快慢指针,快指针先走n+1步(根据快慢指针的具体设计改变)

        ③栈,先将节点全入栈,再将栈顶k个出栈,修改倒数k+1个节点的指向

面试题02.07链表相交

        ①快慢指针,记录两个链表的长度,快指针先走长度差的步数

        ②Set,先将headA中节点加入集合,再找headB中第一个与Set中相同的节点

        ③双指针,利用相交链表的特征,第二次遍历都从另一个头节点开始,长度:a+b = b+a,利用三目运算符简化代码

while(tempA != tempB){
    tempA = tempA == null ? headB : tempA.next;
    tempB = tempB == null ? headA : tempB.next;
}

142.环形链表Ⅱ

        ①Set,从头结点开始放入Set中,第一个重复的就是入口节点

        ②快慢指针,慢指针走一步快指针走两步,最终在环内某一点相交,然后分别从相交节点和头节点开始往后,下一次相交的位置就是入口节点,理论推导:

        头节点到环入口a,环入口到相遇点b,相遇点回到环入口c,假设快指针一共走了环n圈

        慢指针a+b,快指针a+n(b+c)+b,即2(a+b)=a+n(b+c)+b,得a=(n-1)b+nc=c+(n-1)(b+c),即头节点到环入口a等于相遇点到环入口c加上n-1圈长,因此分别从头节点和相遇点开始移动一定会在入口点相遇

public class Solution {
    public ListNode detectCycle(ListNode head) {
        if(head == null || head.next == null)return null;
        ListNode temp1 = head.next, temp2 = head.next.next;
        while(temp1 != null && temp2 != null && temp2.next != null){
            if(temp1 == temp2)break;
            temp1 = temp1.next;
            temp2 = temp2.next.next;
        }
        temp2 = head;
        while(temp1 != null){
            if(temp1 == temp2)return temp1;
            temp1 = temp1.next;
            temp2 = temp2.next;
        }
        return null;
    }
}

链表总结

        1、链表的操作要注意边界条件,注意每个题head、next或者next.next为空的情况

        2、通常使用空头节点会大大便利链表头节点为空的情况

        3、遇到前后个数、相交链表、环形链表等,用快慢指针会很方便

        4、对于倒数问题,可以利用栈先进先出的特性解决

        5、对于重复性问题,如相交链表和环形链表,可以使用Set进行判断

  • 48
    点赞
  • 49
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值