LeetCode C++刷题 73-76题题解

73、矩阵置零

题目:

给定一个 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) 的额外空间,但这仍然不是最好的解决方案。
你能想出一个常数空间的解决方案吗?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/set-matrix-zeroes
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解:

三种方法,空间复杂度分别是

1、O(MN)

2、O(M+N)

3、O(2)

完整代码:

class Solution {
public:
    // //1、O(mn)空间
    // void setZeroes(vector<vector<int>>& matrix)
    // {
        
    //     int m = matrix.size();
    //     int n = matrix[0].size();

    //     //保存标志
    //     vector<vector<int>> flag(m, vector<int>(n, 1));

    //     for(int i = 0; i < m; i++) {
    //         for(int j = 0; j < n; j++) {
    //             //若当前值为0,则设置行和列的标志位为0
    //             if(matrix[i][j] == 0) {
    //                 setZero(matrix, flag, i, j);
    //             } else if(flag[i][j] == 0) {
    //                 matrix[i][j] = 0;
    //             }
    //         }
    //     }
    // }

    // void setZero(vector<vector<int>>& matrix, vector<vector<int>>& flag, int i, int j) 
    // {
    //     int top = 0;
    //     while(top < i) {
    //         matrix[top][j] = 0;
    //         top++;
    //     }

    //     int left = 0;
    //     while(left < j) {
    //          matrix[i][left] = 0;
    //          left++;
    //     }

    //     int bottom = flag.size() - 1;
    //     while(bottom > i) {
    //         flag[bottom][j] = 0;
    //         bottom--;
    //     }

    //     int right = flag[0].size() - 1;
    //     while(right > j) {
    //          flag[i][right] = 0;
    //          right--;
    //     }
    // }

    // //2、O(m + n)空间
    // void setZeroes(vector<vector<int>>& matrix)
    // {
        
    //     int m = matrix.size();
    //     int n = matrix[0].size();

    //     //保存标志
    //     vector<int> row;
    //     vector<int> col;

    //     for(int i = 0; i < m; i++) {
    //         for(int j = 0; j < n; j++) {
    //             //若当前值为0,则设置行和列的标志位为0
    //             if(matrix[i][j] == 0) {
    //                 row.push_back(i);
    //                 col.push_back(j);
    //             } 
    //         }
    //     }

    //     for(int i = 0; i < m; i++) {
    //         for(int j = 0; j < n; j++) {
    //             //若当前值为0,则设置行和列的标志位为0
    //             if(count(row.begin(), row.end(), i) > 0 || count(col.begin(), col.end(), j) > 0) {
    //                 matrix[i][j] = 0;
    //             } 
    //         }
    //     }

    // }

    //3、O(1)空间
    void setZeroes(vector<vector<int>>& matrix)
    {
        int m = matrix.size();
        int n = matrix[0].size();
        int row_flag = false;   // 用于保存第一行是否有0
        int col_flag = false;   // 用于保存第一列是否有0
        // 判断第一行是否有0
        for(int j = 0; j < n; j++) {
            if(matrix[0][j] == 0) {
                row_flag = true;
            }
        }
        //判断第一列是否有0
        for(int i = 0; i < m; i++) {
            if(matrix[i][0] == 0) {
                col_flag = true;
            } 
        }

        //除第一行、第一列外,若当前值为0,则设置行和列的标志位为0
        for(int i = 1; i < m; i++) {
            for(int j = 1; j < n; j++) {
                if(matrix[i][j] == 0) {
                    matrix[i][0] = 0;
                    matrix[0][j] = 0;
                } 
            }
        }

        // 将第一行值为0的设置所在列为0
        for(int j = 1; j < n; j++) {
            if(matrix[0][j] == 0) {
                for(int i = 0; i < m; i++) {
                    matrix[i][j] = 0;
                }
            } 
        }

        // 将第一列值为0的设置所在行为0
        for(int i = 1; i < m; i++) {
            if(matrix[i][0] == 0) {
                for(int j = 0; j < n; j ++) {
                    matrix[i][j] = 0;
                }
            } 
        }

        //若row_flag为true,设置第一行的值为0
        if(row_flag) {
            for(int j = 0; j < n; j ++) {
                matrix[0][j] = 0;
            }
        }

        //若col_flag为true,设置第一列的值为0
        if(col_flag) {
            for(int i = 0; i < m; i++) {
                matrix[i][0] = 0;
            }
        }
    }
};

