代码随想录算法跟练 | Day4 | 链表Part2

个人博客主页:http://myblog.nxx.nx.cn
代码GitHub地址:https://github.com/nx-xn2002/Data_Structure.git

Day4

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

题目链接:
https://leetcode.cn/problems/swap-nodes-in-pairs/

题目描述:
给你一个链表,两两交换其中相邻的节点,并返回交换后链表的头节点。你必须在不修改节点内部的值的情况下完成本题(即,只能进行节点交换)。

思路:
对于这道题,我的思路类似于前一天的反转链表的一种做法,也就是使用递归。将前两个节点交换位置后,递归调用第三个节点,将结果作为第三个节点。

/**
 * 递归实现
 */
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;
}

19. 删除链表的倒数第 N 个结点

题目链接:
https://leetcode.cn/problems/remove-nth-node-from-end-of-list/

题目描述:
给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

思路:
本题的最简单的思路就是先遍历定位到倒数第 n 个节点,然后在第二次遍历中进行删除。但这样使用了两次遍历,还有更巧妙的方法只需要一次遍历就能解决,也就是快慢指针。
已知倒数第 n 个节点其实就是最后一个节点往前推 n 个节点,那么遍历的时候,我们一开始可以使用两个指针,一个指针先于另一个指针 n 个节点到达链表结尾,此时慢的那个指针的位置就是我们找的位置。

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if (headA == null || headB == null) {
        return null;
    }
    ListNode a = headA, b = headB;
    int count = 0;
    while (a != b) {
        if (count > 2) {
            return null;
        }
        if (a.next == null) {
            a = headB;
            count++;
        } else {
            a = a.next;
        }
        if (b.next == null) {
            b = headA;
            count++;
        } else {
            b = b.next;
        }
    }
    return a;
}

面试题 02.07. 链表相交

题目链接:
https://leetcode.cn/problems/intersection-of-two-linked-lists-lcci/

题目描述:
给你两个单链表的头节点 headAheadB ,请你找出并返回两个单链表相交的起始节点。如果两个链表没有交点,返回 null

思路:
本题的一个重点在于,节点的数值相同不代表节点相同,应该是节点的地址相同,这一点在 Java 中可以直接用 == 进行判断。这道题的思路就是无论是否有环,尝试让两个指针将两个链表都遍历一次,如果路途中相遇了,说明有环。

public ListNode detectCycle(ListNode head) {
    ListNode fast = head, slow = head;
    while (true) {
        if (fast == null || fast.next == null) {
            return null;
        }
        fast = fast.next.next;
        slow = slow.next;
        if (fast == slow) {
            break;
        }
    }
    fast = head;
    while (slow != fast) {
        slow = slow.next;
        fast = fast.next;
    }
    return fast;
}

面试题 02.07. 链表相交

题目链接:
https://leetcode.cn/problems/linked-list-cycle-ii/

题目描述:
给定一个链表的头节点 head ,返回链表开始入环的第一个节点。 如果链表无环,则返回 null

如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。如果 pos-1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。

不允许修改链表

思路:
这道题也是用追及的思路,使用快慢指针,快指针一次走两步,慢指针一次走一步,因此在存在环的情况下,相当于快指针每次追一步,两个指针会在环的入口处相遇。

public ListNode detectCycle(ListNode head) {
    ListNode fast = head, slow = head;
    while (true) {
        if (fast == null || fast.next == null) {
            return null;
        }
        fast = fast.next.next;
        slow = slow.next;
        if (fast == slow) {
            break;
        }
    }
    fast = head;
    while (slow != fast) {
        slow = slow.next;
        fast = fast.next;
    }
    return fast;
}
  • 13
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值