奇数值单元格的数目 | 重构 2 行二进制矩阵 | 统计封闭岛屿的数目 | 得分最高的单词集合 | LeetCode 周赛第 162 场 JAVA 实现「162」

1252. 奇数值单元格的数目

给你一个 nm 列的矩阵,最开始的时候,每个单元格中的值都是 0
另有一个索引数组 indicesindices[i] = [ri, ci] 中的 rici 分别表示指定的行和列(从 0 开始编号)。
你需要将每对 [ri, ci] 指定的行和列上的所有单元格的值加 1
请你在执行完所有 indices 指定的增量操作后,返回矩阵中 「奇数值单元格」 的数目。

示例 1

[ 0 0 0   0 0 0 ] > [ 1 2 1   0 1 0 ] > [ 1 3 1   1 3 1 ] \left[ \begin{matrix} 0&0&0 \\\ 0&0&0 \end{matrix} \right] -> \left[ \begin{matrix} 1 & 2 & 1 \\\ 0 & 1 & 0 \end{matrix} \right] -> \left[ \begin{matrix} 1 & 3 & 1 \\\ 1 & 3 & 1 \end{matrix} \right]

输入: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

[ 0 0   0 0 ] > [ 0 1   1 2 ] > [ 2 2   2 2 ] \left[ \begin{matrix} 0 & 0 \\\ 0 & 0 \end{matrix} \right] -> \left[ \begin{matrix} 0 & 1 \\\ 1 & 2 \end{matrix} \right] -> \left[ \begin{matrix} 2 & 2 \\\ 2 & 2 \end{matrix} \right]

输入: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

解题思路

  1. 循环索引数组,计算每行每列出现的次数并保存
  2. 循环矩阵,单元格行列出现次数的和即为该单元格的值。
    • 判断每个位置的值是否为奇数,计算总和

题解 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 行二进制矩阵

给你一个 2n 列的二进制数组:

  • 矩阵是一个二进制矩阵,这意味着矩阵中的每个元素不是 0 就是 1
  • 0 行的元素之和为 upper
  • 1 行的元素之和为 lower
  • 第 i 列(从 0 开始编号)的元素之和为 colsum[i]colsum 是一个长度为 n 的整数数组。

你需要利用 upperlowercolsum 来重构这个矩阵,并以二维整数数组的形式返回它。

如果有多个不同的答案,那么任意一个都可以通过本题。

如果不存在符合要求的答案,就请返回一个空的二维数组。

示例 1

输入:upper = 2,lower = 1,colsum = [111]
输出:[ [110][001] ]
解释:[ [101][010] ][ [011][100] ] 也是正确答案。

示例 2

输入:upper = 2,lower = 3,colsum = [2211]
输出:[ ]

示例 3

输入:upper = 5, lower = 5, colsum = [2120101201]
输出:[ [1110100100][1010001101] ]

提示

  • 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 中赋值方式:

  1. colsum[n] = 0,矩阵 1 矩阵 2 第 n 位的值为 0
  2. colsum[n] = 0,矩阵 1 矩阵 2 第 n 位的值为 1
  3. 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);
}
发布了7 篇原创文章 · 获赞 3 · 访问量 316

猜你喜欢

转载自blog.csdn.net/sl285720967/article/details/103135032
今日推荐