二维数组及滚动数组 ——118、119、661、598、419

118.杨辉三角

解法一、这一列是上一列两两之和

其实第一反应是算组合数(顺便复习了一下高中数学)最后大输特输,23左右就开始狂乱溢出了,阶乘的爆炸级增长确实不容小觑

class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> res = new LinkedList<>();
        List<Integer> temp = new LinkedList<>();
        temp.add(1);
        res.add(temp);
        if(numRows == 1){
            return res;
        }
        for(int i = 1;i < numRows;i++){
            res.add(everyCombination(res.get(i - 1)));
        }
        return res;
    }
    public static List<Integer> everyCombination(List<Integer> temp){//每一层
        List<Integer> res = new LinkedList<>();
        int len = temp.size();
        res.add(1);
        for(int i = 0 ;i < len - 1;i++){
            res.add(temp.get(i) + temp.get(i+1));
        }
        res.add(1);
        return res;
    }

}
 

119.杨辉三角②

解法一、同上

就变个返回值交了一发,居然过了。当然为了空间复杂度考虑还是原数组变化比较好,尽量不开二维数组。

class Solution {
    public List<Integer> getRow(int rowIndex) {
        List<List<Integer>> res = new LinkedList<>();
        List<Integer> temp = new LinkedList<>();
        temp.add(1);
        res.add(temp);
        if(rowIndex == 0){
            return res.get(0);
        }
        for(int i = 1;i <= rowIndex;i++){
            res.add(everyCombination(res.get(i - 1)));
        }
        return res.get(rowIndex);
    }
    public static List<Integer> everyCombination(List<Integer> temp){//每一层
        List<Integer> res = new LinkedList<>();
        int len = temp.size();
        res.add(1);
        for(int i = 0 ;i < len - 1;i++){
            res.add(temp.get(i) + temp.get(i+1));
        }
        res.add(1);
        return res;
    }

}

 

解法二、找每行规律 

如下图(所以说去学高中数学了

class Solution {
    public static List<Integer> getRow(int rowIndex) {
        List<Integer> res = new ArrayList<>();
        res.add(1);
        for (int i = 1; i <= rowIndex; i++) {
                long cur = (long)res.get(i-1) * (rowIndex - i + 1) / i;
                res.add((int)cur);
        }
        return res;
    }
}

661.图片平滑器

解法一、暴力强解

先实现一个九格滑块,再考虑滑块是否在范围内比较好写(好过去区分三种情况,代码量比较麻烦)

class Solution {
    public int[][] imageSmoother(int[][] img) {
        int width = img[0].length;
        int longitudinal = img.length;
        int[][] ans = new int[longitudinal][width];
        for(int i = 0;i < longitudinal;i++){
            for(int j = 0;j < width;j++){
                ans[i][j] = floor(img,i,j);
            }
        }
        return ans;
    }
    public static int floor(int[][] img, int x, int y) {
        int sum = 0;
        int count = 0;

        for(int i = -1; i <= 1; i++) {
            for(int j = -1; j <= 1; j++) {
                int newX = x + i;
                int newY = y + j;

                if(newX >= 0 && newX < img.length && newY >= 0 && newY < img[0].length) {
                    sum += img[newX][newY];
                    count++;
                }
            }
        }

        return sum / count;
    }
}
解法二、前缀和

花了一段时间学习二维数组前缀和,原来是专门用来处理矩形区域求和问题的思想。

关键公式是sum[i][j] = sum[i-1][j] - sum[i][j-1] + img[i-1][j-1]

sum会大一圈,防止i-1和j-1越界。

class Solution {
    public int[][] imageSmoother(int[][] img) {
        int width = img[0].length;
        int longitudinal = img.length;
        int[][] sumArr = new int[longitudinal+1][width+1];
        for(int i = 1;i <= longitudinal;i++ ){
            for(int j = 1;j <= width;j++){
                sumArr[i][j] = sumArr[i-1][j] + sumArr[i][j-1]- sumArr[i-1][j-1] + img[i-1][j-1];
            }
        }
        for(int i = 0;i < longitudinal;i++){
            for(int j = 0; j < width;j++){
                int a = Math.max(0,i-1),b=Math.max(0,j-1);//(a,b)是i-1,j-1那个点
                int c = Math.min(longitudinal - 1,i+1),d = Math.min(width - 1,j+1);//(c,d)是i+1,j+1那个点
                int sum = sumArr[c+1][d+1] - sumArr[a][d+1] - sumArr[c+1][b] + sumArr[a][b];
                int num = (c - a + 1) * (d  - b + 1);
                img[i][j] = sum/num;
                
            }
        }
        return img;
    }
}

598.区间加法②

解法一、分析简化

读题,[0][0]到[ops[i][0]] [ops[i][1]]的部分会被+1,所以只有重叠的一块矩形区域会不断地堆叠,找最小值求每次操作交集面积即可

class Solution {
    public int maxCount(int m, int n, int[][] ops) {
        int min1 = m;
        int min2 = n;
        for(int i = 0;i < ops.length;i++){
            if(ops[i][0] < min1){
                min1 = ops[i][0];
            }
            if(ops[i][1] < min2){
                min2 = ops[i][1];
            }
        }
        return min1 * min2;
    }
}

 

419.棋盘上的战舰

 

解法一、统计起点

一开始就直接考虑了进阶。既然不修改board,则无法把已统计的战舰置为空位。所以,需要检查每个战舰的独特标识点。

选左上角为独特标识点(只会扫描一次,而且一艘战舰只有一个左上角,且最先统计到左上。当然,右上、左下、右上也可以)

class Solution {
    public int countBattleships(char[][] board) {
        int sum = 0;
        for(int i = 0;i < board.length;i++){
            for(int j = 0;j < board[0].length;j++){
                if(board[i][j] == 'X'){
                    if(i > 0 && board[i - 1][j] == 'X'){
                        continue;
                    }
                    if(j > 0 && board[i][j -1 ] == 'X'){
                        continue;
                    }
                    sum++;
                }
            }
        }
        return sum;
    }
}
 


碎碎念

  • 感觉最近写到的题都是思维比较活,算法要求不高
  • 高中数学技能up,如果实不上习可以去带数学家教(。
  • 这次真正理解了之前看到但是没学会的前缀和,在查询规模较大的时候,可以省略多次求和运算
  • 说来愧疚,我居然一直以为java没有int[][]这样的二维数组···(手有多生可见一斑)(这么菜都在坚持写力扣,给大家一点信心吧。。) 
  • 终于开始一天刷一个主题小合集啦
  • 11
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值