栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

五月训练 Day11

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

五月训练 Day11

文章目录
    • 0. Leetcode [1351. 统计有序矩阵中的负数](https://leetcode.cn/problems/count-negative-numbers-in-a-sorted-matrix/)
      • 分析与解答
    • 1. Leetcode [1672. 最富有客户的资产总量](https://leetcode.cn/problems/richest-customer-wealth/)
      • 分析与解答
    • 2. Leetcode [832. 翻转图像](https://leetcode.cn/problems/flipping-an-image/)
      • 分析与解答
    • 3. Leetcode [1329. 将矩阵按对角线排序](https://leetcode.cn/problems/sort-the-matrix-diagonally/)
      • 分析与解答
    • 总结

0. Leetcode 1351. 统计有序矩阵中的负数

给你一个 m * n 的矩阵 grid,矩阵中的元素无论是按行还是按列,都以非递增顺序排列。 请你统计并返回 grid 中 负数 的数目。

分析与解答

解法1
遍历矩阵,计算满足条件的元素数量

class Solution {
public:
    int countNegatives(vector>& grid) {
        int m = grid.size(); // 行数
        int n = grid[0].size(); // 列数
        int result(0);
        for (int i = 0; i < m; ++i) {
            for (int j = 0; j < n; ++j) {
                if (grid[i][j] < 0) {
                    result += 1;
                }
            }
        }
        
        return result;
    }
};

该方法没有利用已有条件,直接遍历矩阵,算法时间复杂度为 O ( m n ) O(mn) O(mn),其中 m , n m,n m,n 为矩阵的行数与列数
解法2
由于矩阵行列均为非递增,因此可以逆序查找,减少时间复杂度。对行从后向前查找,对列从前向后查找,若位置 grid[i, j] > 0,由列元素的非递增性可知,grid[i-1, j] > 0,即对第 i - 1 行,查找时的列表记可从第 i 行中满足 grid[i, j] < 0 的最小 j 开始:

class Solution {
public:
    int countNegatives(vector>& grid) {
        int m = grid.size(); // 行数
        int n = grid[0].size(); // 列数
        int result(0), k(0);
        // 利用元素非递增的特性,m 从下往上扫描,n 从前往后扫描
        for (int i = m - 1; i >= 0; --i) {
            for (int j = k; j < n; ++j) {
                if (grid[i][j] < 0) { // 找到当前行第一个小于 0 的元素,后续元素均小于 0
                    result += n - k;
                    break;
                } else {
                    k++;
                }
            }
        }
        
        return result;
    }
};

由于复用了上一次搜索的列号,因此复杂度为 O ( m + n ) O(m+n) O(m+n)

当然,在查找时也可以用二分法,加快搜索当前行元素的速度

1. Leetcode 1672. 最富有客户的资产总量

给你一个 m x n 的整数网格 accounts ,其中 accounts[i][j] 是第 i​​​​​​​​​​​​ 位客户在第 j 家银行托管的资产数量。返回最富有客户所拥有的 资产总量 。
客户的 资产总量 就是他们在各家银行托管的资产数量之和。最富有客户就是 资产总量 最大的客户。

分析与解答

根据题意,求矩阵的最大行和即可。遍历矩阵每一行,对改行元素求和,记录最大值:

class Solution {
public:
    int maximumWealth(vector>& accounts) {
        int result(0);
        for (int i = 0; i < accounts.size(); ++i) {
            int cur(0);
            for (int j = 0; j < accounts[i].size(); ++j) { // 求第 i 行的元素和
                cur += accounts[i][j];
            }
            if (result < cur) { // 更新最大行和
                result = cur;
            }
        }
        
        return result;
    }
};

算法时间复杂度为 O ( m n ) O(mn) O(mn)

2. Leetcode 832. 翻转图像

给定一个 n x n 的二进制矩阵 image ,先 水平 翻转图像,然后 反转 图像并返回 结果 。
水平翻转图片就是将图片的每一行都进行翻转,即逆序。
例如,水平翻转 [1,1,0] 的结果是 [0,1,1]。
反转图片的意思是图片中的 0 全部被 1 替换, 1 全部被 0 替换。
例如,反转 [0,1,1] 的结果是 [1,0,0]。

分析与解答

依题意,遍历每一行,将每列中位置为 [ i , j ] [i,j] [i,j] 的元素与位置为 [ i , n − j − 1 ] [i, n - j - 1] [i,n−j−1] 的元素交换即可,其中 n n n 为矩阵列数:

class Solution {
public:
    vector> flipAndInvertImage(vector>& image) {
        vector> result;
        int r = image.size();
        int c = image[0].size();
        result.resize(r);
        for (int i = 0; i < r; ++i) {
            result[i].resize(c);
        }
        
        for (int i = 0; i < r; ++i) { // 遍历每一行
            for (int j = 0; j < c / 2 + 1; ++j) { // 只需遍历一半列下标即可
                result[i][j] = !image[i][c - 1 - j];
                result[i][c - 1 - j] = !image[i][j];
            }
        }
        
        return result;
    }
};

算法时间复杂度为 O ( m n ) O(mn) O(mn)

3. Leetcode 1329. 将矩阵按对角线排序

矩阵对角线 是一条从矩阵最上面行或者最左侧列中的某个元素开始的对角线,沿右下方向一直到矩阵末尾的元素。例如,矩阵 mat 有 6 行 3 列,从 mat[2][0] 开始的 矩阵对角线 将会经过 mat[2][0]、mat[3][1] 和 mat[4][2] 。
给你一个 m * n 的整数矩阵 mat ,请你将同一条 矩阵对角线 上的元素按升序排序后,返回排好序的矩阵。
提示:
m == mat.length
n == mat[i].length
1 <= m, n <= 100
1 <= mat[i][j] <= 100

分析与解答

按顺序取出每条对角线上的元素,排序后再依次放回即可。这里由于元素范围有限,因此选择直接用基数排序。当然,也可放入新数组后使用其它排序算法。

class Solution {
public:
    vector> diagonalSort(vector>& mat) {
        int rNum = mat.size();
        int cNum = mat[0].size();
        // 排列上三角
        for (int j = 0; j < cNum; ++j) {
            vector num;
            num.resize(101, 0);
            // 搜索对角线,这里首元素行列 +1 即可得到对角线元素
            int r(0), c(j);
            while (r < rNum && c < cNum) { // 注意边界判断,任何一个到头即结束
                num[mat[r][c]]++;
                r++;
                c++;
            }
            
            // 按顺序向对角线填入排序后元素
            r = 0;
            c = j;
            int numIdx(0);
            while (r < rNum && c < cNum) {
                while (num[numIdx] == 0) { // 跳过没有的元素
                    numIdx++;
                }
                mat[r][c] = numIdx;
                num[numIdx]--; // 填入元素后更新相应元素数量
                r++;
                c++;
            } 
        }
        
        // 排列下三角
        for (int i = 0; i < rNum; ++i) {
            vector num;
            num.resize(101, 0);
            // 搜索对角线
            int r(i), c(0);
            while (r < rNum && c < cNum) {
                num[mat[r][c]]++;
                r++;
                c++;
            }
            
            // 按顺序填入元素
            r = i;
            c = 0;
            int numIdx(0);
            while (r < rNum && c < cNum) {
                while (num[numIdx] == 0) {
                    numIdx++;
                }
                mat[r][c] = numIdx;
                num[numIdx]--;
                r++;
                c++;
            } 
        }
        return mat;
    }
};
总结

涉及到矩阵的算法中弄清下标是最重要的,当你弄清下标之后一切都尽在掌握之中。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/875661.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号