力扣刷题-数组-螺旋矩阵

news2024/11/18 1:38:02

模拟过程,但却十分考察对代码的掌控能力。
重点:循环不变量原则!
第一条原则:
模拟顺时针画矩阵的过程:

  • 填充上行从左到右
  • 填充右列从上到下
  • 填充下行从右到左
  • 填充左列从下到上

由外向内一圈一圈这么画下去。
第二条原则:
左闭右开原则!
这里一圈下来,我们要画每四条边,这四条边怎么画,每画一条边都要坚持一致的左闭右开,或者左开右闭的原则,这样这一圈才能按照统一的规则画下来。
image.png
这里每一种颜色,代表一条边,我们遍历的长度,可以看出每一个拐角处的处理规则,拐角处让给新的一条边来继续画。这也是坚持了每条边左闭右开的原则。

59.螺旋矩阵II

给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
image.png
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]

class Solution(object):
    def generateMatrix(self, n):
        """
        :type n: int
        :rtype: List[List[int]]
        """
        # 螺旋矩阵 重点考察代码能力 不涉及算法
        # 遇到判断循环边界的题目 要遵循 循环不变量 1. 上下行 左右列的遍历原则 2. 左闭右开原则
        result = [[0]*n for _ in range(n)]
        startx ,starty = 0, 0 # 起始位置 因为一般是循环里面用i j 
        loop = n // 2 # 循环个数 需要转几个圈
        mid = n // 2 # 若n为奇数 需要单独处理中间的一个数 result[mid][mid]
        offset = 1 # 第一圈offset当然为1 下一圈需要再加1 offset目的就是保持左闭右开原则
        count = 1 # 计数 就是每个位置填充的数

        # 开始循环
        while loop > 0:
            i = startx # 对于不同循环 每次起始的x y 不一样
            j = starty
            # 上行 左闭右开
            for j in range(starty, n-offset):
                result[startx][j] = count
                count += 1

            j += 1
            # 右列
            for i in range(startx, n-offset):
                result[i][j] = count
                count += 1
            i += 1
            # 下行
            while j > starty:
                result[i][j] = count
                count += 1
                j -= 1
            # 左列
            while i > startx:
                result[i][j] = count
                count += 1
                i -= 1
            
            loop -= 1 # 循环数减1
            offset += 1 # offset加1

            startx += 1
            starty += 1
        
        if n %2 :
            result[mid][mid] = count

        return result

54.螺旋矩阵

给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
示例 1:(方阵)
image.png
输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
示例 2:
image.png
输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]
解题:
与59.螺旋矩阵II相同的是:两者都是模拟矩形的顺时针旋转,所以核心依然是依然是坚持循环不变量,按照左闭右开的原则
与59.螺旋矩阵II不同的是:前题中的螺旋矩阵是正方形,只有正方形的边长n一个边界条件,而本题中,需要考虑长方形的长和宽(m行和n列)两个边界条件。自然,m可以等于n,即前题可视为本题在m==n的特殊情况。
我们从最一般的情况开始考虑,与59.螺旋矩阵II题解对比起来,m和n的带入,主要引来两方面的差异:

  • **loop的计算: **本题的loop计算与59.螺旋矩阵II算法略微差异,因为存在rows和columns两个维度,可自行分析,loop只能取min(rows, columns),例如rows = 5, columns = 7,那loop = 5 / 7 = 2
  • mid的计算及填充: 1、同样的原理,本题的mid计算也存在上述差异; 2、 如果min(rows, columns)为偶数,则不需要在最后单独考虑矩阵最中间位置的赋值 如果min(rows, columns)为奇数,则矩阵最中间位置不只是[mid][mid],而是会留下来一个特殊的中间行或者中间列,具体是中间行还是中间列,要看rows和columns的大小,如果rows > columns,则是中间列,相反,则是中间行

可以自己举例画图分析。

