LeetCode 73矩阵置零&74搜素二维矩阵&75颜色分类

简介: 给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。

矩阵置零



题目描述:


给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。


示例 1:


输入: 
[
  [1,1,1],
  [1,0,1],
  [1,1,1]
]
输出: 
[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]


示例 2:


输入: 
[
  [0,1,2,0],
  [3,4,5,2],
  [1,3,1,5]
]
输出: 
[
  [0,0,0,0],
  [0,4,5,0],
  [0,3,1,0]
]


进阶:


一个直接的解决方案是使用 O(mn) 的额外空间,但这并不是一个好的解决方案。

一个简单的改进方案是使用 O(m + n) 的额外空间,但这仍然不是最好的解决方案。

你能想出一个常数空间的解决方案吗?


分析:


这道题可谓是一波三折,对于O(m*n)的方法不谈了,没啥好讲了。


从O(m+n)的方法说起,一维空间,只要出现0,那么这一行或者这一列就全部变成0,那么就可以用两个boolean数组解决,一个标记行,一个标记列,遍历的时候遇到0就把该行和该列标记为true。最终根据两个boolean数组进行赋值即可。


实现代码为:


class Solution {
    public void setZeroes(int[][] matrix) {
        boolean hang[]=new boolean[matrix.length];
        boolean lie[]=new boolean[matrix[0].length];
        for (int i=0;i<matrix.length;i++)
        {
            for(int j=0;j<matrix[i].length;j++)
            {
                if(matrix[i][j]==0) {
                    hang[i] = true;
                    lie[j] = true;
                }
            }
        }
        for(int i=0;i<hang.length;i++)
        {
            if(hang[i])
            {
                for(int j=0;j<lie.length;j++)
                {
                    matrix[i][j]=0;
                }
            }
        }
        for(int j=0;j<lie.length;j++)
        {
            if(lie[j])
            {
                for(int i=0;i<hang.length;i++)
                {
                    matrix[i][j]=0;
                }
            }
        }
    }
}


题目有说到要使用常数级别的额外空间,而这种情况就要考虑空间的复用!这个就想了一下谈谈我的想法:


这题的核心问题是在根据行或者列遍历的时候不能第一次遇到就把改行和列置零,说说我的错误想法:


  • 第一趟按行遍历,遇到0那么将这一行所有数据特殊的标记起来。 我首先想到的是除0以外标记成负数。
  • 第二趟按列遍历,遇到0直接将该列置为0(行已经遍历过)。遇到负数的时候置为0.


如果所有数据是正数,那么这是可行的,但是很可疑测试数据有负数,over。。


后来又想逃巧将所有数据换成int的最大值或者最小值,但是不幸的是测试有这两组数据,把我卡的死死的。


后来只能先用枚举的方法找到一个数组中不存在的数,因为二维数组是有大小范围int [m][n]的,所以在[1,m*n+1] 范围内一定有一个不存在的数可以作为临时标记。


第二趟按照列遍历,遇到0直接将该列置为0(行已经遍历过)。遇到标记的那个数将那个位置数字为0.


20201129184113437.png


实现代码为:


class Solution {
    public void setZeroes(int[][] matrix) {
         boolean jud=false;//
        int num=1;
        //找到一个合适的数字用于临时替换
        for(int q=1;q<matrix.length*matrix[0].length+2;q++)
        {
            jud=false;
            outer:
            for (int i=0;i<matrix.length;i++)
            {
                for(int j=0;j<matrix[i].length;j++)
                {
                    if(matrix[i][j]==q) {
                        jud=true;
                        break outer;
                    }
                }
            }
           if(!jud)
           {
               num=q;break;
           }
        }
        //遍历行
        for (int i=0;i<matrix.length;i++)
        {
            for(int j=0;j<matrix[i].length;j++)
            {
                if(matrix[i][j]==0)
                {
                    for(int q=0;q<matrix[0].length;q++)
                    {
                        if(matrix[i][q]!=0)
                        matrix[i][q]=num;
                    }
                    break;
                }
            }
        }
        for(int j=0;j<matrix[0].length;j++)//列
        {
            for (int i=0;i<matrix.length;i++)
            {
                if(matrix[i][j]==0)
                {
                    for(int q=0;q<matrix.length;q++)
                    {
                        matrix[q][j]=0;
                    }
                    break;
                }
                if(matrix[i][j]==num)
                    matrix[i][j]=0;
            }
        }
    }
}


搜素二维矩阵



编写一个高效的算法来判断 m x n 矩阵中,是否存在一个目标值。该矩阵具有如下特性:


每行中的整数从左到右按升序排列。

每行的第一个整数大于前一行的最后一个整数。


示例 1:


20201129162448358.png


输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,50]], target = 3
输出:true


示例 2:


20201129162459767.png


输入:matrix = [[1,3,5,7],[10,11,16,20],[23,30,34,50]], target = 13
输出:false


示例 3:


输入:matrix = [], target = 0
输出:false


提示:


m == matrix.length
n == matrix[i].length
0 <= m, n <= 100
-104 <= matrix[i][j], target <= 104


分析:


这题可以根据数据进行两次二分,第一次二分对第一列找到对应的行,第二次对对应的行进行二分找到对应的位置。


具体代码为:


