LeetCode-链表中的排序问题

21. Merge Two Sorted Lists 合并两个有序链表

https://leetcode.com/problems/merge-two-sorted-lists/

题目:合并两个排序链接列表并将其作为新列表返回。新列表应该通过将前两个列表的节点拼接在一起来创建。

解答:

class Solution {
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;
        while(l1 != null && l2 != null) {
            if(l1.val < l2.val) {
                cur.next = l1;
                l1 = l1.next;
            } else {
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        if(l1 != null) {
            cur.next = l1;
        } else {
            cur.next = l2;
        }
        return dummy.next;
    }
}

143. Reorder List 重新排序链表

https://leetcode.com/problems/reorder-list/

题目:对于链表 LL0→L1→…→Ln-1→Ln,重新排序为 L0→LnL1→Ln-1→L2→Ln-2→…

思路:采用快慢指针来找到链表的中点,将中点后面的链表翻转,然后间隔地插入到前半部分的链表中。后半段翻转部分:先记录cur的next,再讲cur的next指向pre,更新pre的指向为和cur相同,更新cur为之前记录的cur的next,每一步都相当于让最新的节点(cur)指向已经完成翻转的链表(pre)。拼接两段链表时:先记录Ln的下一项Ln-1,然后让Ln的next指向L1,L0的next指向Ln,最后更新我们的指针;这样做比先让L0的next指向Ln会方便一些,只用暂时记录Ln的next,不然Ln和L0的next都需要记录。

class Solution {
    public void reorderList(ListNode head) {
        if (head == null || head.next == null) {
            return;
        }
        ListNode slow = head, fast = head;
        while(fast.next != null && fast.next.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        
        ListNode cur = slow.next, pre = null, next = null;
        while(cur != null) {
            next = cur.next;
            cur.next = pre;
            pre = cur;
            cur = next;
        }
        slow.next = null; // 要注意翻转完成后需要将两部分断开
        
        ListNode reHead = pre;
        ListNode tempHead = head;
        while(pre != null && tempHead != null) {
            // pre.next可以为null
            ListNode temp = pre.next;
            pre.next = tempHead.next;
            tempHead.next = pre;
            pre = temp;
            tempHead = tempHead.next.next;
        }
    }
}

147. Insertion Sort List 链表插入排序

https://leetcode.com/problems/insertion-sort-list/

题目:使用插入排序对链表进行排序。

思路:将元素从链表中取出来,然后按顺序插入到新链表中。当pre的next大于等于cur或为null时退出while循环,就将cur插入到pre和pre.next之间,此时满足pre.val < cur.val < pre.next.val。

class Solution {
    public ListNode insertionSortList(ListNode head) {
        if(head == null || head.next == null) return head;
        ListNode dummy = new ListNode(-1000);
        ListNode pre = dummy;
        ListNode cur = head;
        while(cur != null) {
            while(pre.next != null && pre.next.val < cur.val) {
                pre = pre.next;
            }
            ListNode next = cur.next;
            cur.next = pre.next;
            pre.next = cur;
            cur = next;
            pre = dummy;
        }
        return dummy.next;
    }
}

148. Sort List 链表排序

https://leetcode.com/problems/sort-list/

题目:使用常数空间复杂度对链接列表进行O(nlogn)时间排序。

思路:归并排序。将链表拆分,对每一部分应用mergeTwoLists即可得到结果。

class Solution {
    public ListNode sortList(ListNode head) {
        if(head == null || head.next == null) return head;
        ListNode fast = head, slow = head, pre = head;
        while(fast != null && fast.next != null) {
            pre = slow;
            slow = slow.next;
            fast = fast.next.next;
        }
        pre.next = null;
        return mergeTwoLists(sortList(head), sortList(slow));
    }
    
    public ListNode mergeTwoLists(ListNode l1, ListNode l2) {
        ListNode dummy = new ListNode(-1);
        ListNode cur = dummy;
        while(l1 != null && l2 != null) {
            if(l1.val < l2.val) {
                cur.next = l1;
                l1 = l1.next;
            } else {
                cur.next = l2;
                l2 = l2.next;
            }
            cur = cur.next;
        }
        if(l1 != null) {
            cur.next = l1;
        } else {
            cur.next = l2;
        }
        return dummy.next;
    }
}

转载于:https://www.cnblogs.com/nomad1c/p/11390279.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值