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[][]这样的二维数组···(手有多生可见一斑)(这么菜都在坚持写力扣,给大家一点信心吧。。)
- 终于开始一天刷一个主题小合集啦