背景描述:
刷leetcode算法题的时候,遇到了一些开发中知道,但是工作时间久了不太注意的问题。虽然性能不好,但是概括了java里面不太注意的地方。所以借着算法题进行一下记录。
算法题目:
给你一个 m * n 的矩阵,矩阵中的数字 各不相同 。请你按 任意 顺序返回矩阵中的所有幸运数。
幸运数是指矩阵中满足同时下列两个条件的元素:
在同一行的所有元素中最小
在同一列的所有元素中最大
题目来源:力扣(LeetCode)
示例 1:
输入:matrix = [[3,7,8],[9,11,13],[15,16,17]]
输出:[15]
解释:15 是唯一的幸运数,因为它是其所在行中的最小值,也是所在列中的最大值。
示例 2:
输入:matrix = [[1,10,4,2],[9,3,8,7],[15,16,17,12]]
输出:[12]
解释:12 是唯一的幸运数,因为它是其所在行中的最小值,也是所在列中的最大值。
示例 3:
输入:matrix = [[7,8],[1,2]]
输出:[7]
自己写的算法性能分析统计
实现思路
找出每一行中最小的数,放到一个集合中。然后找出每一列中最大的数,放到一个集合中。然后比较两个集合中都存在的数,然后放到集合中,如果不存在,不往集合中放
自己的算法代码:
package testClass;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CountDownLatch;
//自己实现的查找幸运数
public class Solution {
//行数
int rowNum;
//行数组
List<Integer> rowArray = new ArrayList<>();
//列数组
List<Integer> colArray = new ArrayList<>();
public static void main(String[] args) {
//[[3,7,8],[9,11,13],[15,16,17]]
//int[][] arr1 = {{3,7,8}, {9,11,13}, {15,16,17}};
//int[][] arr = {{1,10,4,2}, {9,3,8,7}, {15,16,17,12}};
//[[1,10,4,2],[9,3,8,7],[15,16,17,12]]
//int[][] arr = {{1,10,4,2}, {9,3,8,7}, {15,16,17,12}};
//[7,8],[1,2]
//int[][] arr2 = {{7,8}, {1,2}};
//[[3,6],[7,1],[5,2],[4,8]]
int[][] arr = {{3,6}, {7,1}, {5,2}, {4,8}};
/**
* 首先main方法是静态的,而算法题中给定的方法是非静态
* 的,而静态方法中是不能直接调用非静态方法的。
* 如果我们非得调用,一般先声明非静态方法所在的对象,
* 通过对象.方法名调用就可以了。例如下面的代码:
* Solution ss = new Solution();
* List<Integer> result = ss.luckyNumbers(arr);
*/
Solution ss = new Solution();
List<Integer> result = ss.luckyNumbers(arr);
for(Integer re : result){
System.out.println(re);
}
}
public List<Integer> luckyNumbers (int[][] matrix) {
/**
* CountDownLatch 并发中的字段,作用是并发的时候,
* 进行并发协同。就是很多线程分工干一件事,等所有线程
* 都干完了,然后去执行下面的操作。
*
* 注意:
* 使用CountDownLatch 时候,每个线程执行结束都要
* countDown一下,所都的线程都结束时候,await一下。
* 在创建CountDownLatch的时候里面传的值就是线程数。
* 他是一个信号引用量,当他的数值为0时候,代表所有线程执
* 行完毕
*/
final CountDownLatch cd = new CountDownLatch(2);
new Thread(new Runnable() {
@Override
public void run() {
rowNum = matrix.length;
//行数
//System.out.println("rowNum=" + rowNum);
for (int i = 0; i<rowNum; i++){
/**
* copyMatrix数组的作用就是,两个线程共用
* matrix数组,当一个线程排序找出行中最小
* 的数的时候,线程二再去里面找列中最大数的
* 时候,因为线程一已经进行排序了,而线程二
* 拿到的是排序之后的,会对结果有影响。所以
* 在线程一种对目标数组进行备份,而我们平时
* 的 String a = "sd";
* String b = "we";
* 原因是他们不是new来的共享一个物理地址,
* 而平时数值是不同的,所以可以覆盖。现在是
* 内容相同,操作的时候只会保留最后一次结
* 果。这就会导致目标数组的内容会变化,所以
* 需要进行new一个对象,然后复制进去,同样也
* 不可以 int[] a = {4};
* int[] b = new int[a.length];
* b=a;这种的也是不可以的。正确操作是下面的
*/
int[] copyMatrix = new int[matrix[i].length];
System.arraycopy(matrix[i], 0, copyMatrix, 0, matrix[i].length);
Arrays.sort(copyMatrix);
//System.out.println("arr"+"["+i+"]"+"[0]"+arr[i][0]);
rowArray.add(copyMatrix[0]);
//System.out.println(rowArray.toString());
}
cd.countDown();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
//列数
for (int fl : matrix[0]){
System.out.println("========"+fl);
}
int length2 = matrix[rowNum-1].length;
//System.out.println("length2="+length2);
int j = 0;
//按列输出
for (int m = 0; m < length2; m++){
//定义一个暂时存放列的数组
int[] colTempArr = new int[rowNum];
int col = j++;
for (int i = 0; i < rowNum; i++){
//输出每一列
// System.out.print(matrix[i][col]+", ");
// System.out.println();
colTempArr[i] = matrix[i][col];
}
Arrays.sort(colTempArr);
//System.out.println("每一列最大的数:"+colTempArr[length2-1]);
colArray.add(colTempArr[rowNum-1]);
}
cd.countDown();
}
}).start();
//等待准备完成
try {
cd.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
//建立一个存放找到的相同数的集合
List<Integer> sameArr = new ArrayList<>();
//找出两个集合中相同的数
for (int rowArr : rowArray){
boolean contains = colArray.contains(rowArr);
if (contains){
sameArr.add(rowArr);
}
}
List<Integer> result = new ArrayList<>();
//如果最大值和最小值不相等
if(sameArr.size() == 0){
//如果没有相同的,输出空集合
}else {
Collections.sort(sameArr);
int sameLength = sameArr.size();
//System.out.println(sameArr.get(sameLength-1));
result.add(sameArr.get(sameLength - 1));
}
return result;
}
}
官方代码:
class Solution {
public List<Integer> luckyNumbers (int[][] matrix) {
int m = matrix.length, n = matrix[0].length;
int[] minRow = new int[m];
Arrays.fill(minRow, Integer.MAX_VALUE);
int[] maxCol = new int[n];
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
minRow[i] = Math.min(minRow[i], matrix[i][j]);
maxCol[j] = Math.max(maxCol[j], matrix[i][j]);
}
}
List<Integer> ret = new ArrayList<Integer>();
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
if (matrix[i][j] == minRow[i] && matrix[i][j] == maxCol[j]) {
ret.add(matrix[i][j]);
}
}
}
return ret;
}
}
官方代码的性能算法分析
官方代码的实现思路
预处理出每行的最小值minRow和每列的最大值数组maxCol,其中minRow[i]表示第i行的最小值,maxCol[j]表示第j列的最大值。遍历矩阵matrix,如果matrix[i][j]同时满足matrix[i][j]==minRow[i]和matrix[i][j]==maxCol[j],那么matrix[i][j]是矩阵中的幸运数,加入返回结果
共同探讨学习技术创建技术氛围Day9884125