力扣1337.矩阵战斗力最弱的k行(java TreeMap解法)

题目描述:

给你一个大小为 m * n 的矩阵 mat,矩阵由若干军人和平民组成,分别用 1 和 0 表示。

请你返回矩阵中战斗力最弱的 k 行的索引,按从最弱到最强排序。

军人 总是 排在一行中的靠前位置,也就是说 1 总是出现在 0 之前。

力扣1337.矩阵战斗力最弱的k行(java TreeMap解法)_第1张图片
力扣1337.矩阵战斗力最弱的k行(java TreeMap解法)_第2张图片

解题思路:

此处我们较直观的想法是遍历二维矩阵,计算每行的军人数量,再将其进行比较,得到符合题目要求的行数,所以我们可以想到用存在映射关系的数据结构,将每列的军人数作为键、将行数索引作为值,但是根据题目要求我们应该解决如下问题:

1.如何解决输出最弱的K行(即如何解决一个有关排序的问题)
2.如何满足如果第 i 行的军人数量少于第 j 行,或者两行军人数量相同但 i 小于 j,那么我们认为第 i 行的战斗力比第 j 行弱的要求,(即如果我们使用java中的 集合,该如何解决哈希冲突问题

我们通过如下操作解决:

1.由于题目中存在从小到大的一个顺序关系,我们可以使用java中的TreeMap集合(由于java中Map集合一般都是按键乱序输出,而TreeMap集合会按照键的从小到大顺序输出),将军人数作为键,对应得行数作为值。
2.由于题目中存在一个与哈希冲突有关得问题,在题目中也就是如何存入相同军人数目得行数,我们可以选择将值设计为一个List集合,当已经检测到存在键时,再将该行数添加到 List集合中

代码:

class Solution {
	//TreeMap
    //Time Complexity: O(N^2)
    //Space Complexity: O(N)
    public int[] kWeakestRows(int[][] mat, int k) {
    	//利用TreeMap的升序输出的特性
    	Map<Integer, List<Integer>> map = new TreeMap<>();
    	int[] sum = new int[mat.length];
    	int[] res = new int[k];
    	//遍历统计每行得军人数目
    	for (int i = 0; i < mat.length; i++) {
    		int temp = 0;
    		for (int j = 0; j < mat[0].length; j++) {
    			temp += mat[i][j];
    		}
    		//如果已经存在键,则在值列表中再次添加
    		if (containsKey(temp)) {
    			List<Integer> list = map.get(temp);
    			list.add(i);
    			map.put(temp,list);
    		} else {
    			List<Integer> list = new ArrayList<>();
    			list.add(i);
    			map.put(temp,list);
    		}
    	}
    	int i = 0;
    	for (List<Integer> list : map.values()) {
    		for (Integer l : list) {
    			sum[i++] = l;
    		}
    	}
    	System.arraycopy(sum,0,res,0,k);
    	return res;
    }
}

你可能感兴趣的:(力扣题目,leetcode,矩阵,算法)