代码随想录算法训练营第四天| 22. 两两交换链表中的节点、 19.删除链表的倒数第N个节点、面试题 02.07. 链表相交

149 阅读3分钟

代码随想录算法训练营第四天| 22. 两两交换链表中的节点、 19.删除链表的倒数第N个节点、面试题 02.07. 链表相交

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

题目描述

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

aa.jpg

算法实现(哑节点)

待反转的链表
12345
添加哑节点
012345

反转链表

prevheadhead.nexthead.next.next
0123
  1. 暂时保存head.next.next 节点为temp 以为下面旋转的时候该结点没有指向 就会无法找到
  2. prev.next节点指向head.next
  3. head.next .next指向 head
  4. head.next指向temp节点

反转后的链表

prev21345
  1. 开始移动prev节点的指向 head节点(1)
  2. 移动head 指针到下一个节点 head=head.next
 public static ListNode swapPairs(ListNode head) {
        ListNode dummyNode = new ListNode(-1);
        dummyNode.next = head;
        ListNode prev = dummyNode;

        while (prev.next != null && prev.next.next != null) {

            ListNode temp = head.next.next; //save the node 
            prev.next = head.next;
            head.next.next = head;
            head.next = temp;

            prev = head; //move the pre node 
            head = head.next; //move the next node 

        }
        return dummyNode.next;
    }

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

题目描述

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

算法实现

 public ListNode removeNthFromEnd(ListNode head, int n) {
        ListNode dummyNode = new ListNode(-1); //添加 dummyNode
        dummyNode.next=head;

        ListNode fast=dummyNode;
        ListNode slow=dummyNode;
        while (n-->=0){// fast 先移动n+1 步
            fast=fast.next;
        }

        while(fast!=null){// 同时移动
            fast=fast.next;
            slow=slow.next;
        }
        // slow 节点是要删除的节点的前一个节点
        slow.next=slow.next.next;
        return dummyNode.next;
    }

面试题 02.07. 链表相交

题目描述

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

算法实现

public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
        if (null == headA || null == headB) {
            return null;
        }
        ListNode pA = headA;
        ListNode pB = headB;

        while (pA != pB) {
            pA = pA == null ? headB : pA.next;
            pB = pB == null ? headA : pB.next;
        }
        return pA;
    }

142. 环形链表 II

题目描述

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

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

不允许修改 链表。

算法实现

集合Set实现
 public ListNode detectCycle(ListNode head) {
        Set<ListNode> set = new HashSet<>();
        while (head != null) {
            if (!set.add(head)) { // 代表set集合中已经有该节点
                return head;
            }
            head = head.next;
        }
        return null;
    }
快慢指针
public ListNode detectCycle1(ListNode head) {
        if (head == null) return null;
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
            if (slow == fast) {// 存在环
                ListNode newFastNode = fast;
                ListNode newSlowNode = head;
                while (newFastNode != newSlowNode) {
                    newFastNode = newFastNode.next;
                    newSlowNode = newSlowNode.next;
                }
                return newFastNode;
            }
        }
        return null;
    }