矩阵中的幸运数

背景描述:

  刷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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值