【解题报告】《九日集训》(第七天)

语言:C++

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

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

给你一个 m * n 的矩阵 grid,矩阵中的元素无论是按行还是按列,都以非递增顺序排列。

请你统计并返回 grid负数 的数目。

示例 1:

输入:grid = [[4,3,2,-1],[3,2,1,-1],[1,1,-1,-2],[-1,-1,-2,-3]]
输出:8
解释:矩阵中共有 8 个负数。

遍历+累加

class Solution
{
public:
    int countNegatives(vector<vector<int>>& grid)
    {
        int tmp = 0;
        for (auto n:grid)
        {
            for (auto m : n)
            {
                if (m < 0)
                {
                    tmp++;
                }
            }
        }
        return tmp;
    }
};

二分

class Solution
{
public:
	int countNegatives(vector<vector<int>>& grid)
	{
		int num = 0;
		for (auto x : grid)
		{
			int left = 0;
			int right = x.size() - 1;
			int mid;
			int pos = -1;
			while (left <= right)
			{
				mid = left + (right - left) / 2;
				if (x[mid] < 0)
				{
					pos = mid;
					right = mid - 1;
				}
				else 
					left = mid + 1;
			}
			if (pos!=-1) 
				num += x.size() - pos;// pos=-1表示这一行全是>=0的数,不能统计
		}
		return num;
	}
};

逆序查找1

class Solution
{
public:
	int countNegatives(vector<vector<int>>& grid)
	{
		int num = 0;
		int m = grid[0].size();
		int pos = grid[0].size() - 1;
		for (auto x : grid)
		{
			int i;
			for (i = pos; i >= 0; --i)
			{
				if (x[i] >= 0)
				{
					if (i + 1 < m)
					{
						pos = i + 1;
						num += m - pos;
					}
					break;
				}
			}
			if (i == -1)//此行全负
			{
				num += m;
				pos = -1;
			}
		}
		return num;
	}
};

逆序查找2

class Solution
{
public:
	int countNegatives(vector<vector<int>>& grid)
	{
		int cnt = 0;
		int N = grid[0].size() - 1;
		int pos = N;

		for (int i = 0; i < grid.size(); ++i)
		{
			// 从pos开始向左找到第一个非小于0的数,pos保存,下一行从pos开始找
			while (pos >= 0 && grid[i][pos] < 0)
			{
				--pos;
			}
			cnt += N - pos;
		}
		return cnt;
	}
};

1572. 矩阵对角线元素的和

1572. 矩阵对角线元素的和

给你一个正方形矩阵 mat,请你返回矩阵对角线元素的和。

请你返回在矩阵主对角线上的元素和副对角线上且不在主对角线上元素的和。

示例 1:

img

输入:mat = [[1,2,3],
[4,5,6],
[7,8,9]]
输出:25
解释:对角线的和为:1 + 5 + 9 + 3 + 7 = 25
请注意,元素 mat[1][1] = 5 只会被计算一次。

矩阵遍历:找到对角线的 i、j 规律即可

(看了题解发现我这属于逐行取数)

class Solution
{
public:
	int diagonalSum(vector<vector<int>>& mat)
	{
		int tmp = 0;
		for (int i = 0, j = 0; i < mat[0].size(); ++i, ++j)
		{
			tmp += mat[i][i] + mat[j][mat[0].size() - 1 - j];
		}
		if (mat[0].size() & 1)
		{
			tmp -= mat[mat[0].size() / 2][mat[0].size() / 2];
		}
		return tmp;
	}
};

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

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

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

客户的 资产总量 就是他们在各家银行托管的资产数量之和。最富有客户就是 资产总量 最大的客户。

示例 1:

输入:accounts = [[1,2,3],[3,2,1]]
输出:6
解释:
第 1 位客户的资产总量 = 1 + 2 + 3 = 6
第 2 位客户的资产总量 = 3 + 2 + 1 = 6
两位客户都是最富有的,资产总量都是 6 ,所以返回 6 。

遍历累加

简直有毒,把三目运算符换为fmax,效率直接提升一倍

class Solution
{
public:
	int maximumWealth(vector<vector<int>>& accounts)
	{
		int max = INT_MIN;
		for (auto n : accounts)
		{
			int tmp = 0;
			for (auto m : n)
			{
				tmp += m;
			}
			//max = tmp > max ? tmp : max;
            max = fmax(max, tmp);
		}
		return max;
	}
};

766. 托普利茨矩阵

766. 托普利茨矩阵

给你一个 m x n 的矩阵 matrix 。如果这个矩阵是托普利茨矩阵,返回 true ;否则,返回 false

如果矩阵上每一条由左上到右下的对角线上的元素都相同,那么这个矩阵是 托普利茨矩阵

示例 1:

img

输入:matrix = [[1,2,3,4],[5,1,2,3],[9,5,1,2]]
输出:true
解释:
在上述矩阵中, 其对角线为:
“[9]”, “[5, 5]”, “[1, 1, 1]”, “[2, 2, 2]”, “[3, 3]”, “[4]”。
各条对角线上的所有元素均相同, 因此答案是 True 。

遍历 判断

