【leetcode 447. 回旋镖的数量】审慎思考与推倒重来

447. 回旋镖的数量

题目描述

给定平面上 **n **对 互不相同 的点 points ,其中 points[i] = [xi, yi]回旋镖 是由点 (i, j, k) 表示的元组 ,其中 ij 之间的距离和 ik 之间的欧式距离相等(需要考虑元组的顺序)。

返回平面上所有回旋镖的数量。

原始思路

根据题目描述,所谓回旋镖就是对于一个点i,存在另外两个点到该点的距离相等

以下图为例,点(0,0)(0,2)(2,0)的距离是相通的,这就是一个回旋镖。同样的,点(2,2)(0,2)(2,0)也构成一个回旋镖。

请添加图片描述

大概理解题目的含义后,最直接的想法就是遍历,通过三重遍历分辨判断是否为回旋镖,最后的统计数目就是需要的结果。代码实现如下:

class Solution {
private:// 判断点i与点j、点k是否构成回旋镖// ps:这里省略了开方运算bool isBoomeranges(vector<int>& i, vector<int>& j, vector<int>& k) {return ((j[1] - i[1]) * (j[1] - i[1])) + ((j[0] - i[0]) * (j[0] - i[0])) == ((k[1] - i[1]) * (k[1] - i[1])) + ((k[0] - i[0]) * (k[0] - i[0]));}
public:int numberOfBoomerangs(vector<vector<int>>& points) {int res = 0;int pointNum = points.size();for(int i = 0;i < pointNum;++i) {for(int j = 0;j < pointNum;++j) {for(int k = 0;k < pointNum;++k) {if(i == j || i == k || j == k) {// 同一个点不算continue;}if(isBoomeranges(points[i], points[j], points[k])) {++res;}}}}return res;}
};

三重循环,不出意外地超时了……

image.png

试图挽回,空间换时间

三重循环每次都要计算距离,肯定是做了很多重复运算的,或许可以用空间换时间,

尝试代码如下:

class Solution {
public:int numberOfBoomerangs(vector<vector<int>>& points) {int res = 0;int pointNum = points.size();vector<vector<long>> dis(pointNum, vector<long>(pointNum, 0)); // 记录点与点之间的“距离”for(int i = 0;i < pointNum;++i) {for(int j = i + 1;j < pointNum;++j) {dis[j][i] = dis[i][j] = ((points[j][1] - points[i][1]) * (points[j][1] - points[i][1])) + ((points[j][0] - points[i][0]) * (points[j][0] - points[i][0]));}}for(int i = 0;i < pointNum;++i) {for(int j = 0;j < pointNum;++j) {for(int k = 0;k < pointNum;++k) {if(i == j || i == k || j == k) {continue;}if(dis[i][j] == dis[i][k]) {++res;}}}}return res;}
};

结果从通过25个测试用例提升到通过28个。改善了,但又没完全改善。

image.png

到这里,意识到应该是解决方案本身的时间复杂度 O ( n 3 ) O(n^3) O(n3)就太高了。

回归本源,方法为王

虽然上面的思路简单易懂,但也把我带入“歧途”,没有深入审视题目中的含义。

所以遍历思路走到尽头后,不得不重新审视题目。

三重循环中有很多计算是重复的,还是以开头的例子做讲解,对于点(1,1),它需要分别判断:

  1. (0,0)(0,2)是否构成回旋镖
  2. (0,0)(2,2)是否构成回旋镖
  3. (0,0)(2,0)是否构成回旋镖
  4. (0,2)(0,0)是否构成回旋镖
  5. (0,2)(2,2)是否构成回旋镖
  6. (0,2)(2,0)是否构成回旋镖
  7. (2,2)(0,0)是否构成回旋镖
  8. (2,2)(0,2)是否构成回旋镖
  9. (2,2)(2,0)是否构成回旋镖
  10. (2,0)(0,0)是否构成回旋镖
  11. (2,0)(0,2)是否构成回旋镖
  12. (2,0)(2,2)是否构成回旋镖

在这个过程中,(1,1)(0,0)(0,2)(2,2)(2,0)的距离,分别被算了6遍。

但实际上,(1,1)到这四个点的距离都是相同的,任取两个点都能和(1,1)构成回旋镖,再加上顺序敏感的题目要求(既 [ ( 1 , 1 ) , ( 0 , 0 ) , ( 0 , 2 ) ] [(1,1),(0,0),(0,2)] [(1,1),(0,0),(0,2)] [ ( 1 , 1 ) , ( 0 , 2 ) , ( 0 , 0 ) ] [(1,1),(0,2),(0,0)] [(1,1),(0,2),(0,0)]是两个回旋镖),利用排列数计算就能替代多余计算。

whiteboard_exported_image-7.png

所以,对于某个点i,只需统计其他点与i之间的距离,然后利用排列数就可以计算出回旋镖的数目。
比如上面的例子中,距离为 2 \sqrt{2} 2 的点对有4个,那么 A 4 2 = 4 × 3 = 12 A^2_4 = 4 \times 3 = 12 A42=4×3=12

算法步骤:

  1. 遍历所有点
  2. 对于某个点i,统计与其他点的距离长度
  3. 对每个距离长度的数目,计算排列数
  4. 所有排列数之和即为答案
class Solution {
private:int distance(const vector<int>& p1, const vector<int>& p2) {// 计算两点之间的“距离”return (p1[0] - p2[0]) * (p1[0] - p2[0]) + (p1[1] - p2[1]) * (p1[1] - p2[1]);}
public:int numberOfBoomerangs(vector<vector<int>>& points) {int res = 0;int pointNum = points.size();for(int i = 0;i < pointNum;++i) {// 遍历所有点unordered_map<int, int> disNumMp;for(int j = 0;j < pointNum;++j) {// 统计该点与其他之间距离长度的数目// 只有该点自己到自己的长度为0,所以0对应的数目一定为0,不影响最终结果计算,无需剔除++disNumMp[distance(points[i], points[j])];}for(auto it = disNumMp.begin();it != disNumMp.end();++it) {// 计算排列数res += (it->second * (it->second - 1));}}return res;}
};

小感悟

有些时候,人容易对一开始选择的路径产生依赖,不推倒重来就难以跳脱。

审慎的思考和选择或许可以避免弯路,但更多时候还是要走到南墙才能意识到选择的对错。

所以,要有审慎选择的过程,也要有推倒重来的勇气!

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

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

相关文章

Linux引导过程和服务

一、Linux操作系统引导过程 1.引导过程 bios 加电自检——mbr——grub——加载内核——启动进程 加电后BIOS程序回自检硬件&#xff0c;硬件无故障后&#xff0c;会根据第一次启动项去找内核&#xff0c;一般来说第一启动项是硬盘&#xff0c;找到硬盘后&#xff0c;会根据mb…

深入了解网络流量清洗--使用免费的雷池社区版进行防护

​ 随着网络攻击日益复杂&#xff0c;企业面临的网络安全挑战也在不断增加。在这个背景下&#xff0c;网络流量清洗成为了确保企业网络安全的关键技术。本文将探讨雷池社区版如何通过网络流量清洗技术&#xff0c;帮助企业有效应对网络威胁。 ![] 网络流量清洗的重要性&#x…

第四站:指针的进阶-(二级指针,函数指针)

目录 二级指针 二级指针的用途 多级指针的定义和使用 指针和数组之间的关系 存储指针的数组(指针数组:保存地址值) 指向数组的指针(数组指针) 传参的形式(指针) 数组传参时会退化为指针 void类型的指针 函数指针 定义: 调用:两种方式:(*指针名)(参数地址) 或者 指针…

别闹了,真的不是你的技术菜!!!

最近经常听到有小伙伴总是在抱怨自己的技术菜&#xff0c;公司没有机会让自己去成长技术&#xff0c;于是小编就此场景来写一篇文章&#xff0c;希望对大家有帮助。 错误的理解CRUD工程师 CRUD工程师这个名称是很多小伙伴都听过的&#xff0c;并且很多工程师都把自己比作是代…

Ubuntu 18.04.5 LTS 解决安装包复杂依赖相关问题解决的主要法则和VIM的安装实录

前言&#xff1a;目标和环境 环境&#xff1a; Ubuntu 18.04.5 LTSVMware 目标&#xff1a; 安装vim&#xff0c;解决包依赖的冲突&#xff1a; 本文&#xff0c;通过一个很好的实例&#xff0c;诠释了&#xff0c;LINUX系统下&#xff0c;安装一个应用遇到的依赖库问题如何…

Wilcoxon秩和检验-校正P值(自备)

R语言 boxplot作图 图内展示校正后的P值(padj)_r语言 p值校正-CSDN博客 FDR错误发现率-P值校正学习_fdr和p值的关系-CSDN博客 原理介绍&#xff1a; Benjamini-Hochberg 方法介绍 有N次假设检验&#xff0c;对每一次假设检验都计算其P值&#xff0c;然后将计算出的P值按照…

对接讯飞聊天机器人接口--复盘

1、准备工作 1&#xff09;、进入以下平台进行注册&#xff0c;登录后&#xff0c;点击红框处 2&#xff09;、点击个人免费包&#xff08;会弹出实名认证&#xff0c;先进行实名认证&#xff09; 3&#xff09;、认证后&#xff0c;会进入以下界面&#xff0c;先添加应用 4&am…

代码随想录刷题题Day29

刷题的第二十九天&#xff0c;希望自己能够不断坚持下去&#xff0c;迎来蜕变。&#x1f600;&#x1f600;&#x1f600; 刷题语言&#xff1a;C Day29 任务 ● 01背包问题&#xff0c;你该了解这些&#xff01; ● 01背包问题&#xff0c;你该了解这些&#xff01; 滚动数组 …

软件测试|深入理解Python的encode()和decode()方法

简介 在Python中&#xff0c;字符串是不可变的序列对象&#xff0c;它由Unicode字符组成。当我们需要在字符串和字节之间进行转换时&#xff0c;Python提供了两个非常重要的方法&#xff1a;encode()和decode()。这两个方法允许我们在Unicode字符和字节之间进行相互转换&#…

认知能力测验,⑤破解图形推理测试题,校招社招网申在线测评必用

认知能力测试&#xff0c;如今是每个求职者必须要面对的&#xff0c;有的人可以顺顺利利通过&#xff0c;而有的人只能够遗憾止步。想要通过认知能力测验&#xff0c;并不是一件易事&#xff0c;而今天要说的图形推理&#xff0c;仅仅是其中的一个部分&#xff0c;抛砖引玉&…

【数据分析实战】冰雪大世界携程景区评价信息情感分析采集词云

文章目录 引言数据采集数据集展示数据预处理 数据分析评价总体情况分析本人浅薄分析 各游客人群占比分析本人浅薄分析 各评分雷达图本人浅薄分析 差评词云-可视化本人浅薄分析 好评词云-可视化本人浅薄分析 综合分析写在最后 今年冬天&#xff0c;哈尔滨冰雪旅游"杀疯了&q…

IP地址的网络安全防护和预防

网络安全对于保护个人和组织的信息资产至关重要&#xff0c;而IP地址是网络通信的基础。在这篇文章中&#xff0c;IP数据云将探讨IP地址的网络安全防护和预防措施&#xff0c;以确保网络的安全性和可靠性。 IP地址是互联网上每个设备在网络中的唯一标识符。有IPv4和IPv6两种类…

docker部署awvs

docker部署awvs cantos部署docker点这里 下载镜像 docker pull xiaomimi8/awvs14-log4j-2022 docker images 查看本地所有镜像启动镜像 docker run -it -d&#xff08;后台运行&#xff09; -p&#xff08;端口映射&#xff09; 13443&#xff08;主机端口&#xff09;:3443&…

【Databand】日期时间函数

文章目录 获取当前日期和时间日期格式化函数日期加减运算日期时间和时间戳转化日期时间各部分拆分日期时间加减运算实际应用扩展总结 获取当前日期和时间 Databend 使用 UTC 作为默认时区&#xff0c;并允许您将时区更改为当前地理位置。 -- 查看时区 select timezone(); ---…

【Java开发工具】windows和mac多版本JDK 安装指南:让你在开发中轻松应对不同版本需求

解决思路 通过动态修改JDK环境变量中的JAVA_HOME 将值改成相应的JDK安装目录&#xff0c;来达到在同一电脑中安装不同版本jdk的效果。 windows系统 安装的jdk目录 右键→属性→高级系统设置→高级→环境变量→系统变量。 新建4个系统变 量变量值,变量名分别为&#xff1a…

statsmodels.tsa 笔记 detrend(去趋势)

1 基本使用方法 statsmodels.tsa.tsatools.detrend(x, order1, axis0) 2 参数说明 x数据。如果是二维数组&#xff0c;那么每一行或每一列将独立地去除趋势&#xff0c;但趋势的阶数是一样的。order趋势的多项式阶数。0 表示常数趋势&#xff08;即没有趋势&#xff09;&…

kubernetes Adminssion Webhook 准入控制器 (ImagePolicyWebhook)

开头语 写在前面&#xff1a;如有问题&#xff0c;以你为准&#xff0c; 目前24年应届生&#xff0c;各位大佬轻喷&#xff0c;部分资料与图片来自网络 介绍 原理 流程 Admission Webhook 准入控制器Vebhook是准入控制插件的一种&#xff0c;用于拦截所有向APISERVER发送的…

超声波清洗机是智商税吗?哪些超声波清洗机值得买?这些值得入手

自打超声波清洗机问世以来&#xff0c;就有非常多朋友会有这个疑问&#xff01;超声波清洗机到底是不是智商税呢&#xff1f;其实不光是大家&#xff0c;一开始我也有这个疑问&#xff0c;但是通过了解了超声波清洗机的一些工作原理之后&#xff0c;会发现&#xff0c;其实超声…

服务器组网方案

在当今数字化时代&#xff0c;服务器组网方案不仅是企业信息管理的关键&#xff0c;更是支撑业务运作的核心架构 。为了实现高效的数据处理和存储&#xff0c;服务器组网方案成为企业不可或缺的一部分。本文将深入探 讨服务器组网方案的核心要素和实施策略&#xff0c;明确其在…

RTMP vs SRT:延迟与最大带宽的比较

引言 文来自Haivision的白皮书&#xff0c;比较了RTMP和SRT两种流媒体协议的优缺点&#xff0c;并通过实验测试了两种协议在延迟和最大带宽两方面的表现。 本文福利&#xff0c; 免费领取C音视频学习资料包学习路线大纲、技术视频/代码&#xff0c;内容包括&#xff08;音视频…