二维数组专题

1.力扣48旋转图像

旋转图像:顺时针旋转图像90度

step1.先将这个n*n矩阵按照对角线(从左上角到右下角的对角线,而非从右上角到左下角的对角线)进行对称。比如第一行经过对称就变成第一列

 沿对角线对称的代码:

       for(int i=0;i<n;i++)
        {
            for(int j=i;j<n;j++)
            {
                int temp=nums[i][j];
                nums[i][j]=nums[j][i];
                nums[j][i]=temp;
            }
        }

这里之所以 j 从 i 开始,表示的是蓝色线那部分(每一行的对角线元素和对角线元素右边的那部分元素)

step2:再对矩阵的每一行进行反转

比如第一行是1,5,7,4,经过反转就变成了4,7,5,1

 经过这两步发现矩阵已经顺时针旋转90度了

代码实现如下:

class Solution 
{
    public void rotate(int[][] nums) 
    {
        //这道题要求是原地旋转,不能用另一个新的矩阵在装旋转后的矩阵
        //求出这个方形矩阵的边长(长和宽相等)
        int n=nums.length;
        
        //第一步:先沿对角线进行对称
        for(int i=0;i<n;i++)
        {
            for(int j=i;j<n;j++)
            {
                int temp=nums[i][j];
                nums[i][j]=nums[j][i];
                nums[j][i]=temp;
            }
        }

        //第二步:每一行进行对称
        //取出这个matric矩阵的每一行
        for(int i=0;i<n;i++)
        {
            int p=0,q=n-1;
            while(p<q)
            {
              int temp=nums[i][p];
              nums[i][p]=nums[i][q];
              nums[i][q]=temp;
              p++;
              q--;
            }
        }
    }
}

2.力扣54  螺旋矩阵

按照顺时针的顺序返回二维数组中的所有元素

class Solution 
{
    public List<Integer> spiralOrder(int[][] nums)
    {
        int m=nums[0].length; //矩阵长度
        int n=nums.length;//矩阵宽度

        //定义四个边界
        //注意这里m,n的位置不要写反了,很容易出错                                                                                  
        int left=0; //左边界在第几列
        int right=m-1; //右边界在第几列
        int up=0; //上边界在第几行
        int down=n-1;//下边界在第几行

        List<Integer> result=new ArrayList();
        
        //把m*n个元素全部添加到result
        while(result.size()<m*n)
        {
            //要求是顺时针旋转,所以依次添加上边界,右边界,下边界,左边界的数

            //添加上边界的数
            if(up<=down)
            {
                for(int temp=left;temp<=right;temp++)
                {
                    result.add(nums[up][temp]);
                }
                //上边界下移
                up++;
            }

          //添加右边界的数
            if(left<=right)
            {
                for(int temp=up;temp<=down;temp++)
                {
                    result.add(nums[temp][right]);
                }
                //右边界左移
                right--;
            }
            
            //添加下边界的数
            if(up<=down)
            {
                for(int temp=right;temp>=left;temp--)
                {
                    result.add(nums[down][temp]);
                }
                //下边界上移
                down--;
            }

            //添加左边界的数
            if(left<=right)
            {
                for(int temp=down;temp>=up;temp--)
                {
                    result.add(nums[temp][left]);
                }
                //左边界右移
                left++;
            }
        }
        return result;
    }
}

3.59. 螺旋矩阵 II - 力扣(LeetCode)

生成螺旋矩阵

 用up,down,left,right来标记上下左右边界

初始时候:up=0,down=n-1,left=0,right=n-1;

按照先从左到右,然后从上到下,然后从右到左,然后从下到上                                                                

 从左到右完,上边界就要下移,+1

从上到下完,右边界就要左移,-1

从右到左完,下边界就要上移,-1

从下到上完,左边界就要左移,+1

 还有一个问题是:nums[i][j]  怎么确定二维数组的两个下标是多少,也就是如何确定现在填数填到哪里了,填的都是边界上的位置

