关于链表的相关操作

1、寻找链表的中点

// 找到链表的中点(快慢指针)
    public ListNode getMidNode(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (fast.next != null && fast.next.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }

 

2、翻转链表

// 翻转链表
    public ListNode reverse(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;

        while(curr != null) {
            ListNode node = curr.next;
            curr.next = prev;
            
            prev = curr;
            curr = node;
        }
        return prev;
    }

 

3、合并链表

// 合并链表
    public void merge(ListNode l1, ListNode l2) {
        ListNode l1_tmp;
        ListNode l2_tmp;
        while (l1 != null && l2 != null) {
            l1_tmp = l1.next;
            l2_tmp = l2.next;

            l1.next = l2;
            l1 = l1_tmp;

            l2.next = l1;
            l2 = l2_tmp;
        }
    }

 

综合例子143-重排链表

class Solution {
    public void reorderList(ListNode head) {
        if (head == null || head.next == null) return ;

        // 找到链表的中点
        ListNode node = getMidNode(head);
        ListNode head1 = node.next;
        node.next = null;   // 将左右两部分断开
        // 翻转链表
        head1 = reverse(head1);
        // 合并
        merge(head, head1);
    }
    
    // 找到链表的中点(快慢指针)
    public ListNode getMidNode(ListNode head) {
        ListNode slow = head;
        ListNode fast = head;
        while (fast.next != null && fast.next.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }

    // 翻转链表
    public ListNode reverse(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;

        while(curr != null) {
            ListNode node = curr.next;
            curr.next = prev;
            
            prev = curr;
            curr = node;
        }
        return prev;
    }

    // 合并链表
    public void merge(ListNode l1, ListNode l2) {
        ListNode l1_tmp;
        ListNode l2_tmp;
        while (l1 != null && l2 != null) {
            l1_tmp = l1.next;
            l2_tmp = l2.next;

            l1.next = l2;
            l1 = l1_tmp;

            l2.next = l1;
            l2 = l2_tmp;
        }
    }
}

 

k个一组反转链表

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
        if (head == null || head.next == null) return head;

        ListNode dummy = new ListNode(-1, head);
        ListNode prev = dummy;

        while (head != null) {
            ListNode tail = prev;   // tail往后移动 找到长度为k的子链
            // 查看剩余部分长度是否>=k
            for (int i = 0; i < k; i++) {
                tail = tail.next;
                if (tail == null) { // 长度不足k 直接反转
                    return dummy.next;
                }
            }

            // 找到要分离的位置tail后,保存分离后的下一个位置,以便能装回原链表
            ListNode next = tail.next;

            ListNode[] reverseSet = reverse(head, tail);
            head = reverseSet[0];
            tail = reverseSet[1];

            // 把子链重新装回原链表中
            prev.next = head;
            tail.next = next;

            prev = tail;
            head = tail.next;
        }    
        return dummy.next;
    }

    // 翻转链表,返回一个链表的首部和尾部
    public ListNode[] reverse(ListNode head, ListNode tail) {
        ListNode prev = tail.next;
        ListNode curr = head;

        while (prev != tail) {
            ListNode next = curr.next;
            curr.next = prev;
            prev = curr;
            curr = next;
        }

        return new ListNode[]{tail, head};
    }
}

 // 判断链表是否有环,以及环的入口在哪里

 /**
  * 空间优化O(n)
  * 快慢指针可以用来判断是否有环
  * 因为L_fast = 2L_slow
  * 出发点到相遇点的距离等于相遇点到环路的进入点
  */
public class Solution {
    public ListNode detectCycle(ListNode head) {
        if (head == null || head.next == null) return null;
        ListNode dummy = new ListNode(-1);
        dummy.next = head;  // 快慢指针的起始点

        ListNode slow = head;
        ListNode fast = head.next;
        while(slow != fast) {   
            // 如果无环 
            if (fast == null || fast.next == null) return null; 
            slow = slow.next;
            fast = fast.next.next;
        }
     // 相遇问题 ListNode ans
= dummy; while (ans != slow) { ans = ans.next; slow = slow.next; } return ans; } }

 https://leetcode-cn.com/problems/maximum-twin-sum-of-a-linked-list/solution/shuang-zhou-sai-di-69chang-leetcode5961l-rals/

posted @ 2021-11-10 10:21  Peterxiazhen  阅读(42)  评论(0编辑  收藏  举报