1.<tag-排序和数组, 链表>-lt.215-数组中的第K个最大元素 + lt.148-排序链表(待完善)

lt.215-数组中的第K个最大元素

[案例需求]
在这里插入图片描述

[思路分析]

  • 本题出现频率非常的高!!!
  • 数组中的第K最大, 最小, 或者说中位数, 都可以用各种排序方法先对数组排序, 然后返回要求的值即可;
  • 所以嘛, 熟练掌握快排(迭代的, 递归的), 堆排序, 归并排序(迭代的, 递归的)非常有必要!!!, 当然了链表的各种快排, 归并排序也是必要的, 就在下面一道题.

具体的解析和详细代码可看笔者之前的一篇文章: 点我

[效率比较]

在这里插入图片描述

lt.148-排序链表

[案例需求]
在这里插入图片描述
[思路分析一, 优先队列]

  • 有没有这么一种神奇的数据结构, 它能够存入一些数据, 在拿出来的时候这些数据就是有序的了, 他肯定是一种集合容器;

  • 目前最常用的通过匿名内部类的方式添加比较器对象的, 其实也就TreeSet和PriorityQueue两种, 但是TreeSet会自动的对存入的数据去重, 而PriorityQueue就可以存入重复的数据.
    在这里插入图片描述

  • 本题我们采用优先队列 PriorityQueue, 为什么用这个?

  1. 可以通过类构造器传入自定义比较器, 但是TreeSet 也可以呀!
  2. 可以存入重复元素, 哈哈, TreeSet就不行啦!

/**
 * 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 sortList(ListNode head) {
        //排序链表
        //4-->2-->1-->3
        //优先队列
        
        if(head == null)return null;
        PriorityQueue<ListNode> queue = new PriorityQueue<>(new Comparator<ListNode>(){
            public int compare(ListNode node1, ListNode node2){
                return node1.val - node2.val;
            }
        });

        //遍历链表, 放入优先队列;
        ListNode temp = head;

        while(true){
            if(temp == null)break;
        
            queue.add(temp);
            temp = temp.next;
        }

        ListNode dummyNode = new ListNode(-1);
        ListNode temp1 = dummyNode;

        while(queue.size() != 0){
            ListNode node = queue.poll();
            node.next = null; //取出结点, 并断开结点的next域

            temp1.next = node;
            temp1 = temp1.next;
        }

        return dummyNode.next;
    }
}

[思路分析二, 单链表的快速排序]

链表快排!!! 也是相当的重要啦!

[思路分析三, 单链表的归并排序]

在这里插入图片描述

/**
 * 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 sortList(ListNode head) {
        if (head == null) {
            return null;
        }
        ListNode mid = getMid(head);
        if (mid.next == null) {
            return mid;
        }
        ListNode headB = mid.next;
        mid.next = null;
        return mergeTwoList(sortList(head), sortList(headB));
    }
    public ListNode getMid(ListNode head) {
        head = new ListNode(0, head);
        ListNode slow = head;
        ListNode fast = head;
        while (fast != null && fast.next != null) {
            slow = slow.next;
            fast = fast.next.next;
        }
        return slow;
    }
    public ListNode mergeTwoList(ListNode l1, ListNode l2) {
        ListNode dump = new ListNode();
        ListNode last = dump;
        while (l1 != null && l2 != null) {
            if (l1.val <= l2.val) {
                last.next = l1;
                l1 = l1.next;
            } else {
                last.next = l2;
                l2 = l2.next;
            }
            last = last.next;
        }
        if (l1 != null) {
            last.next = l1;
        }
        if (l2 != null) {
            last.next = l2;
        }
        return dump.next;
    }
}

[复杂度分析]
N为链表的长度, 时间复杂度为O(NlogN), 空间复杂度为O(logN)

这道题考察的点很多,有链表归并,有获取链表的中间节点等等,每一个考点都可以作为一道题来进行考察。

posted @   青松城  阅读(16)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示