class Solution {
    public boolean searchMatrix(int[][] matrix, int target) {
        if(matrix.length==0||matrix[0].length==0)return false;
     //先对第一行进行二分定位到该列
     if(matrix[0][0]>target) return false;
     int l=0,r=matrix.length;
     while (l<r) {
      int mid=(l+r)/2;
      if(matrix[mid][0]==target)
        return true;
      if(matrix[mid][0]<target)
      {
        l=mid+1;
      }
      else {
        r=mid;
      }
    }
    int index=l-1;
    l=0;r=matrix[0].length;
    while (l<r) {
      int mid=(l+r)/2;
      if(matrix[index][mid]==target)
        return true;
      if(matrix[index][mid]<target)
      {
        l=mid+1;
      }
      else {
        r=mid;
      }
    }    
     return false;      
    }
}


颜色分类



给定一个包含红色、白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。


此题中,我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。


进阶:

你可以不使用代码库中的排序函数来解决这道题吗?

你能想出一个仅使用常数空间的一趟扫描算法吗?


示例 1:


输入:nums = [2,0,2,1,1,0]
输出:[0,0,1,1,2,2]


示例 2:


输入:nums = [2,0,1]
输出:[0,1,2]


示例 3:


输入:nums = [0]
输出:[0]


示例 4:


输入:nums = [1]
输出:[1]


提示:


n == nums.length
1 <= n <= 300
nums[i] 为 0、1 或 2


分析:


方法比较灵活,可以用双指针,一个在左,一个在右,遍历的时候遇到0和2分别分配在左侧和右侧。


具体实现可用一个left,right标记左右往中间扩散,left左侧都是0,right右侧都是2,遍历的时候遇到需要交换的则交换,和快排的思想有些相似。


20201129190007772.png


实现代码:


class Solution {
    public void sortColors(int[] nums) {
         int left=0;
     int right=nums.length-1;
     for(int i=0;i<right+1;i++)
     {
       if(nums[i]==0)
       {
         int team=nums[left];
         nums[left++]=0;
         nums[i]=team;
       }
       else if(nums[i]==2)
       {
         int team=nums[right];
         nums[right--]=2;
         nums[i]=team;
         i--;
       }     
     }
    }
}


结语



原创不易,bigsai请你帮两件事帮忙一下:


  1. star支持一下, 您的肯定是我在平台创作的源源动力。
  2. 微信搜索「bigsai」,关注我的公众号,不仅免费送你电子书,我还会第一时间在公众号分享知识技术。加我还可拉你进力扣打卡群一起打卡LeetCode。


目录
相关文章
|
3月前
|
算法 搜索推荐
LeetCode第75题颜色分类
文章介绍了LeetCode第75题"颜色分类"的解法,通过双指针技术对数组中的0、1和2进行排序,避免了传统的排序算法,提供了一种时间复杂度为O(n)的高效解决方案。
LeetCode第75题颜色分类
|
3月前
|
存储 算法 NoSQL
LeetCode第73题矩阵置零
文章介绍了LeetCode第73题"矩阵置零"的解法,通过使用矩阵的第一行和第一列作为标记来记录哪些行或列需要置零,从而在不增加额外空间的情况下解决问题。
LeetCode第73题矩阵置零
|
1月前
|
算法 C++
Leetcode第59题(螺旋矩阵2)
这篇文章介绍了解决LeetCode第59题“螺旋矩阵II”的算法,通过C++编程实现按顺时针顺序填充一个n x n的正方形矩阵。
16 0
|
3月前
|
算法
LeetCode第74题搜索二维矩阵
文章讲解了LeetCode第74题"搜索二维矩阵"的解决方案,利用二分搜索法将问题简化,并通过数学转换找到二维矩阵中的对应元素,展示了将二维问题转化为一维问题的解题技巧。
LeetCode第74题搜索二维矩阵
|
3月前
|
算法 Java
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
LeetCode经典算法题:矩阵中省份数量经典题目+三角形最大周长java多种解法详解
52 6
|
3月前
|
算法 Python
【Leetcode刷题Python】 LeetCode 2038. 如果相邻两个颜色均相同则删除当前颜色
本文介绍了LeetCode 2038题的解法,题目要求在一个由'A'和'B'组成的字符串中,按照特定规则轮流删除颜色片段,判断Alice是否能够获胜,并提供了Python的实现代码。
51 3
|
3月前
|
算法 JavaScript Python
【Leetcode刷题Python】79. 单词搜索和剑指 Offer 12. 矩阵中的路径
Leetcode第79题"单词搜索"的Python解决方案,使用回溯算法在给定的二维字符网格中搜索单词,判断单词是否存在于网格中。
42 4
|
3月前
|
算法 Python
【Leetcode刷题Python】73. 矩阵置零
本文介绍了LeetCode第73题的解法,题目要求在给定矩阵中将所有值为0的元素所在的行和列全部置为0,并提供了一种原地算法的Python实现。
32 0
【Leetcode刷题Python】73. 矩阵置零
|
3月前
|
算法 Python
【Leetcode刷题Python】74. 搜索二维矩阵
两种解决LeetCode "搜索二维矩阵" 问题的方法的Python实现。第一种方法是从二维矩阵的右上角开始线性搜索,通过比较当前元素与目标值来决定搜索方向。第二种方法是将二维矩阵视为一维数组进行二分查找,通过计算中间元素的行列索引来更新搜索区间。两种方法都旨在高效地判断目标值是否存在于给定的有序二维矩阵中。
39 0
|
3月前
|
Python
【Leetcode刷题Python】75. 颜色分类
在不使用sort函数的情况下对包含红色、白色和蓝色元素的数组进行排序的方法:插入排序法和单指针交换法,并提供了相应的Python实现代码。
16 0