忙完都11:40了,原本都不想做了,一看第一题很简单,然后一做就停不下来了···
5255. 奇数值单元格的数目 显示英文描述
用户通过次数948
用户尝试次数974
通过次数970
提交次数1244
题目难度Easy
给你一个 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
这个题挺没意思的。就不说了。
public int oddCells(int n, int m, int[][] indices) {
int[][] arr = new int[n][m];
for (int i = 0; i < indices.length; i++) {
for (int j = 0; j < m; j++) {
arr[indices[i][0]][j] += 1;
}
for (int j = 0; j < n; j++) {
arr[j][indices[i][1]] += 1;
}
}
int sum = 0;
for (int i = 0; i < n; i++) {
for (int j = 0; j < m; j++) {
if (arr[i][j] % 2 == 1) {
sum++;
}
}
}
return sum;
}
5256. 重构 2 行二进制矩阵 显示英文描述
用户通过次数691
用户尝试次数812
通过次数700
提交次数2213
题目难度Medium
给你一个 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 <= colsum.length <= 10^5
0 <= upper, lower <= colsum.length
0 <= colsum[i] <= 2
这个题乍一看,给我的第一直觉就是回溯。
结果。。。
先看一下回溯的代码吧
private int nowUpper = 0;
private int nowLower = 0;
private boolean isFind = false;
private List<Integer> temListUpper = new ArrayList<>();
private List<Integer> temListLower = new ArrayList<>();
public List<List<Integer>> reconstructMatrix(int upper, int lower, int[] colsum) {
List<List<Integer>> lists = new ArrayList<>();
backtrack(0, lists, upper, lower, colsum);
return lists;
}
private void backtrack(int n, List<List<Integer>> lists, int upper, int lower, int[] colsum) {
if (n == colsum.length) {
if (upper == nowUpper && lower == nowLower) {
lists.add(new ArrayList<>(temListUpper));
lists.add(new ArrayList<>(temListLower));
isFind = true;
}
return;
}
if (isFind || (nowLower > lower && nowUpper > upper)) {
return;
}
switch (colsum[n]) {
case 0:
temListLower.add(0);
temListUpper.add(0);
backtrack(n + 1, lists, upper, lower, colsum);
temListLower.remove(temListLower.size() - 1);
temListUpper.remove(temListUpper.size() - 1);
break;
case 1:
for (int i = 0; i < 2; i++) {
if (i == 0) {
temListLower.add(0);
temListUpper.add(1);
nowUpper += 1;
backtrack(n + 1, lists, upper, lower, colsum);
temListLower.remove(temListLower.size() - 1);
temListUpper.remove(temListUpper.size() - 1);
nowUpper -= 1;
} else {
temListLower.add(1);
temListUpper.add(0);
nowLower += 1;
backtrack(n + 1, lists, upper, lower, colsum);
temListLower.remove(temListLower.size() - 1);
temListUpper.remove(temListUpper.size() - 1);
nowLower -= 1;
}
}
break;
case 2:
nowUpper += 1;
nowLower += 1;
temListLower.add(1);
temListUpper.add(1);
backtrack(n + 1, lists, upper, lower, colsum);
temListLower.remove(temListLower.size() - 1);
temListUpper.remove(temListUpper.size() - 1);
nowUpper -= 1;
nowLower -= 1;
break;
}
}
一看这个数据量
1 <= colsum.length <= 10^5
哈哈,稳稳的超时。
最后想想,这个题其实并不是什么算法题,两遍循环就搞定了。
public List<List<Integer>> reconstructMatrix2(int upper, int lower, int[] colsum) {
List<List<Integer>> lists = new ArrayList<>(3);
int[][] arr = new int[2][colsum.length];
for (int i = 0; i < colsum.length; i++) {
if (colsum[i] == 2) {
arr[0][i] = 1;
arr[1][i] = 1;
upper--;
lower--;
if (upper < 0 || lower < 0) {
return lists;
}
}
}
for (int i = 0; i < colsum.length; i++) {
if (colsum[i] == 1) {
if (upper > 0) {
arr[0][i] = 1;
upper--;
} else if (lower > 0) {
arr[1][i] = 1;
lower--;
} else {
return lists;
}
}
}
if (lower != 0 || upper != 0) {
return lists;
}
List<Integer> list1 = new ArrayList<>(colsum.length + 1);
List<Integer> list2 = new ArrayList<>(colsum.length + 1);
for (int i = 0; i < arr[0].length; i++) {
list1.add(arr[0][i]);
list2.add(arr[1][i]);
}
lists.add(list1);
lists.add(list2);
return lists;
}
5257. 统计封闭岛屿的数目 显示英文描述
用户通过次数436
用户尝试次数513
通过次数440
提交次数793
题目难度Medium
有一个二维矩阵 grid ,每个位置要么是陆地(记号为 0 )要么是水域(记号为 1 )。
我们从一块陆地出发,每次可以往上下左右 4 个方向相邻区域走,能走到的所有陆地区域,我们将其称为一座「岛屿」。
如果一座岛屿 完全 由水域包围,即陆地边缘上下左右所有相邻区域都是水域,那么我们将其称为 「封闭岛屿」。
请返回封闭岛屿的数目。
示例 1:
输入: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
解释:
灰色区域的岛屿是封闭岛屿,因为这座岛屿完全被水域包围(即被 1 区域包围)。
示例 2:
输入: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
这个题应该用深搜也可以吧,但是不太好写应该。
我用广搜做的。
boolean[][] isVisit;
boolean isHave = true;
public int closedIsland(int[][] grid) {
isVisit = new boolean[grid.length][grid[0].length];
int count = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[i].length; j++) {
if (grid[i][j] == 0 && !isVisit[i][j]) {
BFS(i, j, grid);
if (isHave) {
count++;
}
}
isHave = true;
}
}
return count;
}
private void BFS(int i, int j, int[][] grid) {
Queue<List<Integer>> queue = new LinkedList<>();
queue.add(new ArrayList<>(Arrays.asList(i, j)));
while (!queue.isEmpty()) {
int size = queue.size();
for (int k = 0; k < size; k++) {
List<Integer> list = queue.poll();
int i1 = list.get(0);
int j1 = list.get(1);
isVisit[i1][j1] = true;
if (i1 == 0 || i1 == grid.length - 1 || j1 == 0 || j1 == grid[0].length - 1) {
isHave = false;
}
if (i1 - 1 >= 0 && grid[i1 - 1][j1] == 0 && !isVisit[i1 - 1][j1]) {
queue.add(new ArrayList<>(Arrays.asList(i1 - 1, j1)));
}
if (i1 + 1 < grid.length && grid[i1 + 1][j1] == 0 && !isVisit[i1 + 1][j1]) {
queue.add(new ArrayList<>(Arrays.asList(i1 + 1, j1)));
}
if (j1 - 1 >= 0 && grid[i1][j1 - 1] == 0 && !isVisit[i1][j1 - 1]) {
queue.add(new ArrayList<>(Arrays.asList(i1, j1 - 1)));
}
if (j1 + 1 < grid[0].length && grid[i1][j1 + 1] == 0 && !isVisit[i1][j1 + 1]) {
queue.add(new ArrayList<>(Arrays.asList(i1, j1 + 1)));
}
}
}
}
5258. 得分最高的单词集合 显示英文描述
用户通过次数222
用户尝试次数247
通过次数227
提交次数385
题目难度Hard
你将会得到一份单词表 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] 只包含小写的英文字母。
这个题啊,乍一看,好像挺难,其实也就一般,我才做了1个小时·········。
private int[] hash;
private int sco = 0;
private int max = 0;
private HashMap<String, Integer> map;
public int maxScoreWords(String[] words, char[] letters, int[] score) {
hash = new int[150];
map = new HashMap<>();
for (char letter : letters) {
hash[letter] += 1;
}
for (int i = 0; i < words.length; i++) {
int s = 0;
for (int j = 0; j < words[i].length(); j++) {
s += score[words[i].charAt(j) - 'a'];
}
map.put(words[i], s);
}
backtrack(0, words, letters, score);
return max;
}
private void backtrack(int n, String[] words, char[] letters, int[] score) {
if (n >= words.length) {
max = Math.max(sco, max);
return;
}
for (int i = 0; i < 2; i++) {
if (i == 0) {
boolean ok = true;
for (int j = 0; j < words[n].length(); j++) {
hash[words[n].charAt(j)] -= 1;
if (hash[words[n].charAt(j)] < 0) {
ok = false;
}
}
if (ok) {
sco += map.get(words[n]);
backtrack(n + 1, words, letters, score);
sco -= map.get(words[n]);
}
for (int j = 0; j < words[n].length(); j++) {
hash[words[n].charAt(j)] += 1;
}
} else {
backtrack(n + 1, words, letters, score);
}
}
}
注意这个数据量啊
1 <= words.length <= 14
直接回溯就完事了,当然还是要做一点点优化的。
解题步骤如下: