@@ -52,8 +52,9 @@ private KthSmallestElementInASortedMatrix() {}
5252 */
5353
5454 /**
55- * url: https://leetcode.cn/problems/kth-smallest-element-in-a-sorted-matrix/solution/shi-yong-dui-heapde-si-lu-xiang-jie-ling-fu-python/
56- * url: https://blog.csdn.net/lanheboyuan/article/details/107096011
55+ * url:
56+ * https://leetcode.cn/problems/kth-smallest-element-in-a-sorted-matrix/solution/shi-yong-dui-heapde-si-lu-xiang-jie-ling-fu-python/
57+ * https://blog.csdn.net/lanheboyuan/article/details/107096011
5758 *
5859 * 1、堆排序+记录行数
5960 * 因为矩阵从左往右、从上到下依次是有序的,如果矩阵有两行,那么就变成两个有序矩阵合并求第k小元素,这就是归并排序的最基础形式;
@@ -80,12 +81,100 @@ static Integer kthSmallest(int[][] matrix, int k) {
8081 return heap .peek ();
8182 }
8283
84+ static Integer kthSmallestH (int [][] matrix , int k ) {
85+ int [] arr = new int [k ];
86+ int row = matrix .length , col = matrix [0 ].length ;
87+ int count = 0 , i = 0 , j = 0 ;
88+ for (; i < row ; i ++) {
89+ for (j = 0 ; j < col ; j ++) {
90+ if (count >= k ) {
91+ break ;
92+ }
93+ int cur = matrix [i ][j ];
94+ arr [count ++] = cur ;
95+ }
96+ if (count >= k ) {
97+ break ;
98+ }
99+ }
100+ for (int x = (k - 1 ) / 2 ; x >= 0 ; x --) {
101+ //从第一个非叶子结点从下至上,从右至左调整结构
102+ downAdjust (arr , x , k );
103+ }
104+ for (; i < row ; i ++) {
105+ for (; j < col ; j ++) {
106+ int cur = matrix [i ][j ];
107+ if (cur < arr [0 ]) {
108+ arr [0 ] = cur ;
109+ downAdjust (arr , 0 , k );
110+ }
111+ }
112+ j = 0 ;
113+ }
114+ return arr [0 ];
115+ }
116+
117+ // 大根堆
118+ private static void downAdjust (int [] arr , int p , int k ) {
119+ // arr = int[k+1];
120+ // parent = i, left = 2i+1, right = 2i+2, i < k
121+
122+ //将temp作为父节点
123+ int tmp = arr [p ];
124+ //左孩子
125+ int l = 2 * p + 1 ;
126+ while (l < k ) {
127+ //右孩子
128+ int r = l + 1 ;
129+ // 如果有右孩子结点,并且右孩子结点的值大于左孩子结点,则选取右孩子结点
130+ if (r < k && arr [l ] < arr [r ]) {
131+ l ++;
132+ }
133+
134+ // 如果父结点的值已经大于孩子结点的值,则直接结束
135+ if (tmp >= arr [l ]) {
136+ break ;
137+ }
138+
139+ // 把孩子结点的值赋给父结点
140+ arr [p ] = arr [l ];
141+
142+ //选取孩子结点的左孩子结点,继续向下筛选
143+ p = l ;
144+ l = 2 * l + 1 ;
145+ }
146+ arr [p ] = tmp ;
147+ }
148+ /**
149+ * 创建堆,
150+ * @param arr 待排序列
151+ */
152+ private static void heapSort (int [] arr ) {
153+ //创建堆
154+ for (int i = (arr .length - 1 ) / 2 ; i >= 0 ; i --) {
155+ //从第一个非叶子结点从下至上,从右至左调整结构
156+ downAdjust (arr , i , arr .length );
157+ }
158+
159+ //调整堆结构+交换堆顶元素与末尾元素
160+ for (int i = arr .length - 1 ; i > 0 ; i --) {
161+ //将堆顶元素与末尾元素进行交换
162+ int temp = arr [i ];
163+ arr [i ] = arr [0 ];
164+ arr [0 ] = temp ;
165+
166+ //重新对堆进行调整
167+ downAdjust (arr , 0 , i );
168+ }
169+ }
170+
171+
83172 /**
84173 * url:
85174 * https://www.superweb999.com/article/280646.html
86175 * https://zhuanlan.zhihu.com/p/140541322
87176 * https://www.programminghunter.com/article/7306413754/
88- *
177+ *
89178 * 2. 二分查找
90179 * 矩阵内的元素是从左上到右下递增的,整个二维数组中 matrix[0][0] 为最小值,matrix[n−1][n−1] 为最大值,现在将其分别记作 left 和 right。
91180 * 任取一个数 mid 满足 left ≤ mid ≤ right,那么矩阵中不大于 mid 的数,肯定全部分布在矩阵的左上角。
@@ -151,19 +240,30 @@ private static boolean check(int[][] matrix, int mid, int k, int n) {
151240
152241 private static void testFindK () {
153242 int [][] arr = new int [][]{
154- {1 ,2 ,3 ,4 },
155- {2 ,3 ,4 ,5 },
156- {3 ,4 ,5 ,6 },
157- {4 ,5 ,6 ,7 }};
158- int k = 3 ;
243+ {1 , 2 , 3 , 4 },
244+ {3 , 3 , 4 , 5 },
245+ {3 , 4 , 5 , 6 },
246+ {4 , 5 , 6 , 7 }};
247+ int k = 8 ;
248+
249+ // int[][] arr = new int[][]{
250+ // {1, 5, 9},
251+ // {10, 11, 13},
252+ // {12, 13, 15}};
253+ // int k = 8;
254+
159255 int rs = kthSmallest (arr , k );
160256 System .out .println (rs );
161257
258+ rs = kthSmallestH (arr , k );
259+ System .out .println (rs );
260+
162261 rs = kthSmallestBS (arr , k );
163262 System .out .println (rs );
164263 }
165264
166265 public static void main (String [] args ) {
167266 testFindK ();
267+ heapSort (new int []{-1 , 0 , 3 , 7 , 1 , 5 });
168268 }
169269}
0 commit comments