class Solution
{
public:
	bool isToeplitzMatrix(vector<vector<int>>& matrix)
	{
		int m = matrix.size();
		int n = matrix[0].size();
		for (int i = 0; i < m - 1; ++i)
		{
			for (int j = 0; j < n - 1; ++j)
			{
				if (matrix[i][j] != matrix[i + 1][j + 1])
					return false;
			}
		}
		return true;
	}
};

1380. 矩阵中的幸运数

1380. 矩阵中的幸运数

给你一个 m * n 的矩阵,矩阵中的数字 各不相同 。请你按 任意 顺序返回矩阵中的所有幸运数。

幸运数是指矩阵中满足同时下列两个条件的元素:

  • 在同一行的所有元素中最小
  • 在同一列的所有元素中最大

示例 1:

输入:matrix = [[3,7,8],[9,11,13],[15,16,17]]
输出:[15]
解释:15 是唯一的幸运数,因为它是其所在行中的最小值,也是所在列中的最大值。

居然没超时

遍历遍历遍历

先保存i行中最小数的列数tmpj,再去遍历该列中的最大数的行数tmpk,判断tmpk与i的关系,一致则说明是幸运数

class Solution
{
public:
    vector<int> luckyNumbers(vector<vector<int>>& matrix)
    {
        int min = INT_MAX;
        int max = INT_MIN;
        int tmpj,tmpk;
        vector<int>arr;
        for (int i=0;i<matrix.size();++i)
        {
            min = INT_MAX;
            max = INT_MIN;
            for (int j = 0; j < matrix[0].size(); ++j)
            {
                if (matrix[i][j] < min)
                {
                    tmpj = j;
                    min = matrix[i][j];
                }
            }
            for (int k = 0; k < matrix.size(); ++k)
            {
                if (matrix[k][tmpj]> max)
                {
                    tmpk = k;
                    max = matrix[k][tmpj];
                }
            }
            if (tmpk == i)
                arr.push_back(min);
        }
        return arr;
    }
};

1582. 二进制矩阵中的特殊位置

1582. 二进制矩阵中的特殊位置

给你一个大小为 rows x cols 的矩阵 mat,其中 mat[i][j]01,请返回 矩阵 *mat* 中特殊位置的数目

特殊位置 定义:如果 mat[i][j] == 1 并且第 i 行和第 j 列中的所有其他元素均为 0(行和列的下标均 从 0 开始 ),则位置 (i, j) 被称为特殊位置。

示例 1:

输入:mat = [[1,0,0],
[0,0,1],
[1,0,0]]
输出:1
解释:(1,2) 是一个特殊位置,因为 mat[1][2] == 1 且所处的行和列上所有其他元素都是 0

和1380题一个套路

遍历遍历遍历

先保存i行中唯一1的列数tmpj,再去遍历该列中的唯一1的行数tmpk,判断tmpk与i的关系,一致则说明是特殊位置

class Solution
{
public:
    int numSpecial(vector<vector<int>>& mat)
    {
        int sum1 = 0;
        int sum2 = 0;
        int tmpj,tmpk;
        int num = 0;
        for (int i = 0; i < mat.size(); ++i)
        {
            sum1 = 0;
            tmpj = -1;
            for (int j = 0; j < mat[0].size(); ++j)
            {
                if (mat[i][j])
                {
                    if (sum1 == 0)
                    {
                        tmpj =j;
                        sum1++;
                    }
                    else
                    {
                        tmpj = -1;
                        break;
                    }
                }
            }
            if (tmpj!=-1)
            {
                tmpk = -1;
                sum2 = 0;
                for (int k = 0; k < mat.size(); ++k)
                {
                    if (mat[k][tmpj])
                    {
                        if (sum2 == 0)
                        {
                            tmpk = k;
                            sum2++;
                        }
                        else
                        {
                            tmpk = -1;
                            break;
                        }
                    }
                }
                if (tmpk ==i)
                {
                    num++;
                }
            }
        }
        return num;
    }
};

463. 岛屿的周长

463. 岛屿的周长

给定一个 row x col 的二维网格地图 grid ,其中:grid[i][j] = 1 表示陆地, grid[i][j] = 0 表示水域。

网格中的格子 水平和垂直 方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。

岛屿中没有“湖”(“湖” 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。

示例 1:

img

输入:grid = [[0,1,0,0],[1,1,1,0],[0,1,0,0],[1,1,0,0]]
输出:16
解释:它的周长是上面图片中的 16 个黄色的边

算是个找规律题,所有的1* 4 - 所有的1(右邻1 +下邻1)* 2

class Solution
{
public:
	int islandPerimeter(vector<vector<int>>& grid)
	{
		int sum = 0;
		int tmp = 0;
		for (int i = 0; i < grid.size(); ++i)
		{
			for (int j = 0; j < grid[0].size(); ++j)
			{
				if (grid[i][j])
				{
					sum++;
				}
				if (grid[i][j] && (i + 1 < grid.size() && grid[i + 1][j]))
				{
					tmp++;
				}
				if (grid[i][j] && (j + 1 < grid[0].size() && grid[i][j + 1]))
				{
					tmp++;
				}
			}
		}
		return sum * 4 - tmp * 2;
	}
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值