剑指 Offer II 026. 重排链表(143. 重排链表)

题目:

 

 

 

思路:

【1】利用辅助空间的方式:先遍历一遍链表,将所有节点都存于数组中,然后按顺序一头一尾的配对连起来即可。

【2】不利用辅助空间的方式:先找出中位节点,拆分成两条链表(由于是链表,所以将指针指向一断就分成两条了,保留后半部分的首节点能拿到即可),将后半部分进行反转,再将两者合并。

代码展示:

利用辅助空间的方式:

//时间3 ms击败34.11%
//内存43.9 MB击败79.64%
//时间复杂度:O(N),其中 N 是链表中的节点数。
//空间复杂度:O(N),其中 N 是链表中的节点数。主要为线性表的开销。
/**
 * 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 void reorderList(ListNode head) {
        if (head == null) return;
        
        List<ListNode> list = new ArrayList<ListNode>();
        ListNode node = head;
        while (node != null) {
            list.add(node);
            node = node.next;
        }
        int i = 0, j = list.size() - 1;
        while (i < j) {
            list.get(i).next = list.get(j);
            i++;
            if (i == j) {
                break;
            }
            list.get(j).next = list.get(i);
            j--;
        }
        list.get(i).next = null;
    }
}

 

不利用辅助空间的方式:

//时间1 ms击败99.93%
//内存43.9 MB击败68.23%
//时间复杂度:O(N),其中 N 是链表中的节点数。
//空间复杂度:O(1)。
/**
 * 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 void reorderList(ListNode head) {
        //这三种情况分别代表[],[1],[1,2]这三种情况,都是不需要变化的
        if(head == null) return;
        if (head.next == null) return;
        if (head.next.next == null) return;
        
        ListNode mid = middleNode(head);
        ListNode l1 = head;
        ListNode l2 = mid.next;
        mid.next = null;
        l2 = reverseList(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 reverseList(ListNode head) {
        ListNode prev = null;
        ListNode curr = head;
        while (curr != null) {
            ListNode nextTemp = curr.next;
            curr.next = prev;
            prev = curr;
            curr = nextTemp;
        }
        return prev;
    }

    //将两部分再进行合并
    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;
        }
    }
}

 

posted @ 2023-03-10 12:52  忧愁的chafry  阅读(10)  评论(0编辑  收藏  举报