热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

算法特别篇_强大的static_注重细节的百倍优化(LeetCode_839_相似字符串组)

算法特别篇_强大的static优化概:思来想去,果然还是有必要记录一下这见证历史的时刻!学c++也有点时间了,关于代码基础细节反面,一直没有切身体会过有多大的影响。今天借这份每日一




算法特别篇_强大的static优化

:思来想去,果然还是有必要记录一下这见证历史的时刻!学c++也有点时间了,关于代码基础细节反面,一直没有切身体会过有多大的影响。今天借这份每日一题记录一下细节上的百倍优化。
来源:力扣(LeetCode)
链接:LeetCode_839_相似字符串组


故事开始


首先题目

我打开力扣看到了今天的每日一题,又是困难,又是并查集,大体思路并不难,不会并查集的hxd去隔壁博客康康算法特别篇_并查集思路(LeetCode_778_水位上升的泳池中游泳) 。嗯,那我先把题扔上来。


  • 题目
    如果交换字符串 X 中的两个不同位置的字母,使得它和字符串 Y 相等,那么称 X 和 Y 两个字符串相似。如果这两个字符串本身是相等的,那它们也是相似的。
    例如,“tars” 和 “rats” 是相似的 (交换 0 与 2 的位置); “rats” 和 “arts” 也是相似的,但是 “star” 不与 “tars”,“rats”,或 “arts” 相似。
    总之,它们通过相似性形成了两个关联组:{“tars”, “rats”, “arts”} 和 {“star”}。注意,“tars” 和 “arts” 是在同一组中,即使它们并不相似。形式上,对每个组而言,要确定一个单词在组中,只需要这个词和该组中至少一个单词相似。
    给你一个字符串列表 strs。列表中的每个字符串都是 strs 中其它所有字符串的一个字母异位词。请问 strs 中有多少个相似字符串组?

  • 例子
    示例 1:
    输入:strs = [“tars”,“rats”,“arts”,“star”]
    输出:2
    示例 2:
    输入:strs = [“omv”,“ovm”]
    输出:1

  • 提示
    1 <= strs.length <= 100
    1 <= strs[i].length <= 1000
    sum(strs[i].length) <= 2 * 104
    strs[i] 只包含小写字母。
    strs 中的所有单词都具有相同的长度,且是彼此的字母异位词。

  • 备注
    字母异位词(anagram),一种把某个字符串的字母的位置(顺序)加以改换所形成的新词。


然后AC这道题目

下来我就动手了,很快啊!直接搓了一个并查集,给他ac了,但是效率感人(如下图),我刷力扣以来第一次这么惨淡,虽然ac了,但是伤害不高羞辱性极强。我能忍吗,我不能,我得优化它。在这里插入图片描述

这边先贴一下最开始用的那份代码

