1895 最大的幻方(暴力枚举)

1. 问题描述:

一个 k x k 的幻方指的是一个 k x k 填满整数的方格阵,且每一行、每一列以及两条对角线的和全部相等 。幻方中的整数不需要互不相同 。显然,每个 1 x 1 的方格都是一个幻方。
给你一个 m x n 的整数矩阵 grid ,请你返回矩阵中最大幻方的尺寸 (即边长 k)。

示例 1:

输入:grid = [[7,1,4,5,6],[2,5,1,6,4],[1,5,4,3,2],[1,2,7,3,4]]
输出:3
解释:最大幻方尺寸为 3 。
每一行,每一列以及两条对角线的和都等于 12 。
- 每一行的和:5+1+6 = 5+4+3 = 2+7+3 = 12
- 每一列的和:5+5+2 = 1+4+7 = 6+3+3 = 12
- 对角线的和:5+4+3 = 6+4+2 = 12

示例 2:

输入:grid = [[7,1,4,5,6],[2,5,1,6,4],[1,5,4,3,2],[1,2,7,3,4]]
输出:3
解释:最大幻方尺寸为 3 。
每一行,每一列以及两条对角线的和都等于 12 。
- 每一行的和:5+1+6 = 5+4+3 = 2+7+3 = 12
- 每一列的和:5+5+2 = 1+4+7 = 6+3+3 = 12
- 对角线的和:5+4+3 = 6+4+2 = 12

输入:grid = [[5,1,3,1],[9,3,3,1],[1,3,3,8]]
输出:2
提示:
m == grid.length
n == grid[i].length
1 <= m, n <= 50
1 <= grid[i][j] <= 10 ^ 6

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/largest-magic-square

2. 思路分析:

分析题目可以知道最容易想到的是暴力枚举,结合题目的数据范围m, n = 50,大概总的数据规模为:50 * (50 ^ 2) * (50 ^ 2) = 312500000,而且并不是每一次都是枚举50次的,所以应该是可以通过的。我们可以枚举长度为l, l - 1, l - 2...1的所有方阵,枚举的时候可以从由大到小的长度进行枚举,这样当我们找到满足的一个答案之后可以直接返回即可方阵的长度即可。最外层的循环表示当前方阵的长度,第二层循环表示从当前长度为l的方阵的起始行,第三层循环表示从当前长度为l的方阵的起始列,在枚举每一个长度为l的方阵中计算每一行的和,每一列的和,主对角线与副对角线的和,s1, s2计算方阵中每一行,每一列的和,其中需要设置当前方阵行与列的和是否满足条件的标记r_flag, c_flag用来判断行与列的和是否相等。主要是注意其中的细节问题。

3. 代码如下:

from typing import List


class Solution:
    def largestMagicSquare(self, grid: List[List[int]]):
        r, c = len(grid), len(grid[0])
        max_l = min(r, c)
        # 逆序遍历表示从大到小进行枚举
        for l in range(max_l, 0, -1):
            start_r, start_c = 0, 0
            while start_r + l <= r:
                start_c = 0
                while start_c + l <= c:
                    # 枚举每一个幻方, 设置两个标志r_flag, c_flag来判断当前方阵的行的和与列的和是否满足条件
                    r_flag, c_flag = True, True
                    r_s = -1
                    for j in range(start_r, start_r + l):
                        s1 = 0
                        for k in range(start_c, start_c + l):
                            s1 += grid[j][k]
                        if r_s == -1:
                            r_s = s1
                        elif r_s != s1:
                            r_flag = False
                            break
                    # 只有行的和满足条件才检查列的和
                    if r_flag:
                        c_s = -1
                        for k in range(start_c, start_c + l):
                            s2 = 0
                            for j in range(start_r, start_r + l):
                                s2 += grid[j][k]
                            if c_s == -1:
                                c_s = s2
                            elif c_s != s2:
                                c_flag = False
                                break
                        if s1 == s2 and c_flag:
                            t1, t2 = 0, 0
                            # 起始列位置
                            t_c = start_c
                            for j in range(start_r, start_r + l):
                                t1 += grid[j][t_c]
                                t_c += 1
                            # 起始行位置
                            t_r = start_r
                            for j in range(start_c + l - 1, start_c - 1, -1):
                                t2 += grid[t_r][j]
                                t_r += 1
                            # 只有当三者和相等的时候才满足条件
                            if s1 == t1 and t1 == t2:
                                return l
                    start_c += 1
                start_r += 1
        return 1

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值