LeetCode记录 有序矩阵中第K小的数

有序矩阵中的第K小的数

日期:2020年7月10日08:46:36

难度:中等
时长:N天(大雾)
分类:暴力、堆、归并、二分

题目:

给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第 k 小的元素。
请注意,它是排序后的第 k 小元素,而不是第 k 个不同的元素。

示例:

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

返回 13。

解法:

  1. 降维+sort排序
  2. 降维+堆排序
  3. 归并
  4. 二分

自我尝试——思想错误

我也不知道我在想啥,用了一般的数学找规律,以为是这样的

1
4
9
16
25

然后以为每个正方形是个数值块,右下角的值最大,然后根据K开平方得到所在排和列。。。然后直接排序查找,,,
然而,并不是这样的规律的矩阵

// 自我尝试——思想错误
/**
 * @param {number[][]} matrix
 * @param {number} k
 * @return {number}
 */
var kthSmallest = function (matrix, k) {
  if (k <= 1) {
    return matrix[0][0];
  }
  var low = Math.floor(Math.sqrt(k)); // 所在排
  console.log(low);

  var diff = k - low * low;
  console.log(diff);
  if (0 == diff) {
    return matrix[low - 1][low - 1];
  } else {
    var row = matrix[low];

    var col = [];
    for (var i = 0; i < low; i++) {
      col.push(matrix[i][low]);
    }

    // console.log(row);
    // console.log(col);
    var newArr = Array.prototype.concat(row, col);
    newArr.sort(function (a, b) {
      return a - b;
    });
    // console.log(newArr);
    return newArr[diff - 1];
  }
};
// var matrix = [
//     [1, 5, 9],
//     [10, 11, 13],
//     [12, 13, 15],
//   ],
//   k = 8;
var matrix = [
    [1, 2],
    [1, 3],
  ],
  k = 4;
console.log(kthSmallest(matrix, k));

正解

  1. 降维+sort

    //直接排序
    var kthSmallest = function (matrix, k) {
      var arr = [];
      for (var i = 0; i < matrix.length; i++) {
        for (var j = 0; j < matrix[i].length; j++) {
          arr.push(matrix[i][j]);
        }
      }
      arr.sort(function (a, b) {
        return a - b;
      });
      return arr[k - 1];
    };
    
  2. 降维+最大堆

    siftdown
    首先判断节点的左子节点是否存在,然后和左子节点进行比较,得到较大的再和右子节点比较,得到子树中最大的,然后进行交换。继续判断其子树直到没子树

    // 拆解矩阵 + 最大堆(
    /**
     * @param {number[][]} matrix
     * @param {number} k
     * @return {number}
     */
    var kthSmallest = function (matrix, k) {
      function Heap(arr) {
        this.heap = arr || [];
        return this.init();
      }
      Heap.prototype = {
        constructor: Heap,
        init: function () {
          this.len = this.heap.length;
          // console.log(this.heap);
    
          if (this.len == 0) {
            throw Error("数据为空");
          }
        },
        get() {
          return this.heap;
        },
        peekHead: function () {
          return this.heap[0];
        },
        replaceHead: function (num) {
          this.heap[0] = num;
          return this.heap;
        },
        getMaxHeap: function () {
          for (let i = Math.floor(this.len / 2); i >= 0; i--) {
            // console.log("根节点", this.heap[i]);
            this.siftDown(i);
          }
          return this.heap;
        },
        siftDown: function (i) {
          var flag = false;
          var t = i;
          // 节点循环
          // console.log("被优化的", this.heap[i]);
    
          while (i * 2 < this.len && !flag) {
            // 左子节点判断
            if (this.heap[i] < this.heap[i * 2]) {
              t = i * 2;
            } else {
              t = i;
            }
            // 右子节点判断
            if (i * 2 + 1 < this.len) {
              if (this.heap[t] < this.heap[i * 2 + 1]) {
                t = i * 2 + 1;
              }
              // else {
              //   t = i;
              // }
            }
            if (t == i) {
              flag = true;
            } else {
              var temp = this.heap[i];
              this.heap[i] = this.heap[t];
              this.heap[t] = temp;
              i = t;
            }
          }
        },
      };
      // 降维
      var arr = [];
      for (var i = 0; i < matrix.length; i++) {
        arr.push(...matrix[i]);
      }
      // 创建最大堆
      var heap = new Heap(arr.slice(0, k));
      heap.getMaxHeap();
      // console.log(heap);
    
      for (var j = k; j < arr.length; j++) {
        // console.log(arr[j], heap.peekHead());
        if (arr[j] <= heap.peekHead()) {
          heap.replaceHead(arr[j]);
          heap.siftDown(0);
        }
      }
      // console.log(heap);
      return heap.peekHead();
    };
    var matrix = [
        [1, 5, 9],
        [10, 11, 13],
        [12, 13, 15],
      ],
      k = 8;
    var matrix = [
        [1, 2],
        [1, 3],
      ],
      k = 2;
    var matrix = [
        [1, 3, 5],
        [6, 7, 12],
        [11, 14, 14],
      ],
      k = 5;
    console.log(kthSmallest(matrix, k));
    
  3. 归并

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值