74、搜索二维矩阵

题目:

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

每行中的整数从左到右按升序排列。
每行的第一个整数大于前一行的最后一个整数。
示例 1:

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

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-a-2d-matrix
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解:

二分

完整代码:

class Solution {
public:
    bool searchMatrix(vector<vector<int>>& matrix, int target) 
    {
        
        int m = matrix.size();     // 行数
         if(m == 0) {
            return false;
        }
        int n = matrix[0].size();  //列数
        
        int l = 0;
        int r = m * n - 1;
        // 二分查找
        while(l <= r) {
            int mid = (l + r) / 2;
            int i = mid / n;
            int j = mid % n;
            if(matrix[i][j] == target) {
                return true;
            } else if(matrix[i][j] < target) {
                l = mid + 1;
            } else {
                r = mid - 1;
            }
        }

        return false;
    }
};

75、颜色分类

题目:

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

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

注意:
不能使用代码库中的排序函数来解决这道题。

示例:

输入: [2,0,2,1,1,0]
输出: [0,0,1,1,2,2]
进阶:

一个直观的解决方案是使用计数排序的两趟扫描算法。
首先,迭代计算出0、1 和 2 元素的个数,然后按照0、1、2的排序,重写当前数组。
你能想出一个仅使用常数空间的一趟扫描算法吗?

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sort-colors
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解:

一次遍历

完整代码:

class Solution {
public:
    void sortColors(vector<int>& nums) {
        int l = 0;
        int r = nums.size() - 1;

        int i = 0;

        while(i <= r) {
            if(nums[i] == 0) {
                swap(nums[i], nums[l]);
                i++; // 换过来的值肯定不是0或者2,所以i++
                l++;
            } else if(nums[i] == 2) {
                swap(nums[i], nums[r]);
                r--;
            } else {
                i++;
            }
            
        }
        
    }
};

76、最小覆盖子串

题目:

给你一个字符串 S、一个字符串 T 。请你设计一种算法,可以在 O(n) 的时间复杂度内,从字符串 S 里面找出:包含 T 所有字符的最小子串。

 

示例:

输入:S = "ADOBECODEBANC", T = "ABC"
输出:"BANC"
 

提示:

如果 S 中不存这样的子串,则返回空字符串 ""。
如果 S 中存在这样的子串,我们保证它是唯一的答案。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-window-substring
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

题解:

滑动窗口

完整代码:

// 滑动窗口,两个指针,1个用于延伸,另一个用于收缩
class Solution {
private:
    unordered_map<char, int> ori, idx; // 用于存储字符串中每个字符的个数
public:
    //用于判断是否满足要求
    bool check()
    {
        for(const auto &s: ori) {
            if(idx[s.first] < s.second) {
                return false;
            }
        }
        return true;
    }

    string minWindow(string s, string t) 
    {
        
        for(auto str: t) {
           ori[str]++;
        }
        int l = 0;
        int r = 0;
        int len = INT_MAX;
        int l_len = -1;

        while(r < s.size()) {
            if(ori.find(s[r]) != ori.end()) {
                idx[s[r]] ++;
            }

            while(check() && l <= r) {
                if(r - l + 1 < len) {
                    len = r - l + 1;
                    l_len = l;
                }

                if(ori.find(s[l]) != ori.end()) {
                    idx[s[l]] --;
                }

                l++;
            }
            r++;
        }

        return l_len == -1 ? "" : s.substr(l_len, len);

    }
};

 

CC 公众号: hw_cchang CSDN认证博客专家 C++/Go后台
微信公众号:编程技术与生活(hw_cchang)
软件工程本硕毕业于武汉大学,现就职于某大厂。
从事过Java Web、Android、CV、深度学习开发,现主要从事CPP/Go后台开发。
©️2020 CSDN 皮肤主题: 数字20 设计师:CSDN官方博客 返回首页
实付 19.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值