Day05 数组
最近开始准备工作了,发现自己真的是毫无准备,如果一切能重来的话,我就大二大三暑假出去实习了,现在简历上没有写的,秋招也错过了,如果今年不能出去实习,又找不到合适的计算机相关的工作,那我毕业可能只能先去打工了,唉,但是我并不后悔我放弃考研的决定(题解均来自leetcode网站)。07 重塑矩阵
2022/2/10
2022/10/11 复习
在 MATLAB 中,有一个非常有用的函数 reshape ,它可以将一个 m x n 矩阵重塑为另一个大小不同(r x c)的新矩阵,但保留其原始数据。
给你一个由二维数组 mat 表示的 m x n 矩阵,以及两个正整数 r 和 c ,分别表示想要的重构的矩阵的行数和列数。
重构后的矩阵需要将原始矩阵的所有元素以相同的 行遍历顺序 填充。
如果具有给定参数的 reshape 操作是可行且合理的,则输出新的重塑矩阵;否则,输出原始矩阵。
(java)
思路:判断是否能输出该矩阵,否则返回原始矩阵;我用了一个笨办法,将传入的矩阵转化为一维数组,再赋值给多维矩阵。
class Solution {
public int[][] matrixReshape(int[][] mat, int r, int c) {
int row = mat.length; //获取行数
int col = mat[0].length; //获取列数
if(row*col != r*c)
{
/*
if((r > row || r == row) && (c > col || c == col))
return mat;
return new int[0][0];
*/
return mat;
}
int[] storedMat = new int[row*col];
int count = 0;
/*
for(int[] x:mat)
for(int x1:x)
storedMat[count++] = x;
*/
for(int i=0;i<row;i++)
for(int j=0;j<col;j++)
storedMat[count++] = mat[i][j];
//System.out.print(mat[0][1]+" "+mat[1][0]+" "+count);
for(int i=0;i<count;i++)
System.out.print(i+" ");
for(int i=count-1;i>=0;i--)
System.out.print(i+" ");
int[][] newMat = new int[r][c];
for(int i=r-1;i>=0;i--){
for(int j=c-1;j>=0;j--){
newMat[i][j] = storedMat[--count];
}
}
return newMat;
}
}
用时56ms,击败了7.22%用户,可见时间和空间效率都很低。
题解:
相当于一维矩阵的映射,从m行n列到r行c列,满足关系式mn = rc则进行矩阵转换,否则返回原矩阵;
将二维数组 nums 映射成一个一维数组;将这个一维数组映射回 r 行 c 列的二维数组。
(其中通过取模和取余运算完成映射赋值问题)
class Solution {
public int[][] matrixReshape(int[][] nums, int r, int c) {
int m = nums.length;
int n = nums[0].length;
if (m * n != r * c) {
return nums;
}
int[][] ans = new int[r][c];
for (int x = 0; x < m * n; ++x) {
ans[x / c][x % c] = nums[x / n][x % n];
}
return ans;
}
}
08 杨辉三角
2021/12/30
2022/10/11 复习
给定一个非负整数 numRows,生成「杨辉三角」的前 numRows 行。
在「杨辉三角」中,每个数是它左上方和右上方的数的和。
(java)
思路:思路很简单,每一次循环,读取上一次存储的list子列表temp的值,若是首和尾则向子列表中添加1,否则添加temp[i-1]+temp[i]的值,最后将子列表添加到总list中。
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> listA = new ArrayList<>();
List<Integer> listB = new ArrayList<>();
int count = 1;
for(int i=0;i<numRows;i++){
//int[] addList = new int[count];
//若listA中存在数据
if(!listA.isEmpty()){
//需取上一个子列表进行赋值,清空当前子列表中数据
listB.clear();
List<Integer> temp = listA.get(i-1);
for(int j=0;j<count;j++){
if(j==0 || j==count-1)
listB.add(1);
else{
listB.add(temp.get(j-1)+temp.get(j));
}
}
}else{
listB.add(1);
}
//添加list子列表
listA.add(listB);
count ++;
}
return listA;
}
}
解答错误,显示list中总是超出下标,但是实际测试,发现temp这个子列表无法通过listA.get(i)语句进行赋值操作。
题解:
(1)每个数字等于上一行的左右两个数字之和;第n行第i个数等于第n-1行的第i-1个数和第i个数之和
class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> listA = new ArrayList<List<Integer>>();
for(int i=0;i<numRows;i++){
//int[] addList = new int[count];
//若listA中存在数据
/*if(!listA.isEmpty()){
for(int j=0;j<=i;j++){
if(j==0 || j==i)
listB.add(1);
else{
//需取上一个子列表进行赋值
listB.add(listA.get(i-1).get(j-1)+listA.get(i-1).get(j));
}
}
}else{
listB.add(1);
}*/
List<Integer> listB = new ArrayList<>();
for(int j=0;j<=i;j++){
if(j==0 || j==i)
listB.add(1);
else{
//需取上一个子列表进行赋值
listB.add(listA.get(i-1).get(j-1)+listA.get(i-1).get(j));
}
}
//添加list子列表
listA.add(listB);
}
return listA;
}
}
草稿
改进后的程序如下,依然报错,经过调试后发现,listB中数组在clear()一次后,其基本容量依然为1,第二次add()中,listB中值为[1,null],即add()两次,list作为子对象时,无法扩容class Solution {
public List<List<Integer>> generate(int numRows) {
List<List<Integer>> listA = new ArrayList<>();
//List<Integer> listB = new ArrayList<>();
for(int i=0;i<numRows;i++){
//int[] addList = new int[count];
List<Integer> listB = new ArrayList<>();
//若listA中存在数据
if(!listA.isEmpty()){
//需取上一个子列表进行赋值,清空当前子列表中数据
listB.clear();
//List<Integer> temp = listA.get(i-1);
for(int j=0;j<i+1;j++){
if(j==0 || j==i)
listB.add(1);
else{
listB.add(listA.get(i-1).get(j-1)+listA.get(i-1).get(j));
}
}
}else{
listB.add(1);
}
//添加list子列表
listA.add(listB);
}
return listA;
}
}