杨辉三角
-
题目介绍
-
思路分析
- 首先我们需要了解杨辉三角是怎怎么形成的。如图所示,每一层的首尾数字都是1,剩余每个位置的数字都等于它的上一层对应位置的数字以及该位置前一个的数字的和。
- 所以我们可以用一个List存放每一层的数据,然后再用另一个List存放每一层即可。
-
相关代码片段
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> list = new ArrayList<List<Integer>>();
for (int i = 0; i < numRows; ++i) {
List<Integer> list1 = new ArrayList<Integer>();
for (int j = 0; j <= i; ++j) {
if (j == 0 || j == i) {
list1.add(1);
} else {
list1.add(list.get(i - 1).get(j - 1) + list.get(i - 1).get(j));
}
}
list.add(list1);
}
return list;
}
}
杨辉三角II
-
题目介绍
-
思路分析
- 这道题跟第一道题很相似,唯一不同的就是求的是杨辉三角具体的某一层的数据,且层数是从0开始记录的。
- 但根据进阶中的要求,我们不能像第一道题一样将杨辉三角的某一行之前的所有行的数据全部存储起来。根据杨辉三角的性质我们可以得到杨辉三角的某一行的数据起始直接取决于其上一行的数据,因此我们可以利用一个List只存放上一行的数据。
-
相关代码片段
class Solution {
public List<Integer> getRow(int rowIndex) {
List<Integer> list = new ArrayList<>();
for(int i = 0; i <= rowIndex; i++){
List<Integer> list1 = new ArrayList<>();
for(int j = 0; j <= i; j++){
if(j == 0 || j == i){
list1.add(1);
}else{
list1.add(list.get(j)+list.get(j-1));
}
}
list = list1;
}
return list;
}
}
图片平滑器
-
题目介绍
-
思路分析
- 根据题目我们知道是求二维数组中以每个数字为中心的九宫格的平均值,有点类似"扫雷"。
- 这道题恶心的地方在于对于边界的处理,因为边界中的有效数字的个数是随着矩阵的规模的变化而变化的,因此为了方便处理矩阵的边界,我们可以给已有的矩阵加一个新的边界,即将A[m][n]存入B[m+2][n+2]中。
- 然后我们分开考虑矩阵规模对边界的有效数字的影响。对于矩阵的四个顶点的元素而言,当矩阵的规模为1x1时,有效数字个数为1;规模为1xk或kx1时,有效数字个数为2;剩余规模的有效个数为4。对于矩阵四个边界除去顶点的元素而言,当矩阵的规模为1xk或kx1时,有效数字个数为4;其他规模的有效个数为6(不用考虑只有1个元素的情况)。剩余元素的有效个数即为9。
-
相关代码片段
class Solution {
public int[][] imageSmoother(int[][] img) {
int row = img.length;
int col = img[0].length;
int[][] sum = new int[row][col];
int[][] newImg = new int[row+2][col+2];
for(int i = 1; i < row+1;i++){
for(int j = 1; j < col + 1; j++){
newImg[i][j] = img[i-1][j-1];
}
}
for(int i = 1; i < row + 1; i++){
for(int j = 1; j < col + 1; j++){
sum[i-1][j-1] = (newImg[i-1][j-1]+newImg[i-1][j]+newImg[i-1][j+1]+
newImg[i][j-1]+newImg[i][j]+newImg[i][j+1]+
newImg[i+1][j-1]+newImg[i+1][j]+newImg[i+1][j+1]);
int k = 0;
if(i==1&&j==1||(i==1&&j==col)||(i==row&&j==1)||(i==row&&j==col)){
if(row == 1 && col == 1){
k = 1;
}else if(row == 1||col == 1){
k = 2;
}else{
k = 4;
}
}else if(i==1||i==row||j==1||j==col){
if(row == 1|| col == 1){
k = 3;
}else{
k = 6;
}
}else{
k = 9;
}
sum[i-1][j-1] /= k;
}
}
return sum;
}
}
范围求和
-
题目介绍
-
思路分析
- 首先题目的注意中已经给出了提示:m和n最大可以达到40000,对于一个二维数组而言正常情况下无法开到这么大。所以要考虑其他的"高效"的方法。
- 我们观察第一个例子可以看到:在两次操作中,第二次的操作范围覆盖了第一次,所以第一次的操作覆盖的范围即为最大元素的个数。根据此我们可以想到这道题的实质就是找所有操作的横坐标的最小值和纵坐标的最小值然后相乘,当然要注意当操作次数为0时,最大元素的个数为原来的所有数据。
-
相关代码片段
class Solution {
public int maxCount(int m, int n, int[][] ops) {
int res = m * n;
if(ops.length == 0){
return res;
}
int rmin = ops[0][0];
int cmin = ops[0][1];
for(int i = 0; i < ops.length;i++){
if(rmin > ops[i][0]){
rmin = ops[i][0];
}
if(cmin > ops[i][1]){
cmin = ops[i][1];
}
}
return rmin * cmin;
}
}
总结
本次总结的题目主要关于的是二维数组以及滚动数组,在解决二维数组的问题时,我们优先考虑的是对二维数组规模的估量以及对二维数组边界以及一些特殊条件的优先处理;滚动数组实质上体现的是一种递归的思想,根据前面的递归出后面的,层层相连。当然,题目本身还是很简单的,哈哈,,呜呜。。希望对大家有所收获!