1252. 奇数值单元格的数目
给你一个 n
行 m
列的矩阵,最开始的时候,每个单元格中的值都是 0
。
另有一个索引数组 indices
,indices[i] = [ri, ci]
中的 ri
和 ci
分别表示指定的行和列(从 0
开始编号)。
你需要将每对 [ri, ci]
指定的行和列上的所有单元格的值加 1
。
请你在执行完所有 indices
指定的增量操作后,返回矩阵中 「奇数值单元格」 的数目。
示例 1
输入:n = 2,m = 3,indices = [ [0,1],[1,1] ]
输出:6
解释:最开始的矩阵是 [ [0,0,0],[0,0,0] ]。
第一次增量操作后得到 [ [1,2,1],[0,1,0] ]。
最后的矩阵是 [ [1,3,1],[1,3,1] ],里面有 6 个奇数。
示例 2
输入:n = 2,m = 2,indices = [ [1,1],[0,0] ]
输出:0
解释:最后的矩阵是 [ [2,2],[2,2] ],里面没有奇数。
提示
1 <= n <= 50
1 <= m <= 50
1 <= indices.length <= 100
0 <= indices[i][0] < n
0 <= indices[i][1] < m
解题思路
- 循环索引数组,计算每行每列出现的次数并保存
- 循环矩阵,单元格行列出现次数的和即为该单元格的值。
- 判断每个位置的值是否为奇数,计算总和
题解 JAVA 实现
public int oddCells(int n, int m, int[][] indices) {
int[] nCount = new int[n];
int[] mCount = new int[m];
for (int[] index : indices) {
nCount[index[0]] += 1;
mCount[index[1]] += 1;
}
int result = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
int num = nCount[i] + mCount[j];
if (num % 2 == 1) {
result += 1;
}
}
}
return result;
}
1253. 重构 2 行二进制矩阵
给你一个 2
行 n
列的二进制数组:
- 矩阵是一个二进制矩阵,这意味着矩阵中的每个元素不是
0
就是1
。 - 第
0
行的元素之和为upper
。 - 第
1
行的元素之和为lower
。 - 第 i 列(从 0 开始编号)的元素之和为
colsum[i]
,colsum
是一个长度为n
的整数数组。
你需要利用 upper
,lower
和 colsum
来重构这个矩阵,并以二维整数数组的形式返回它。
如果有多个不同的答案,那么任意一个都可以通过本题。
如果不存在符合要求的答案,就请返回一个空的二维数组。
示例 1
输入:upper = 2,lower = 1,colsum = [1,1,1]
输出:[ [1,1,0],[0,0,1] ]
解释:[ [1,0,1],[0,1,0] ] 和 [ [0,1,1],[1,0,0] ] 也是正确答案。
示例 2
输入:upper = 2,lower = 3,colsum = [2,2,1,1]
输出:[ ]
示例 3
输入:upper = 5, lower = 5, colsum = [2,1,2,0,1,0,1,2,0,1]
输出:[ [1,1,1,0,1,0,0,1,0,0],[1,0,1,0,0,0,1,1,0,1] ]
提示
1 <= nums.length <= 50000
1 <= nums[i] <= 10^5
1 <= k <= nums.length
解题思路
colsum 数组中,只可能能存在 0(0+0),1(1+0),2(1+1) 三中数值。
针对第 n 位,根据 colsum[n] 的值,有以下 3 中赋值方式:
- colsum[n] = 0,矩阵 1 和 矩阵 2 第 n 位的值为 0
- colsum[n] = 0,矩阵 1 或 矩阵 2 第 n 位的值为 1
- colsum[n] = 0,矩阵 1 和 矩阵 2 第 n 位的值为 1
首先计算 colsum 中有值为 2 的个数 countTwo
- 则第一行元素值为 1 的个数为 upper - countTwo
- 则第二行元素值为 1 的个数为 lower - countTwo
- 若元素值为 1 的个数 < 0,无解,返回空数组。
循环 colsum 数组,根据数值及 upper 和 lower 进行赋值。当 upper 和 lower 都为 0 后,colsum 数组再出现 > 0 的值,则返回空数组。
题解 JAVA 实现
public static List<List<Integer>> reconstructMatrix(int upper, int lower, int[] colsum) {
List<List<Integer>> resultList = new ArrayList<>();
List<Integer> list1 = new ArrayList<>(colsum.length);
List<Integer> list2 = new ArrayList<>(colsum.length);
int count2 = 0;
for (int i : colsum) {
if(i==2){
count2 += 1;
}
}
upper = upper - count2;
lower = lower - count2;
if(upper<0 || lower<0)
{
return resultList;
}
for (int i = 0; i < colsum.length; i++) {
if(colsum[i]==2){
list1.add(i,1) ;
list2.add(i,1);
} else if (colsum[i] == 0) {
list1.add(i,0);
list2.add(i,0);
}
if(colsum[i]==1){
if(upper>0){
list1.add(i,1) ;
list2.add(i,0);
upper--;
}else if(lower>0){
list2.add(i,1);
list1.add(i,0);
lower--;
}else{
return resultList;
}
}
}
if(upper == 0 && lower==0)
{ resultList.add(list1);
resultList.add(list2);}
return resultList;
}
1254. 统计封闭岛屿的数目
有一个二维矩阵 grid
,每个位置要么是陆地(记号为 0
)要么是水域(记号为 1
)。
我们从一块陆地出发,每次可以往上下左右 4 个方向相邻区域走,能走到的所有陆地区域,我们将其称为一座「岛屿」。
如果一座岛屿 完全 由水域包围,即陆地边缘上下左右所有相邻区域都是水域,那么我们将其称为 「封闭岛屿」。
请返回封闭岛屿的数目。
示例 1
示 | 例 | 1 | |||||
---|---|---|---|---|---|---|---|
1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 0 | 0 | 1 | 1 | 0 |
1 | 0 | 1 | 0 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 0 | 0 | 1 | 0 | 0 |
1 | 1 | 1 | 1 | 1 | 1 | 1 | 0 |
输入:grid = [ [1,1,1,1,1,1,1,0],[1,0,0,0,0,1,1,0],[1,0,1,0,1,1,1,0],[1,0,0,0,0,1,0,1],[1,1,1,1,1,1,1,0] ]
输出:2
解释:灰色区域(加粗的 0)的岛屿是封闭岛屿,因为这座岛屿完全被水域包围(即被 1 区域包围)。
示例 2
示 | 例 | 2 | ||
---|---|---|---|---|
0 | 0 | 1 | 0 | 0 |
0 | 1 | 0 | 1 | 0 |
0 | 1 | 1 | 1 | 0 |
输入:grid = [ [0,0,1,0,0],[0,1,0,1,0],[0,1,1,1,0] ]
输出:1
示例 3
输入:grid = [[1,1,1,1,1,1,1],
[1,0,0,0,0,0,1],
[1,0,1,1,1,0,1],
[1,0,1,0,1,0,1],
[1,0,1,1,1,0,1],
[1,0,0,0,0,0,1],
[1,1,1,1,1,1,1]]
输出:2
提示
1 <= grid.length, grid[0].length <= 100
0 <= grid[i][j] <=1
解题思路
坐标为(x,y)的位置,上下左右位置坐标如下图所示
坐 | 标 | 图 |
---|---|---|
x,y+1 | ||
x-1,y | x,y | x+1,y |
x,y-1 |
如何确定「封闭岛屿」:
- 值为 0 的位置,进行上下左右递归遍历,直到值为 1 或 达到或超出边界
- 遍历完所有与当前 0 位置连续的 0 值,没有超出矩阵范围并且所有 0 值位置不是边界,则该岛屿为封闭岛屿
递归遍历判断:
- 该位置是否为矩阵边界,为边界且值为 0,则非封闭岛屿。
- 该位置是否超出矩阵范围,超出则非封闭岛屿。(出现该情况只有边界为 0 之后的判断,边界为 0 已经可以判断为非封闭岛屿,结束该次判断即可)
- 该位置的值为 1 则结束此方向判断。为 0 继续进行上下左右递归判断。
- 该位置是否遍历过,没遍历则遍历,遍历过则跳过。
封闭岛屿如果存在,矩阵最小为: 3 * 3 矩阵
题解 JAVA 实现
private static boolean[][] flag;
private static boolean mark;
private static int[][] rowCol = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
public static int closedIsland(int[][] grid) {
int n = grid.length;
if (n <= 2) {
return 0;
}
int m = grid[0].length;
if (m <= 2) {
return 0;
}
int result = 0;
flag = new boolean[n][m];
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (flag[i][j] || grid[i][j] == 1) {
continue;
}
mark = true;
flag[i][j] = true;
dfs(grid, i, j);
if (mark) {
result++;
}
}
}
return result;
}
private static void dfs(int[][] grid, int x, int y) {
for (int i = 0; i < 4; i++) {
int xNew = x + rowCol[i][0];
int yNew = y + rowCol[i][1];
if (xNew < 0 || xNew >= grid.length || yNew < 0 || yNew >= grid[0].length) {
mark = false;
} else if (grid[xNew][yNew] != 1 && !flag[xNew][yNew]) {
flag[xNew][yNew] = true;
dfs(grid, xNew, yNew);
}
}
}
1255. 得分最高的单词集合
你将会得到一份单词表 words
,一个字母表 letters
(可能会有重复字母),以及每个字母对应的得分情况表 score
。
请你帮忙计算玩家在单词拼写游戏中所能获得的「最高得分」:能够由 letters
里的字母拼写出的 任意 属于 words
单词子集中,分数最高的单词集合的得分。
单词拼写游戏的规则概述如下:
- 玩家需要用字母表
letters
里的字母来拼写单词表 words 中的单词。 - 可以只使用字母表
letters
中的部分字母,但是每个字母最多被使用一次。 - 单词表
words
中每个单词只能计分(使用)一次。 - 根据字母得分情况表
score
,字母'a', 'b', 'c', ... , 'z'
对应的得分分别为score[0], score[1], ..., score[25]
。 - 本场游戏的「得分」是指:玩家所拼写出的单词集合里包含的所有字母的得分之和。
示例 1
输入:words = [“dog”,“cat”,“dad”,“good”], letters = [“a”,“a”,“c”,“d”,“d”,“d”,“g”,“o”,“o”], score = [1,0,9,5,0,0,3,0,0,0,0,0,0,0,2,0,0,0,0,0,0,0,0,0,0,0]
输出:23
解释:
字母得分为 a=1, c=9, d=5, g=3, o=2
使用给定的字母表 letters,我们可以拼写单词 “dad” (5+1+5)和 “good” (3+2+2+5),得分为 23 。
而单词 “dad” 和 “dog” 只能得到 21 分。
示例 2
输入:words = [“xxxz”,“ax”,“bx”,“cx”], letters = [“z”,“a”,“b”,“c”,“x”,“x”,“x”], score = [4,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,5,0,10]
输出:27
解释:
字母得分为 a=4, b=4, c=4, x=5, z=10
使用给定的字母表 letters,我们可以组成单词 “ax” (4+5), “bx” (4+5) 和 “cx” (4+5) ,总得分为 27 。
单词 “xxxz” 的得分仅为 25 。
示例 3
输入:words = [“leetcode”], letters = [“l”,“e”,“t”,“c”,“o”,“d”], score = [0,0,1,1,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,1,0,0,0,0,0,0]
输出:0
解释:
字母 "e"
在字母表 letters 中只出现了一次,所以无法组成单词表 words 中的单词。
提示
1 <= words.length <= 14
1 <= words[i].length <= 15
1 <= letters.length <= 100
letters[i].length == 1
score.length == 26
0 <= score[i] <= 10
words[i]
和letters[i]
只包含小写的英文字母。
解题思路
没有其他思路,纯暴力流。
计算所有可能性,计算所有可能性的得分,求得分最大值。
答题耗时 260ms+
答完看了下 Java 的最速时间,2ms  ̄□ ̄||
下面题解实现代码为 LeetCode 最速解答,非博主的实现方式,特此说明。
题解 JAVA 实现
int max = 0;
public int maxScoreWords(String[] words, char[] letters, int[] score) {
int[] scoreOfWords = new int [words.length];
for(int i=0; i<words.length; i++){
int count = 0;
for(int j =0; j<words[i].length(); j++){
count += score[words[i].charAt(j)-97];
}
scoreOfWords[i] = count;
}
int ans = 0;
int []manzu = new int[26];
for(int i=0; i<letters.length; i++){
manzu[letters[i]-97]++;
}
this.getOrNot(words, scoreOfWords, manzu, 0, 0);
return max;
}
public void getOrNot(String[] word, int[] scoreOfWords, int[] manzu, int index, int sum){
if(index==word.length){
max = Math.max(max, sum);
return;
}
int []cop = Arrays.copyOf(manzu, 26);
int flag = 0;
for(int i=0; i<word[index].length(); i++){
manzu[word[index].charAt(i)-97]--;
if(manzu[word[index].charAt(i)-97]<0){
flag = 1;
break;
}
}
if(flag == 0){
this.getOrNot(word, scoreOfWords, manzu, index+1, sum+scoreOfWords[index]);
this.getOrNot(word, scoreOfWords, cop, index+1, sum);
}
if(flag==1)
this.getOrNot(word, scoreOfWords, cop, index+1, sum);
}