比如你 从左到右,那一定是上边界不动,然后i在移动,然后上边界下移+1

从上到下,一定是右边界不动,然后i在移动,然后右边界左移-1

从右到左,一定是下边界不懂,然后i在移动,然后下边界-1

从下到上,一定是左边界不懂,然后i在移动,然后左边界+1

class Solution {
    public int[][] generateMatrix(int n) {
        int[][] nums=new int[n][n];
        int up=0,down=n-1,left=0,right=n-1;

        int count=1;
        while(count<=n*n)
        {
            for(int i=left;i<=right;i++)//左到右
            {
                nums[up][i]=count;
                count++;
            }
            up++;//上边界往下移

            for(int i=up;i<=down;i++)//上到下
            {
                nums[i][right]=count;
                count++;
            }
            right--;//右边界往左移

            for(int i=right;i>=left;i--)//右到左
            {
                nums[down][i]=count;
                count++;
            }
           down--; //下边界上移

            for(int i=down;i>=up;i--)//下到上
            {
                nums[i][left]=count;
                count++;
            }
            left++;//左边界右移

        }
        return nums;
    

    }
}

 而荣耀的笔试题几乎完全一样

在nxn方阵里填入1,2,.,nxn,要求填成蛇形。元素1从右上角开始,顺时针排列,例如,n=4时

 只需要改变一下遍历顺序就可以,遍历顺序由

先从左到右,然后从上到下,然后从右到左,然后从下到上         

变成:

然后从上到下,然后从右到左,然后从下到上,再从左到右

只需要将上面的代码顺序调换一下就行

public class test4
{
    public static void main(String[] args) {

        Scanner scanner=new Scanner(System.in);
        int n=scanner.nextInt();
        int[][] nums=new int[n][n];
        int up=0,down=n-1,left=0,right=n-1;

        int count=1;
        while(count<=n*n) {


            for (int i = up; i <= down; i++)//上到下
            {
                nums[i][right] = count;
                count++;
            }
            right--;//右边界往左移

            for (int i = right; i >= left; i--)//右到左
            {
                nums[down][i] = count;
                count++;
            }
            down--; //下边界上移

            for (int i = down; i >= up; i--)//下到上
            {
                nums[i][left] = count;
                count++;
            }
            left++;//左边界右移

            for (int i = left; i <= right; i++)//左到右
            {
                nums[up][i] = count;
                count++;
            }
            up++;//上边界往下移

        }

        for(int i=0;i<n;i++)
        {
            for (int j = 0; j < n; j++) {
                System.out.print(nums[i][j]+" ");
            }
            System.out.println();
        }

    }
}

4.力扣2022 将一维数组转变成二维数组

class Solution 
{
    public int[][] construct2DArray(int[] original, int m, int n) 
    {
        if(original.length!=m*n)
        {
            int[][] result=new int[0][0];
            return result;
        }
        
        int[][]  result=new int[m][n];

        int index=0;

        for(int i=0;i<m;i++)
        {
            for(int j=0;j<n;j++)
            {
               result[i][j]=original[index];
               index++;

               //或者这里可以这样写:result[i][j]=original[i*n+j];一行有n个元素
               //这里也可以不用两重循环,而是一重循环,遍历original数组
               /*for(int i=0;i<original.length;i++)
                 {
                    res[i/n][i%n] = original[i];
                 }
               */
        }
        return result;
    }
}

5.力扣240 搜索二维数组||

从最左下角的数开始:

如果target比这个数小,就去这个数的上面(比这个数小的区域找)

如果target比这个数大 ,就去这个数的右边(比这个数大的区域找)

终止条件就是索引超出边界

class Solution 
{
    public boolean searchMatrix(int[][] nums, int target)
    {
        int m=nums.length;
        //这里可能需要判断一下m是否等于0,因为下面有nums[0],如果nums数组的长度为0,就不存在nums[0]
        int n=nums[0].length;
        
        //从左下角开始出发
        int x=m-1;
        int y=0;

        //横坐标最小为0,纵坐标最大为n-1
        while(x>=0&&y<=n-1)
        {
            //比target小,那就去右边更大的区域找
            if(nums[x][y]<target)
            {
               y++;
            }
            //比target大,就往上面更小的区域找
            else if(nums[x][y]>target)
            {
               x--;
            }
            else
            {
                return true;
            }
        }
        return false;
    }
}

或者是从右上角出发(但是不能从左上角和右下角出发)

