【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-1yAx-1y-1
AxyAxy+1
Ax+1yAx+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;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值