【数据结构和算法】 相等行列对

news2024/11/25 20:49:33

其他系列文章导航

Java基础合集
数据结构与算法合集

设计模式合集

多线程合集

分布式合集

ES合集


文章目录

其他系列文章导航

文章目录

前言

一、题目描述

二、题解

2.1 三层循环

2.2 哈希 + 二层循环

三、代码

3.1 三层循环

3.2 哈希 + 二层循环

四、复杂度分析

4.1 三层循环

4.2 哈希 + 二层循环


前言

这是力扣的 2352 题,难度为中等,解题方案有很多种,本文讲解我认为最奇妙的一种。


一、题目描述

给你一个下标从 0 开始、大小为 n x n 的整数矩阵 grid ,返回满足 Ri 行和 Cj 列相等的行列对 (Ri, Cj) 的数目

如果行和列以相同的顺序包含相同的元素(即相等的数组),则认为二者是相等的。

示例 1:

输入:grid = [[3,2,1],[1,7,6],[2,7,7]]
输出:1
解释:存在一对相等行列对:
- (第 2 行,第 1 列):[2,7,7]

示例 2:

输入:grid = [[3,1,2,2],[1,4,4,5],[2,4,2,2],[2,4,2,2]]
输出:3
解释:存在三对相等行列对:
- (第 0 行,第 0 列):[3,1,2,2]
- (第 2 行, 第 2 列):[2,4,2,2]
- (第 3 行, 第 2 列):[2,4,2,2]

提示:

  • n == grid.length == grid[i].length
  • 1 <= n <= 200
  • 1 <= grid[i][j] <= 105

二、题解

2.1 三层循环

思路与算法:

我们直接将矩阵 gridgridgrid 的每一行和每一列进行比较,如果相等,那么就是一对相等行列对,答案加一。

2.2 哈希 + 二层循环

思路与算法:

这道题暴力解:遍历每一列,然后遍历每一行,再比对当前行和当前列是否以相同顺序包含相同元素。

遍历每一行的时间复杂度为O(n^2),再套上一层遍历每一列时间复杂度就为O(n^3)。

我们可以发现,我们其实在遍历每一列的时候都在重复的遍历每一行,那么我们可以使用哈希表来存储每一行的数字序列字符串。

然后在遍历每一个行的时候生成这一行对应的数字序列字符串,哈希表中记录有这个数字序列字符串的个数就是对应的行列对个数。

如果直接把数字进行拼接会造成歧义,可能不同的数字会有相同数字序列字符串。因此每一个数字之后添加一个标识符%进行区分。

图解

以示例2进行图解


三、代码

3.1 三层循环

Java版本:

class Solution {
    public int equalPairs(int[][] grid) {
        int n = grid.length;
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                int ok = 1;
                for (int k = 0; k < n; ++k) {
                    if (grid[i][k] != grid[k][j]) {
                        ok = 0;
                        break;
                    }
                }
                ans += ok;
            }
        }
        return ans;
    }
}

C++版本:

class Solution {
public:
    int equalPairs(vector<vector<int>>& grid) {
        int n = grid.size();
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            for (int j = 0; j < n; ++j) {
                int ok = 1;
                for (int k = 0; k < n; ++k) {
                    if (grid[i][k] != grid[k][j]) {
                        ok = 0;
                        break;
                    }
                }
                ans += ok;
            }
        }
        return ans;
    }
};

Python版本:

class Solution:
    def equalPairs(self, grid: List[List[int]]) -> int:
        g = [list(col) for col in zip(*grid)]
        return sum(row == col for row in grid for col in g)

3.2 哈希 + 二层循环

Java版本:

class Solution {
    public int equalPairs(int[][] grid) {
        int n = grid.length;    // 矩阵尺寸
        Map<String, Integer> rowSeqCount = new HashMap<>();     // 存储行数字序列字符串的哈希表
        StringBuilder sb ;      // 用于生成数字序列字符串
        String rowSeq;          // 数字序列字符串
        for(int i = 0; i < n; i++){     // 遍历每一行
            sb = new StringBuilder();   // 每一行新建一个对象
            // 生成行数字序列字符串
            for(int j = 0; j < n; j++){
                sb.append(grid[i][j]);
                sb.append('%');
            }
            rowSeq = sb.toString(); 
            // 哈希表记录这个数字序列字符串个数
            rowSeqCount.put(rowSeq, rowSeqCount.getOrDefault(rowSeq, 0) + 1);
        }
        int count = 0;
        for(int j = 0; j < n; j++){     // 遍历每一列
            sb = new StringBuilder();   // 每一列新建一个对象
            // 生成列数字序列字符串
            for(int i = 0; i < n; i++){
                sb.append(grid[i][j]);
                sb.append('%');
            }
            rowSeq = sb.toString();
            // 从哈希表中查询是和这个列数字序列字符串相同的行数字序列字符串的个数
            count += rowSeqCount.getOrDefault(rowSeq, 0);
        }
        return count; 
    }
}