class UnionFind
{
public:
vector parents;
int count = 0;
UnionFind(int n)
{
count = n;
for(int i = 0;i {
parents.push_back(i);
}
}
int Find(int x)
{
if(parents[x]==x) return x;
return Find(parents[x]);
}
void marge(int x,int y)
{
if(Find(x)!=Find(y))
{
parents[Find(x)] = Find(y);
count--;
}
}
};
class Solution {
public:
int numSimilarGroups(vector& strs) {
UnionFind uf(strs.size());
for(int i = 0;i for(int j = i+1;j if(strResemble(strs[i],strs[j])) uf.marge(i,j);
return uf.count;
}
bool strResemble(string& a,string& b)
{
vector ve;
for(int i = 0;i
if(a[i]!=b[i])
{
ve.push_back(i);
}
}
if(ve.size()==0) return true;
if(ve.size()!=2) return false;
if(a[ve[0]]==b[ve[1]]&&a[ve[1]]==b[ve[0]]) return true;
return false;
}
};

接着优化我的效率


  • 如上代码中,我只有一个方法的参数使用了引用,是因为感觉那些int参数无关紧要的,但是效率太低之后,我决定给我所有的参数都改成引用,但是效率仍旧感人。你可以理解成没变
  • 在苦思冥想之后,我觉得是因为频繁调用strResemble方法频繁创建了vector并且频繁申请空间导致,于是我当机立断,给这个vector改成了static,然后稍稍调整代码,但仍旧基本没有改变,让我直呼发生甚么事了。
  • 最终得出结论,问题可能并不出在声明vector上,二是出在push_back()这一手动态内存申请上,于是我把vector改成了静态数组,并取一个int变量去作为size来使用,全员静态,就不存在动态申请内存,导致内存使用过多的情况了,反复利用一块内存的优势就来了,看下图
    在这里插入图片描述
    贴个最终代码

class UnionFind
{
public:
vector parents;
int count = 0;
UnionFind(int n)
{
count = n;
parents = vector(n);
for(int i = 0;i {
parents[i] = i;
}
}
int Find(int& x)
{
if(parents[x]==x) return x;
return Find(parents[x]);
}
void marge(int& x,int& y)
{
if(Find(x)!=Find(y))
{
parents[Find(x)] = Find(y);
count--;
}
}
};
class Solution {
public:
int numSimilarGroups(vector& strs) {
UnionFind uf(strs.size());
for(int i = 0;i for(int j = i+1;j if(strResemble(strs[i],strs[j])) uf.marge(i,j);
return uf.count;
}
bool strResemble(string& a,string& b)
{
static int p[2];
static int boo;
boo = 0;
for(int i = 0;i {
if(a[i]!=b[i])
{
if(boo>1) return false;
p[boo] = i;
boo++;
}
}
if(boo==0) return true;
if(boo==1) return false;
if(a[p[0]]==b[p[1]]&&a[p[1]]==b[p[0]]) return true;
return false;
}
};


推荐阅读
  • 本文介绍了如何在 C# 和 XNA 框架中实现一个自定义的 3x3 矩阵类(MMatrix33),旨在深入理解矩阵运算及其应用场景。该类参考了 AS3 Starling 和其他相关资源,以确保算法的准确性和高效性。 ... [详细]
  • 由二叉树到贪心算法
    二叉树很重要树是数据结构中的重中之重,尤其以各类二叉树为学习的难点。单就面试而言,在 ... [详细]
  • 深入理解Java多线程并发处理:基础与实践
    本文探讨了Java中的多线程并发处理机制,从基本概念到实际应用,帮助读者全面理解并掌握多线程编程技巧。通过实例解析和理论阐述,确保初学者也能轻松入门。 ... [详细]
  • 本文详细介绍了Hive中用于日期和字符串相互转换的多种函数,包括从时间戳到日期格式的转换、日期到时间戳的转换,以及如何处理不同格式的日期字符串。通过这些函数,用户可以轻松实现日期和字符串之间的灵活转换,满足数据处理中的各种需求。 ... [详细]
  • 深入解析ArrayList与LinkedList的差异
    本文详细对比了Java中ArrayList和LinkedList两种常用集合类的特性、性能及适用场景,通过代码示例进行测试,并结合实际应用场景分析其优缺点。 ... [详细]
  • 本文详细介绍了装饰者(Decorator)模式,这是一种动态地为对象添加职责的方法。与传统的继承方式不同,装饰者模式通过组合而非继承来实现功能扩展,从而提供更大的灵活性和可维护性。 ... [详细]
  • 为了解决不同服务器间共享图片的需求,我们最初考虑建立一个FTP图片服务器。然而,考虑到项目是一个简单的CMS系统,为了简化流程,团队决定探索七牛云存储的解决方案。本文将详细介绍使用七牛云存储的过程和心得。 ... [详细]
  • 并发编程 12—— 任务取消与关闭 之 shutdownNow 的局限性
    Java并发编程实践目录并发编程01——ThreadLocal并发编程02——ConcurrentHashMap并发编程03——阻塞队列和生产者-消费者模式并发编程04——闭锁Co ... [详细]
  • 深入解析 Android IPC 中的 Messenger 机制
    本文详细介绍了 Android 中基于消息传递的进程间通信(IPC)机制——Messenger。通过实例和源码分析,帮助开发者更好地理解和使用这一高效的通信工具。 ... [详细]
  • Java多线程实现:从1到100分段求和并汇总结果
    本文介绍如何使用Java编写一个程序,通过10个线程分别计算不同区间的和,并最终汇总所有线程的结果。每个线程负责计算一段连续的整数之和,最后将所有线程的结果相加。 ... [详细]
  • Linux环境下进程间通信:深入解析信号机制
    本文详细探讨了Linux系统中信号的生命周期,从信号生成到处理函数执行完毕的全过程,并介绍了信号编程中的注意事项和常见应用实例。通过分析信号在进程中的注册、注销及处理过程,帮助读者理解如何高效利用信号进行进程间通信。 ... [详细]
  • 深入解析Java多线程与并发库的应用:空中网实习生面试题详解
    本文详细探讨了Java多线程与并发库的高级应用,结合空中网在挑选实习生时的面试题目,深入分析了相关技术要点和实现细节。文章通过具体的代码示例展示了如何使用Semaphore和SynchronousQueue来管理线程同步和任务调度。 ... [详细]
  • 本文介绍了如何通过Java代码计算一个整数的位数,并展示了多个基础编程示例,包括求和、平均分计算、条件判断等。 ... [详细]
  • 本篇文章介绍如何将两个分别表示整数的链表进行相加,并生成一个新的链表。每个链表节点包含0到9的数值,如9-3-7和6-3相加得到1-0-0-0。通过反向处理链表、逐位相加并处理进位,最终再将结果链表反向,即可完成计算。 ... [详细]
  • Spring Boot 中静态资源映射详解
    本文深入探讨了 Spring Boot 如何简化 Web 应用中的静态资源管理,包括默认的静态资源映射规则、WebJars 的使用以及静态首页的处理方法。通过本文,您将了解如何高效地管理和引用静态资源。 ... [详细]
author-avatar
禹Ayu
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有