【leetcode】378. Kth Smallest Element in a Sorted Matrix

文章目錄

題目

題目鏈接: https://leetcode.com/problems/kth-smallest-element-in-a-sorted-matrix/

Given a n x n matrix where each of the rows and columns are sorted in ascending order, find the kth smallest element in the matrix.

Note that it is the kth smallest element in the sorted order, not the kth distinct element.

Example:

matrix = [ [ 1, 5, 9], [10, 11, 13], [12, 13, 15] ], k = 8,

return 13.

Note:
You may assume k is always valid, 1 ≤ k ≤ n2.

思路

自定義有序鏈表,從小大排列
實現對應的刪除和插入操作

  1. 先將首行依次放入有序鏈表
  2. 遍歷k-1次,找到k-1小元素並刪除
    2.1 將第i小元素下方的元素加入有序列表中
    2.2 刪除第i小元素
    如果第i小元素是最後一行的,則刪除它然後再遍歷
  3. 返回有序鏈表表頭元素值

爲什麼第2.1步驟是第i小元素下方的元素
假設第i小元素爲Axy,則加入鏈表中的元素爲Ax+1y

  • Ax-1y肯定已經出有序鏈表
  • Ax+1y+1肯定比Ax+1y,所以Ax+1y 要先進鏈表
    比較不好判斷的是Axy+1
  • 如果Ax-1y-1 < Axy,則Axy+1也已經在鏈表中,因爲Ax-1y-1比Axy先出鏈表
  • 如果Ax-1y-1 >= Axy,如果Ax+1y =< Ax-1y-1,Ax+1y<=Axy+1 沒什麼問題,
  • 如果Ax-1y-1 >= Axy, 如果Ax+1y > Ax-1y-1且Ax+1y>Axy+1,則Ax-1y-1必定會在Ax+1y出鏈表,則Ax-1y-1出的時候Axy+1進入且插入Ax+1y之前,所以也沒什麼問題。
Ax-1y Ax-1y-1
Axy Axy+1
Ax+1y Ax+1y+1

代碼

直接用鏈表實現的,插入的時候從頭開始遍歷鏈表
其實可以用二分查找進行優化插入位置

    class ListNode {
        int val;
        int x;
        int y;
        ListNode next;
        ListNode(int val, int x, int y) {
            this.val = val;
            this.x = x;
            this.y = y;
        }
    }

    public ListNode rmTop(ListNode root) {
        return root.next;
    }

    public void insetList(ListNode root, ListNode node) {
        ListNode p = root, q = root.next;
        while (q != null && q.val <= node.val) {
            p = q;
            q = q.next;
        }
        p.next = node;
        if (q != null) {
            node.next = q;
        }
    }

    public int kthSmallest(int[][] matrix, int k) {
        if (matrix == null || matrix.length <= 0 || matrix[0].length <= 0) return -1;
        // 第一行放入有序列表中
        ListNode root = new ListNode(matrix[0][0], 0, 0);
        ListNode tmp = root;
        for (int i = 1; i < matrix[0].length; i++) {
            ListNode node = new ListNode(matrix[0][i], 0, i);
            tmp.next = node;
            tmp = node;
        }
        for (int i = 1; i < k; i++) {
            if (root.x + 1 >= matrix[0].length) {
                root = rmTop(root);
                continue;
            }
            ListNode node = new ListNode(matrix[root.x + 1][root.y], root.x + 1, root.y);
            // 將node插入有序列表
            insetList(root, node);
            // 刪除top i節點
            root = rmTop(root);
        }
        return root.val;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章