【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;
    }

你可能感兴趣的:(每日总结,leetcode)