C++版本:

class Solution {
public:
    int equalPairs(std::vector<std::vector<int>>& grid) {
        int n = grid.size(); // 矩阵尺寸
        std::unordered_map<std::string, int> row_seq_count; // 存储行数字序列字符串的哈希表
        for (int i = 0; i < n; i++) { // 用于生成数字序列字符串
            std::string row_seq = ""; // 每一行新建一个字符串
            // 生成行数字序列字符串
            for (int j = 0; j < n; j++) {
                row_seq += std::to_string(grid[i][j]) + "%";
            }
            // 哈希表记录这个数字序列字符串个数
            row_seq_count[row_seq] = row_seq_count[row_seq] + 1;
        }

        int count = 0;
        for (int j = 0; j < n; j++) { // 遍历每一列
            std::string row_seq = ""; // 每一列新建一个对象
            // 生成列数字序列字符串
            for (int i = 0; i < n; i++) {
                row_seq += std::to_string(grid[i][j]) + "%";
            }
            // 从哈希表中查询是和这个列数字序列字符串相同的行数字序列字符串的个数
            count += row_seq_count[row_seq];
        }

        return count;
    }
};

Python版本:

class Solution:
    def equalPairs(self, grid: List[List[int]]) -> int:
        n = len(grid)       # 矩阵尺寸
        row_seq_count = {}  # 存储行数字序列字符串的哈希表
        for i in range(n):  # 用于生成数字序列字符串
            row_seq = ""    # 每一行新建一个字符串
            # 生成行数字序列字符串
            for j in range(n):  
                row_seq += f"{grid[i][j]}%"
            # 哈希表记录这个数字序列字符串个数
            row_seq_count[row_seq] = row_seq_count.get(row_seq, 0) + 1
        
        count = 0
        for j in range(n):  # 遍历每一列
            row_seq = ""    # 每一列新建一个对象
            # 生成列数字序列字符串
            for i in range(n):
                row_seq += f"{grid[i][j]}%"
            # 从哈希表中查询是和这个列数字序列字符串相同的行数字序列字符串的个数
            count += row_seq_count.get(row_seq, 0)

        return count

四、复杂度分析

4.1 三层循环

时间复杂度: O(n^3)。其中 n 为矩阵 grid 的行数或列数。

空间复杂度: O(1)。

4.2 哈希 + 二层循环

时间复杂度: O(n^2)。其中 n 为矩阵 grid 的行数或列数。

空间复杂度: O(n^2)。


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

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

相关文章

Eureka注册及使用

一、Eureka的作用 Eureka是一个服务注册与发现的工具&#xff0c;主要用于微服务架构中的服务发现和负载均衡。其主要作用包括&#xff1a; 服务提供者将自己注册到Eureka Server上&#xff0c;包括服务的地址和端口等信息。服务消费者从Eureka Server上获取服务提供者的地址…

C++入门【17-C++ 字符串】

C 字符串 C 提供了以下两种类型的字符串表示形式&#xff1a; C 风格字符串C 引入的 string 类类型 C 风格字符串 C 风格的字符串起源于 C 语言&#xff0c;并在 C 中继续得到支持。字符串实际上是使用 null 字符 \0 终止的一维字符数组。因此&#xff0c;一个以 null 结尾…

2023年度十大科技名词发布:大语言模型、脑机接口在列

源自&#xff1a;IT之家 “人工智能技术与咨询” 发布 IT之家 12 月 26 日消息&#xff0c;据光明日报&#xff0c;全国科学技术名词审定委员会事务中心联合国家语言资源监测与研究平面媒体中心、蜜度微热点研究院、万方数据、百度百科、百度指数、《中国科技术语》杂志社等…

uni-app 前后端调用实例 基于Springboot 数据列表显示实现

锋哥原创的uni-app视频教程&#xff1a; 2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中..._哔哩哔哩_bilibili2023版uniapp从入门到上天视频教程(Java后端无废话版)&#xff0c;火爆更新中...共计23条视频&#xff0c;包括&#xff1a;第1讲 uni…

【VTK三维重建-体绘制】第四期 VTK中GPU加速

很高兴在雪易的CSDN遇见你 VTK技术爱好者 QQ&#xff1a;870202403 前言 上期内容讲到VTK的体绘制技术vtkGPUVolumeRayCastMapper&#xff0c;本文分享VTK中GPU加速的相关内容&#xff0c;希望对各位小伙伴有所帮助&#xff01; 感谢各位小伙伴的点赞关注&#xff0c;小易会…

国标GB28181对接的时候如何配置服务端口和本地端口

目 录 一、国标GB28181对接需要配置的端口等参数 二、GB28181服务器端口的配置&#xff1a;SIP服务器端口 三、GB28181设备测端口的配置&#xff1a;本地SIP端口 &#xff08;一&#xff09;本地SIP端口配置的意义 &#xff08;二&#xf…

一文初识Linux进程(超详细!)

