链表

38 阅读2分钟

1. 链表反转

1.1 反转链表

public ListNode reverseList(ListNode head) {
        ListNode cur = head, pre = null;
        while(cur != null){
            ListNode temp = cur.next;
            cur.next = pre;
            pre = cur;
            cur = temp;
        }
        
        return pre;
}

1.2 反转链表 II

    public ListNode reverseBetween(ListNode head, int left, int right) {
        if(right-left == 0) return head;
        if(head == null) return head;

        ListNode reversePre = head;  // 反转区间的头节点的上一个节点
        for(int i=1;i<left-1;i++) reversePre = reversePre.next;

        ListNode reverseHead = null; // 反转区间的头结点
        if(left == 1) reverseHead = reversePre;
        else reverseHead = reversePre.next; 
        
        ListNode cur = reverseHead.next;
        ListNode next = cur;
        ListNode pre = reverseHead;
        for(int i=0;i<(right-left);i++){
            next = cur.next;
            cur.next = pre;
            pre = cur;
            if(cur.next != null) cur = next;
        }

        if(reverseHead == reversePre){
            reverseHead.next = next;
            return pre;
        }else{
            reversePre.next = pre;
            reverseHead.next = next;
        }
       
        return head;
    }

1.3 K 个一组翻转链表

    public ListNode reverseKGroup(ListNode head, int k) {
        if(head==null || k==1) return head;

        // 初始化一开始的start和head
        ListNode start = head;
        ListNode end = head;
        for(int i=1;i<k;i++){
            if(end == null) break;
            end = end.next;
        }
        head = end;

        while (end != null){
            // 反转该链表
            ListNode pre = start;
            ListNode cur = pre.next;
            ListNode next = null;
            for(int i=1;i<k;i++){
                next = cur.next;
                cur.next = pre;
                pre = cur;
                cur = next;                
            }
            // 找start节点的next节点
            end = next;
            for(int i=1;i<k;i++){
                if(end == null) break;
                end = end.next;
            }
            // 如果长度满足,start的next节点是下一组节点的end节点
            // 如果长度不满足,start的next节点是下一组节点的头节点
            if(end != null) start.next = end;
            else start.next = next;

            start = next;
        }

        return head;
    }

2. 删除排序链表中的重复元素

2.1 删除排序链表中的重复元素

    public ListNode deleteDuplicates(ListNode head) {
        ListNode cur = head;
        while(cur != null){
            ListNode next = cur.next;
            // 找到值和cur不相等的节点,删掉中间部分
            while(next!=null && cur.val == next.val ){
                next = next.next;
            }
            cur.next = next;
            cur = next;
        }
        return head;
    }

2.2 删除排序链表中的重复元素 II

    public ListNode deleteDuplicates(ListNode head) {
        ListNode dummy = new ListNode();
        ListNode tail = dummy;

        while(head != null){
            // 进入循环时,确保了head不会与上一节点相同
            if(head.next==null || head.val!=head.next.val){
                tail.next = head;
                tail = head;
            }
            // 如果head与下一节点相同,跳过相同节点
            while(head.next!=null && head.val==head.next.val) head=head.next;
            head = head.next;
        }

        tail.next = null;
        return dummy.next;
    }

3. 其他

3.1 重排链表

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

        ListNode mid = middleNode(head);
        ListNode l1 = head;
        ListNode l2 = mid.next;
        mid.next = null;    // 断掉左边右边

        l2 = reverseRightList(l2);

        mergeList(l1, l2);
    }

    // 快慢指针找链表中点
    public ListNode middleNode(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 reverseRightList(ListNode head){
        ListNode pre = null;
        ListNode cur = head;
        while(cur != null){
            ListNode next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        return pre;
    }

    // 交叉合并左半段和右半段
    public void mergeList(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;
        }
    }
}