 这道题也可以在每一行中用二分查找

6.返回最多1的是哪一行

这个二维矩阵的特点是每一行左边全0,右边全1

从第一行的最后一个元素出发,一直往左移动,找到第一个不为1的数为止,记录下此时最多1的个数为4,行数为0

然后此时直接横坐标+1,纵坐标不变去下一行

6. 力扣 2482  求差值矩阵

class Solution
{
   //给定一个1-0矩阵,求差值矩阵
   //每个位置的值等于:行1的个数+列1的个数-行0的个数-列0的个数
   //改写成行1的个数-行0的个数+列1的个数-列0的个数
   //=行1的个数-(列数-行1的个数)+列1的个数-(行数-列1的个数)
   //=2*行1的个数-列数+2*列1的个数-行数
   public int[][] onesMinusZeros(int[][] grid)
   {
       int n=grid.length;//行数
       int m=grid[0].length;//列数

       
       //求出每一行1的个数:
       int[] nums1=new int[n];
       //求出每一列1的个数
       int[]  nums2=new int[m];

       for(int i=0;i<n;i++)
       {
           int sum=0;
           for(int j=0;j<m;j++)
           {
               if(grid[i][j]==1)
               {
                   sum++;
               }
           }
           nums1[i]=sum;
       }
       
       for(int i=0;i<m;i++)
       {
           int sum=0;
           for(int j=0;j<n;j++)
           {
               if(grid[j][i]==1)
               {
                   sum++;
               }
           }
           nums2[i]=sum;
       }

       int[][] result=new  int[n][m];
       for(int i=0;i<n;i++)
       {
           for(int j=0;j<m;j++)
           {
               //第i行第j列=行1的个数-行0的个数+列1的个数-列0的个数=2*行1的个数-列数+2*列1的个数-行数
               result[i][j]=2*nums1[i]+2*nums2[j]-m-n;
           }
       }
       
       return  result;
   }
}

简化代码:

class Solution
{
   //给定一个1-0矩阵,求差值矩阵
   //每个位置的值等于:行1的个数+列1的个数-行0的个数-列0的个数
   //改写成行1的个数-行0的个数+列1的个数-列0的个数
   //=行1的个数-(列数-行1的个数)+列1的个数-(行数-列1的个数)
   //=2*行1的个数-列数+2*列1的个数-行数
   public int[][] onesMinusZeros(int[][] grid)
   {
       int n=grid.length;//行数
       int m=grid[0].length;//列数

       
       //求出每一行1的个数:
       int[] nums1=new int[n];
       //求出每一列1的个数
       int[]  nums2=new int[m];

       for(int i=0;i<n;i++)
       {
           for(int j=0;j<m;j++)
           {
               if(grid[i][j]==1)
               {
                   nums1[i]++;
                   nums2[j]++;
               }
           }
       }
       
    

       int[][] result=new  int[n][m];
       for(int i=0;i<n;i++)
       {
           for(int j=0;j<m;j++)
           {
               //第i行第j列=行1的个数-行0的个数+列1的个数-列0的个数=2*行1的个数-列数+2*列1的个数-行数
               result[i][j]=2*nums1[i]+2*nums2[j]-m-n;
           }
       }
       
       return  result;
   }
}

  • 2
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值