&#x1f3ac;慕斯主页&#xff1a;修仙—别有洞天 ♈️今日夜电波&#xff1a;HEART BEAT—YOASOBI 2:20━━━━━━️&#x1f49f;──────── 5:35 &#x1f504; ◀️ ⏸ ▶️ ☰ …

QT上位机开发(绘图软件)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 稍微复杂一点的软件&#xff0c;一般都是带有绘图功能。绘图的意义&#xff0c;不仅仅是像CAD一样&#xff0c;可以进行模型的设计、比对和调试。它…

数字图像处理(3)——频域图像增强

&#x1f525;博客主页&#xff1a;是dream &#x1f680;系列专栏&#xff1a;深度学习环境搭建、环境配置问题解决、自然语言处理、语音信号处理、项目开发 &#x1f498;每日语录&#xff1a;贤才&#xff0c;难进易出&#xff1b;庸才&#xff0c;易进易初出&#xff1b;…

IDA入门【二】IDA数据显示窗口

主窗口 IDA图形视图 图形视图会让人联想到程序流程图&#xff0c;因为它将一个函数分解成许多基本块&#xff0c;以生动显示该函数由一个块到另一个块的控制流程。 在屏幕上你会发现&#xff0c;IDA使用不同的彩色箭头区分函数块之间各种类型的流。 根据测试条件&#xff0c…

【Spring实战】15 Logback

文章目录 1. 依赖2. 配置3. 打印日志4. 启动程序5. 验证6. 调整日志级别7. 代码详细总结 Spring 作为一个现代化的 Java 开发框架&#xff0c;提供了很多便利的功能&#xff0c;其中包括灵活而强大的日志记录。本文将介绍如何结合 Spring 和 Logback 配置和使用日志&#xff0c…

旅游平台网页前后端

功能清单 游客功能 用户注册、登录登录权限拦截按名称搜索房间支付流程查看订单信息和状态评论预定过的房间&#xff0c;并自动修改订单状态查看统计剩余房间数量&#xff0c;数量为0时不可预定 管理员功能 房间分类管理 类型的删除、修改、查询&#xff08;准备添加增添功能…

一文通透Text Embedding模型:从text2vec、openai-ada-002到m3e、bge

前言 本文一开始是属于此文《知识库问答LangChainLLM的二次开发&#xff1a;商用时的典型问题及其改进方案》的1.2节&#xff0c;但为把Text Embedding模型阐述的更为精准、全面&#xff0c;特把那部分的内容抽取出来&#xff0c;不断完善成此文 第一部分 衡量文本向量表示效果…

【Java系列】文件操作详解

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Java系列专栏】【JaveEE学习专栏】 本专栏旨在分享学习JavaEE的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 …

天气预报网站windy的使用简介

原来这些文章我都写在QQ日志里&#xff0c;只为方便自己翻阅&#xff0c;但QQ日志很不好的地方就是没有查找功能&#xff0c;自己想翻看都很不方便&#xff0c;以后就还是在熟悉的CSDN作记录吧。 windy是个很不错的天气预报网站&#xff0c;对喜欢钓鱼的我来说&#xff0c;能方…

Python-docx 深入word源码 带有序号的段落无法设置段后、段前距离、间距等段落属性

如果使用p doc.add_paragraph(内容, styleList Number)来创建序号段落&#xff0c;会发现设置序号段落之间的段前、段后以及段落间距无法生效。后来将docx库生成的word文档打开后发现段落的设置出现问题&#xff0c;如下图红框所示&#xff0c;将该选项去掉即可使段落间距属性…

软件设计模式 --- 类,对象和工厂模式的引入

Q1&#xff1a;什么是软件设计模式&#xff1f; A&#xff1a;软件设计模式&#xff0c;又称设计模式。它是一套被反复使用、多数人知晓的、经过分类编目的、代码设计经验的总结。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性、程序的重用性。综上&…

mysql原理--MySQL基于规则的优化

设计 MySQL 的大叔依据一些规则&#xff0c;竭尽全力的把一些很糟糕的语句转换成某种可以比较高效执行的形式&#xff0c;这个过程也可以被称作 查询重写 &#xff08;就是人家觉得你写的语句不好&#xff0c;自己再重写一遍&#xff09;。 1.条件化简 我们编写的查询语句的搜…

怎么给直播录屏?超简单教程,一学就会!

随着直播行业的兴起&#xff0c;许多玩家和观众都希望能够录制直播内容以方便随时回顾或与他人分享。可是怎么给直播录屏呢&#xff1f;本文将详细介绍两种流行的直播录屏方法。通过学习这两种工具&#xff0c;你可以轻松实现直播录屏&#xff0c;记录并分享你的直播内容。 怎么…

jsp结合servlet

servlet配置 环境配置2023.12.31 idea配置搭建 创建一个普通的java项目 由于新版idea去除了add framework support的ui显示&#xff0c;可以在左边项目栏中使用快捷键shiftk或者setting中搜索add framework support在修改对应的快捷键 点击ok然后应该就是下面这样的结果 这里…