class Solution(object):
    def spiralOrder(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[int]
        """
        m = len(matrix) # 行数
        n = len(matrix[0]) # 列数
        result = []
        if m == n: # 当矩阵为方阵时
            startx, starty = 0, 0
            offset = 1
            loop = n // 2
            mid = n // 2
            while loop:
                i = startx
                j = starty
                # 上行
                for j in range(starty, n-offset):
                    result.append(matrix[startx][j])
                j += 1
                # 右列
                for i in range(startx, n-offset):
                    result.append(matrix[i][j])
                i += 1
                # 下行
                while j > starty:
                    result.append(matrix[i][j])
                    j -= 1
                # 左列
                while i > startx:
                    result.append(matrix[i][j])
                
                loop -= 1
                offset += 1

                startx += 1
                starty += 1
            
            if n % 2:
                result.append(matrix[mid][mid])
        # m与n不等 则loop循环数量为 min(m,n) // 2 并且如果min(m,n)为奇数 则不再是中间位置 而可能是留下一行或者一列
        if m != n:
            startx, starty = 0, 0
            offset = 1
            loop = min(m ,n ) // 2
            mid = min(m, n) // 2
            while loop:
                i = startx
                j = starty
                for j in range(starty, starty+n-offset): # 注意是startx+n-offset
                    result.append(matrix[startx][j])
                j += 1
                for i in range(startx, startx+m-offset):
                    result.append(matrix[i][j])
                i += 1
                while j > starty:
                    result.append(matrix[i][j])
                    j -= 1
                while i > startx:
                    result.append(matrix[i][j])
                    i -= 1
                
                loop -= 1
                offset += 2 # 注意这里要加2 因为外圈遍历完后,再遍历内圈,内圈的矩阵行和列相比外圈都少了两个长度

                startx += 1
                starty += 1
            # 处理额外的行/列数据
            if min(m,n)%2:
                if m>n: # 那就是额外的列
                    for i in range(mid, mid+m-n+1):
                        result.append(matrix[i][mid])
                else:
                    for j in range(mid, mid+n-m+1):
                        result.append(matrix[mid][j])
        return result

其实可以不用分:

class Solution(object):
    def spiralOrder(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[int]
        """
        m = len(matrix) # 行数
        n = len(matrix[0]) # 列数
        result = []
        # if m == n: # 当矩阵为方阵时
        #     startx, starty = 0, 0
        #     offset = 1
        #     loop = n // 2
        #     mid = n // 2
        #     while loop:
        #         i = startx
        #         j = starty
        #         # 上行
        #         for j in range(starty, n-offset):
        #             result.append(matrix[startx][j])
        #         j += 1
        #         # 右列
        #         for i in range(startx, n-offset):
        #             result.append(matrix[i][j])
        #         i += 1
        #         # 下行
        #         while j > starty:
        #             result.append(matrix[i][j])
        #             j -= 1
        #         # 左列
        #         while i > startx:
        #             result.append(matrix[i][j])
                
        #         loop -= 1
        #         offset += 1

        #         startx += 1
        #         starty += 1
            
        #     if n % 2:
        #         result.append(matrix[mid][mid])
        # m与n不等 则loop循环数量为 min(m,n) // 2 并且如果min(m,n)为奇数 则不再是中间位置 而可能是留下一行或者一列
        startx, starty = 0, 0
        offset = 1
        loop = min(m ,n ) // 2
        mid = min(m, n) // 2
        while loop:
            i = startx
            j = starty
            for j in range(starty, starty+n-offset): # 注意是startx+n-offset
                result.append(matrix[startx][j])
            j += 1
            for i in range(startx, startx+m-offset):
                result.append(matrix[i][j])
            i += 1
            while j > starty:
                result.append(matrix[i][j])
                j -= 1
            while i > startx:
                result.append(matrix[i][j])
                i-=1
                
            loop -= 1
            offset += 2 # 注意这里要加2 因为外圈遍历完后,再遍历内圈,内圈的矩阵行和列相比外圈都少了两个长度

            startx += 1
            starty += 1
        # 处理额外的行/列数据
        if min(m,n)%2:
            if m>n: # 那就是额外的列
                for i in range(mid, mid+m-n+1):  # 注意是mid
                    result.append(matrix[i][mid])
            else: # 那就是额外的行
                for j in range(mid, mid+n-m+1):
                    result.append(matrix[mid][j])
        return result

重点在于考虑到m!=n时候如何判断循环圈数,以及什么时候要考虑循环完毕之后剩余的元素,以及如何处理。

参考:https://programmercarl.com/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1032677.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【探索Linux世界|中秋特辑】--- 倒计时和进度条的实现与演示

个人主页:兜里有颗棉花糖 欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 兜里有颗棉花糖 原创 收录于专栏【Linux专栏】🎈 本专栏旨在分享学习Linux的一点学习心得,欢迎大家在评论区讨论💌 演示环境&#xff1…

PageHelp插件在复杂sql下引起的Having无法识别错误及其解决方案

1: 问题出现的场景 系统中有一个复杂SQL内嵌套了多个子查询.在改动时需要将SQL的最后一行加上having来做额外的过滤处理. 添加完having语句后发现SQL能够正常执行就直接将代码提交到了测试环境.结果在测试环境报错Unknown column ‘xxx‘ in ‘having clause. 2: 分析问题 1…

公众号留言功能怎么打开?有什么条件?

为什么公众号没有留言功能?2018年2月12日,TX新规出台:根据相关规定和平台规则要求,我们暂时调整留言功能开放规则,后续新注册帐号无留言功能。这就意味着2018年2月12日号之后注册的公众号不论个人主体还是组织主体&…

十四、MySql的用户管理

文章目录 一、用户管理二、用户(一)用户信息(二)创建用户1.语法:2.案例: (三) 删除用户1.语法:2.示例: (四)修改用户密码1.语法&#…

ps丢失d3dcompiler_47.dll怎么办,这四个方法都能解决

在当今的信息化社会,电脑已经成为我们生活和工作中不可或缺的一部分。然而,随着软件技术的不断发展,电脑在使用过程中也难免会遇到各种问题。其中,缺失d3dcompiler_47.dll文件是一个常见的问题。本文将为大家介绍如何修复电脑出现…

Python JS逆向之Ku狗,实现搜索下载功能(附源码)

今天用Python来实现一下酷狗JS逆向,实现搜索下载功能 1、环境使用 Python 3.8Pycharm 2、模块使用 import hashlib --> pip install hashlib import prettytable as pt --> pip install prettytable import requests --> pip install requests import…

深度学习从入门到入土

1. 数据操作 N维数组样例 N维数组是机器学习和神经网络的主要数据结构 0-d 一个类别: 1.0 1-d 一个特征向量(一维矩阵):[1.0, 2.7, 3.4] 2-d 一个样本-特征矩阵-(二维矩阵) 3-d RGB图片 (宽x高x通道)- 三维数组 4-d 一个RGB…

selenium自动化测试入门,一篇足矣

Selenium是一个基于浏览器的自动化测试工具,它提供了一种跨平台、跨浏览器的端到端的web自动化解决方案。 Selenium是用于自动化控制浏览器做各种操作,打开网页,点击按钮,输入表单等等,可以模拟各种人工操作浏览器的功…

共享WiFi贴项目怎么实施与运营,微火为你提供高效解答!

共享WiFi贴是一项有前景的商业项目,不仅可以满足用户对网络的需求,还可以为创业者带来盈利的机会。那么,我们来看看如何有效地开展共享WiFi贴项目。 最重要的是选择合适的位置。共享WiFi贴项目的成功与否很大程度上取决于位置选择。优先选择人…

web前端之float布局与flex布局

float布局 <style>.nav {overflow: hidden;background-color: #6adfd0; /* 导航栏背景颜色 */}.nav a {float: left;display: block;text-align: center;padding: 14px 16px;text-decoration: none;color: #000000; /* 导航栏文字颜色 */}.nav a:hover {background-col…

示例-安装office2016图文教程简体中文下载安装包

目录 简介 步骤 总结 简介 Office 2016作为一款办公软件套件&#xff0c;下载和安装 都具有许多令人印象深刻的特点。让我来为你介绍一下&#xff1a;Office 2016注重实现跨平台的一致性。无论你是在Windows、Mac、iOS还是Android上使用Office&#xff0c;你都可以享受到相似…

软件测试之白盒测试

白盒测试 白盒测试&#xff08;White Box Testing&#xff09;又称结构测试、透明盒测试、逻辑驱动测试或基于代码的测试。白盒测试只测试软件产品的内部结构和处理过程&#xff0c;而不测试软件产品的功能&#xff0c;用于纠正软件系统在描述、表示和规格上的错误&#xff0c…

「回到县城」正成为大学生就业的无奈选择

现如今&#xff0c;上大学已经不再是当年的天之骄子&#xff0c;现在的大学升学率极高&#xff0c;而毕业就业率却与之相反。 只有少数人能成为优秀的人&#xff0c;而竞争激烈的结果只有更少的人获得胜利。 想象一下&#xff0c;在大城市里打拼&#xff0c;就像千军万马争夺…

图像分割基础,点、线、孤立点检测(数字图像处理概念 P7)

文章目录 基础特性边缘检测孤立点检测线检测全局阈值处理 分割将图像细分成 构成他的子区域或对象 异常图像分割是最困难的图像处理之一&#xff0c;分割的程度取决于问题 基础特性 边缘检测 孤立点检测 线检测 全局阈值处理

Django — 介绍和搭建

目录 一、介绍二、虚拟环境1、作用2、创建2.1、安装虚拟环境模块2.2、创建文件夹2.3、配置环境变量 三、项目创建四、目录介绍1、manage.py2、__ init __.py3、asgi.py4、settings.py5、urls.py6、wsgi.py 五、启动服务1、配置启动服务2、从终端启动 六、创建子应用1、子应用2、…

小程序中如何(批量)删除会员卡

因为一些原因&#xff0c;可能需要删除会员卡。下面我将介绍一下小程序中如何删除会员卡的步骤&#xff0c;包括批量删除会员卡的操作。 1. 找到指定的会员卡。在管理员后台->会员管理处&#xff0c;找到需要删除的会员卡。也支持对会员卡按卡号、手机号和等级进行搜索。 2…

【深度学习实验】前馈神经网络(八):模型评价(自定义支持分批进行评价的Accuracy类)

目录 一、实验介绍 二、实验环境 1. 配置虚拟环境 2. 库版本介绍 三、实验内容 0. 导入必要的工具包 1. __init__(构造函数) 2. update函数(更新评价指标) 5. accumulate(计算准确率) 4. reset(重置评价指标) 5. 构造数据进行测试 6. 代码整合 一、实验介绍 本文将实…

基于Yolov8的工业小目标缺陷检测(5):大缺陷小缺陷一网打尽的轻量级目标检测器GiraffeDet,暴力提升工业缺陷检测能力

💡💡💡本文改进:大小缺陷一网打尽的GiraffeDet,提升处理低分辨率图像和小物体等更困难的检测能力。 GiraffeDet | 亲测在工业小目标缺陷涨点明显,原始mAP@0.5 0.679提升至0.727 收录专栏: 💡💡💡深度学习工业缺陷检测 :http://t.csdn.cn/fVSgs ✨✨✨提供…

【一】Spring Cloud 系列简介

Spring Cloud 系列简介 简介&#xff1a;从单体架构到分布式架构&#xff0c;再到微服务架构&#xff0c;一路经历走来spring框架也一直在与时俱进&#xff0c;回顾下来感觉做Java开发就是基于spring开发&#xff0c;spring也一路发展出了spring boot&#xff0c;在此基础上发…

阿里云服务器u1和经济型e系列性能差异?哪个比较好?

阿里云服务器经济型e实例和云服务器u1有什么区别&#xff1f;同CPU内存配置下云服务器u1性能更强&#xff0c;u1实例价格也要更贵一些。经济型e实例属于共享型云服务器&#xff0c;不同实例vCPU会争抢物理CPU资源&#xff0c;并导致高负载时计算性能波动不稳定&#xff0c;而云…