目标子矩阵的数量| 豆包MarsCode AI 刷题

119 阅读5分钟
目标子矩阵的数量

小M最近在研究矩阵,他对矩阵中的子矩阵很感兴趣。给定一个矩阵 matrix 和一个日标值target,他的任务是找到所有总和等于日标值的非空了知阵的数量。

子矩阵通过选择矩阵的某个矩形区域定义,形式为(x1,y1,x2,y2),其中(x1,y1)表示左上角的坐标,(x2,y2)表示右下角的坐标。一个子矩阵包含短阵中所有位于这个矩形区域内的单元格。如果两个子短阵的坐标不同(如 x1 != x1'或 y1 != y1'),则这两个子短阵被认为是不同的。

你需要返回满足条件的子矩阵数量。

测试样例

样例1:

输入:matrix=[[-1,1,0],[1,1,1],[0,1,0]] ,target = @输出:7

样例2:

输入:matrix=[[-1,-1],[-1,1]],target = 0

输出:2

样例3:

输入:matrix=[[-1,2,3],[4,5,6],[7,8,9]],target = 10

输出:2

解题思路
  1. 初始化变量
    • rows:矩阵的行数。
    • cols:矩阵的列数。
    • count:用于记录满足条件的子矩阵数量。
  1. 外层循环 (x1y1):确定子矩阵的左上角坐标。
    • x1 从 0 到 rows-1,表示子矩阵可能的起始行。
    • y1 从 0 到 cols-1,表示子矩阵可能的起始列。
  1. 内层循环 (x2y2):确定子矩阵的右下角坐标。
    • x2x1rows-1,表示子矩阵可能的结束行,必须大于等于 x1
    • y2y1cols-1,表示子矩阵可能的结束列,必须大于等于 y1
  1. 计算子矩阵的和
    • 使用列表推导式 sum(matrix[i][j] for i in range(x1, x2+1) for j in range(y1, y2+1)) 来计算当前子矩阵的元素和。
    • 这个列表推导式会遍历子矩阵中的所有元素,并将它们相加。
  1. 判断和是否等于目标值
    • 如果计算出的子矩阵和等于 target,则 count 加一。
  1. 返回结果
    • 循环结束后,返回 count,即满足条件的子矩阵数量。

算法复杂度

  • 时间复杂度:O(n^4),其中 n 是矩阵的边长。这是因为我们有两层循环来确定子矩阵的起始点(x1, y1),另外两层循环来确定子矩阵的结束点(x2, y2)。
  • 空间复杂度:O(1),除了输入矩阵外,我们只需要常数级别的额外空间来存储计数器和循环变量。

性能考虑

  • 这个算法在小矩阵上运行良好,但对于大矩阵,由于其高时间复杂度,可能会非常慢。
  • 在实际应用中,可能需要更高效的算法,如使用前缀和、哈希表或其他数据结构来优化子矩阵和的计算。

优化思路

  • 可以使用前缀和数组来减少计算子矩阵和的时间,将时间复杂度降低到 O(n^3)。
  • 可以使用哈希表来存储已经计算过的子矩阵和,以避免重复计算,这可能会进一步优化性能
代码实现
def solution(matrix: list, target: int) -> int:
    rows = len(matrix)
    cols = len(matrix[0])
    count = 0

    for x1 in range(rows):
        for y1 in range(cols):
            for x2 in range(x1, rows):
                for y2 in range(y1, cols):
                    current_sum = sum(matrix[i][j] for i in range(x1, x2+1) for j in range(y1, y2+1))
                    if current_sum == target:
                        count += 1

    return count

if __name__ == '__main__':
    print(solution(matrix=[[-1, 1, 0], [1, 1, 1], [0, 1, 0]], target=0) == 7)
    print(solution(matrix=[[-1, -1], [-1, 1]], target=0) == 2)
    print(solution(matrix=[[-1, 2, 3], [4, 5, 6], [7, 8, 9]], target=10) == 2)
出现最多的质数判断

给定一个由小写字母组成的字符串s,要求统计每个字符出现的次数,并判断出现次数最多的字符的出现次数是否为质数。如果是质数,则输出“YES”,否则输出“NO”。

以下步骤进行:

  1. 字符频率统计:遍历字符串,使用一个字典(或哈希表)来记录每个字符出现的次数。
  2. 找出最大频率:在字典中找到出现次数最多的字符及其次数。
  3. 质数判断:编写一个函数来判断一个数是否为质数。
  4. 输出结果:根据最大频率是否为质数,输出 "YES" 或 "NO"。

下面是具体的解答思路:

步骤1: 字符频率统计

  • 初始化一个空字典 frequency
  • 遍历字符串 s 中的每个字符 char
  • 对于每个字符,如果它不在 frequency 字典中,添加它并设置其计数为1。
  • 如果它已经在字典中,将其计数加1。

步骤2: 找出最大频率

  • 初始化两个变量 max_countmax_char 来存储出现次数最多的字符及其次数。
  • 遍历 frequency 字典,比较每个字符的计数,更新 max_countmax_char

步骤3: 质数判断

  • 编写一个函数 is_prime(n) 来判断一个数 n 是否为质数。
  • 如果 n 小于2,返回 False
  • 从2到 sqrt(n)(包括2),检查 n 是否能被任何数整除。如果能,返回 False
  • 如果没有找到除数,返回 True

步骤4: 输出结果

  • 使用 is_prime 函数检查 max_count 是否为质数。
  • 如果是,输出 "YES";否则,输出 "NO"。
代码实现
from collections import Counter
from math import sqrt

def is_prime(num):
    """判断一个数是否为质数"""
    if num <= 1:
        return False
    for i in range(2, int(sqrt(num)) + 1):
        if num % i == 0:
            return False
    return True

def solution(s: str) -> str:
    # 统计每个字符出现的次数
    count = Counter(s)
    # 找到出现次数最多的字符的次数
    max_count = max(count.values())
    # 判断这个次数是否为质数
    if is_prime(max_count):
        return "YES"
    else:
        return "NO"

if __name__ == '__main__':
    print(solution("abccckjskw") == "YES")
    print(solution("qwqwtttqqttttt") == "NO")
    print(solution("aabbbccddd") == "YES")
    print(solution("xyzzzz") == "NO")
    print(solution("mmnnooo") == "YES")