算法训练Day4_链表基础 | LeetCode: 24_两两交换链表中的节点 + 19_删除链表的倒数第N个节点 + 面试题 02.07. 链表相交+ 142_环形链表II

LeetCode:24_两两交换链表中的节点

问题描述

解决方案:

1.思路

  • 最先想到的是递归实现
  • 递归的返回值和参数分别是:新链表的头节点和原始链表的头结点;
  • 递归的终止条件是:链表中没有节点 ( h e a d = = n u l l 而且 h e a d . n e x t = = n u l l ) (head == null 而且head.next == null) head==null而且head.next==null或者链表中只有一个节点 ( h e a d = = n u l l ) (head == null) head==null;
  • 递归的逻辑是:假如链表有6个节点,那么题目中的函数swapPairs(ListNode head)的含义就是按照题目要求两两交换该链表中的节点;所以直接:head指向紫色范围的子链表【swapPairs(newHead.next)】;newHead.next=head; 返回newHead;
  • 在这里插入图片描述

2.代码实现

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

3.复杂度分析

在这里插入图片描述

4.注意

  • 递归的逻辑最好去画画图;

LeetCode: 19_删除链表的倒数第N个节点

解决方案:

1.思路:

  • 首先遍历一遍链表,然后计算倒数第n个节点的索引值,进行正常删除,但是时间复杂度就为 O ( n ) O(n) O(n
  • 也可以通过栈实现,将链表元素全部入栈,在弹出栈的过程中,弹出的第n个元素就是要删除的节点,那么栈顶的元素就是待删除链表元素的前驱节点。
  • 双指针,设置两个快慢指针,快指针比慢指针提前n个节点,那么当快指针遍历到链表结尾的时候,慢指针指的就是倒数第N个节点

2.代码实现

class Solution {
    public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummyHead = new ListNode(0, head);
        ListNode slow = dummyHead;
        ListNode fast = head;
        for (int i = 0; i < n; i++) {
            fast = fast.next;
        }
        while (fast != null) {
            fast = fast.next;
            slow = slow.next;
        }
        slow.next= slow.next.next;
        ListNode ans =dummyHead.next;
        return ans;
    }
}

3.复杂度分析

在这里插入图片描述

4.注意事项

  • 考虑到我们删除某一个链表节点,需要首先找到它的前驱结点,所以,我们可以设置一个哑结点作为头结点,让慢指针从哑结点开始遍历,其余规则不变,那么当快指针遍历到链表结尾的时候,慢指针指的就是倒数第N个节点的前驱节点,直接进行删除就好。

LeetCode: 面试题 02.07. 链表相交

解决方案:

1.思路:使用双指针

-在这里插入图片描述

  • 参考:https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/solutions/1/mian-shi-ti-0207-lian-biao-xiang-jiao-sh-b8hn/

2.代码实现

public class Solution {
    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (headA == null || headB == null) {
            return null;
        }
        ListNode pA = headA, pB = headB;
        while (pA != pB) {
            pA = pA == null ? headB : pA.next;
            pB = pB == null ? headA : pB.next;
        }
        return pA;
    }
}

3.复杂度分析

在这里插入图片描述

4.注意事项

  • 注意三元条件运算符大大精简了代码量;
  • 其基本语法为:条件 ? 表达式1 : 表达式2。如果条件为真(true),则计算并返回表达式1的值;如果条件为假(false),则计算并返回表达式2的值。
  • 在这里插入图片描述在这里插入图片描述
  • LeetCode: 142_环形链表II

  • 解决方案:

1.思路:

方法一:哈希表

  • 遍历链表中的每个节点,并将它记录下来,存入哈希表中;
  • 一旦遇到了此前遍历过的节点,就可以判定链表中存在环。

方法二:快慢指针

  • 使用快慢指针,起始都位于链表的头部,开始移动
  • 慢指针每次向后移动一个位置(slow = slow.next;),而快指针向后移动两个位置( fast = fast.next.next;)。
  • 如果链表中存在环,则两指针将再次相遇(fast == slow);
  • 再额外使用一个指针 ptr,起始,它指向链表头部ListNode ptr = head;;随后,它和慢指针每次向后移动一个位置ptr = ptr.next; slow = slow.next。最终,它们会在入环点相遇,返回ptr即可。

2.代码实现

public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null) {
            return null;
        }
        ListNode slow = head, fast = head;
        while (fast != null) {
            slow = slow.next;
            if (fast.next != null) {
                fast = fast.next.next;
            } else {
                return null;
            }
            if (fast == slow) {
                ListNode ptr = head;
                while (ptr != slow) {
                    ptr = ptr.next;
                    slow = slow.next;
                }
                return ptr;
            }
        }
        return null;
    }
}

3.复杂度分析

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值