代码随想录64——额外题目【哈希表、字符串】:205同构字符串、1002查找常用字符、925长键按入、844比较含退格的字符串

news2024/11/16 12:39:27

文章目录

  • 1.205同构字符串
    • 1.1.题目
    • 1.2.解答
  • 2.1002查找常用字符
    • 2.1.题目
    • 2.2.解答
  • 3.925长键按入
    • 3.1.题目
    • 3.2.解答
  • 4.844比较含退格的字符串
    • 4.1.题目
    • 4.2.解答
      • 4.2.1.使用栈
      • 4.2.2.从后往前双指针

1.205同构字符串

参考:代码随想录,205同构字符串;力扣题目链接

1.1.题目

1.2.解答

这道题目其实也很简单,其实就是一直在存储两个字符串之间字符的映射关系。

  • 定义一个map,其中键是字符串A中的字符,值是对应的字符串B中对应的字符。
  • 然后开始遍历每一个字符,如果当前字符在map中出现过,那么就根据A的字符当做键,寻找B应该对应的值,如果不相等直接返回false。如果没有出现过,则新添加这个映射关系即可。
  • 但是还存在一个问题是,不能单纯的看A对B是否对应,还要看B对A是否对应。比如当前字符没有在A的map中出现过,那么A的map中自然就没有记录对应B的字符。但是此时如果B中的字符在之前已经出现过了,那么他们就不是匹配的了。比如A是abc,B是eff,其中遍历到A的c时,发现没有出现过,但是此时B中对应的字符是f,显然是不对的。

注意:这个地方就是相互的对应关系都要满足,跟SLAM中两帧特征点的对应关系是一样的

最后直接给出代码如下,需要维护两个map

bool isIsomorphic(string s, string t)
{
    unordered_map<char, char> umap1;   // 使用unordered_map即可
    unordered_map<char, char> umap2;   

    for(int i = 0; i < s.size(); i++)
    {
        // 1.map1、2中都没有对应字符出现过,说明是全新的对应关系,加入即可
        if(umap1.find(s[i]) == umap1.end() && umap2.find(t[i]) == umap2.end())
        {
            umap1[s[i]] = t[i];
            umap2[t[i]] = s[i];
        }
        // 2.map1、2中都有对应的字符出现,看是否匹配
        else if(umap1.find(s[i]) != umap1.end() && umap2.find(t[i]) != umap2.end())
        {
            if(umap1[s[i]] != t[i] || umap2[t[i]] != s[i])
                return false;
        }
        // 3.map1、2中一个出现过,一个没出现过,肯定不匹配
        else
            return false;
    }

    return true;
}

2.1002查找常用字符

参考:代码随想录,1002查找常用字符;力扣题目链接

2.1.题目

在这里插入图片描述

2.2.解答

首先想到的是用哈希数组存储26个字母的出现次数,然后最后判断出现次数如果>=3,那么说明共同出现过。其实这样是错误的,存在两个问题:

  • 如果某个字母是在一个子串中出现了多次,而其他子串中没有出现,那么这样的结果就是错的。比如字符串分别是aaabcdefg,这样a出现了三次,但是都是在一个子串中出现的,所以并不是公共出现。
  • 另外注意仔细看题目,如果一个字母在字符中共同出现多次,那么结果也要输出多个相同字母。比如上面的示例1,答案中就有两个字母l

正确思路是统计出搜索字符串里26个字符的出现的频率,然后取每个字符频率最小值,最后转成输出格式就可以了

如下图所示:如
最后给出代码如下,其实很简单,就是过程繁琐了一点。

vector<string> commonChars(vector<string> &words)
{
    vector<string> result;   // 其实最后里面的字母是char就行,这里用string也无所谓

    int hash[26] = {0};   // 记录最后总的结果,即各个字符串中字母出现次数的最小值,即出现次数的交集
    
    // 1.先统计第一个子串中出现的情况
    for(int i = 0; i < words[0].size(); i++)
        hash[words[0][i]-'a']++;

    // 2.再统计其他子串出现字母的情况,并对hash表取最小的值
    for(int i = 1; i < words.size(); i++)
    {
        int tmp_hash[26] = {0};   // 当前子串的字母出现情况
        for(int j = 0; j < words[i].size(); j++)
            tmp_hash[words[i][j]-'a']++;
        // 遍历hash表,取最小值
        for(int k = 0; k < 26; k++)
            hash[k] = min(hash[k], tmp_hash[k]);  
    }

    // 3.此时hash中存的就是每个字母出现的次数,转成结果就行了
    for(int i = 0; i < 26; i++)
    {
        while(hash[i]--)   // 有多个字符
        {
            string s(1, i+'a');   // i + 'a'就是根据索引,变成字母
            result.push_back(s);
        }
    }

    // 4.最后返回结果
    return result;
}

3.925长键按入

参考:代码随想录,925长键按入;力扣题目链接

3.1.题目

在这里插入图片描述

3.2.解答

这道题目一看以为是哈希,仔细一看不行,要有顺序

所以模拟同时遍历两个数组,进行对比就可以了。

对比的时候需要一下几点:

  • name[i]typed[j]相同,则i++,j++ (继续向后对比)
  • name[i]typed[j]不相同
    (1)看是不是第一位就不相同了,也就是j如果等于0,那么直接返回false
    (2)不是第一位不相同,就让j跨越重复项,移动到重复项之后的位置,再次比较name[i] typed[j]
    ①如果 name[i]typed[j]相同,则i++,j++ (继续向后对比)
    ②不相同,返回false
  • 对比完之后有两种情况
    (1)name没有匹配完,例如name:"pyplrzzzzdsfa" type:"ppyypllr",则显然是false
    (1)type没有匹配完,例如name:"alex" type:"alexxrrrrssda",则必须保证type剩下的字符都是之前遍历的最后一个字符,否则也是false

动画如下:

在这里插入图片描述

最后给出代码如下,比较繁琐,但是不难。

bool isLongPressedName(string name, string typed)
{
    int i = 0, j = 0;   // name, typed两个数组的索引

    // 遍历两个数组,哪个都不能超过范围
    while(i < name.size() && j < typed.size())
    {
        // 1.如果相等,则继续比较下一个
        if(name[i] == typed[j])
        {
            i++;
            j++;
        }
        // 2.如果不相等
        else
        {
            // 2.1.如果是第一个字母就不相等,直接返回false
            if(j == 0)
                return false;
            // 2.2.如果不是第一个字母,则可能是由于typed[j]是前一个字母的重复字母,此时就向后跳过重复的字母
            else
            {
                // typed[j]向后跳过重复的字母
                while(j < typed.size() && typed[j] == typed[j-1])
                    j++;
                // typed[j]跳过重复的字母之后,再和name[i]比较
                // 2.2.1.如果相等,则继续比较下一个
                if(name[i] == typed[j])
                {
                    i++;
                    j++;
                }
                // 2.2.2.如果不相等,则直接不满足要求,返回false
                else
                {
                    return false;
                }
            }
        }
    }

    // 3.遍历之后,可能存在name没有遍历完,或者typed没有遍历完的情况
    // 3.1.name没有遍历完,显然typed太短了,直接返回false
    if(i < name.size())
        return false;
    
    // 3.2.tpyed没有遍历完,那么后面剩余的字符必须都是上面遍历的最后一个字符
    while(j < typed.size())
    {
        if(typed[j] != typed[j-1])  // 一旦不是上面遍历的最后一个字符,直接返回false
            return false;
        j++;
    }

    // 4.最终运行到这里则满足要求,返回true
    return true;
}

4.844比较含退格的字符串

参考:代码随想录,844比较含退格的字符串;力扣题目链接

4.1.题目

在这里插入图片描述

4.2.解答

4.2.1.使用栈

这道题目一看就是要使用栈的节奏,这种匹配(消除)问题也是栈的擅长所在。

但是本题没有必要使用栈,因为最后比较的时候还要比较栈里的元素,有点麻烦。

这里直接使用字符串string,来作为栈,末尾添加和弹出,string都有相应的接口最后比较的时候,只要比较两个字符串就可以了比比较栈里的元素方便一些

代码如下:

bool backspaceCompare(string s, string t)
{
    // 使用string当做栈,存储没有#的结果
    string ss;
    string tt;

    // 对string s进行去#操作
    for(const auto& ch : s)
    {
        if(ch != '#')  // 如果不是#,则正常入栈
            ss += ch;   // 这里应该蕴含一个隐式类型转换,char转成string
        else   // 如果是#,则执行删除上一个字符的功能,也就是出栈
            if(!ss.empty())   // 出栈之前判断栈非空
                ss.pop_back();
    }

    // 同理对string t进行去#操作
    for(const auto& ch : t)
    {
        if(ch != '#')
            tt += ch;
        else
            if(!tt.empty())
                tt.pop_back();
    }

    // 最后判断两个字符串是否相等
    return ss == tt;
}
  • 时间复杂度:O(n + m),n为S的长度,m为T的长度 ,也可以理解是O(n)的时间复杂度
  • 空间复杂度:O(n + m)

4.2.2.从后往前双指针

当然还可以有使用 O(1) 的空间复杂度来解决该问题。

同时从后向前遍历S和T(i初始为S末尾,j初始为T末尾),记录#的数量,模拟消除的操作,如果#用完了,就开始比较S[i]和S[j]。

如下图所示:
在这里插入图片描述

在遍历过程中:如果S[i]和S[j]不相同返回false,如果有一个指针(i或者j)先走到的字符串头部位置,也返回false。

最后给出代码如下,也不复杂,但是要把i/j位置的所有情况都考虑到,不能遗漏。

bool backspaceCompare(string s, string t)
{
    // 从后往前遍历,当前位置要消除的元素个数
    int skip_s = 0;
    int skip_t = 0;

    // s/t最后一个元素的索引
    int i = s.size() - 1;
    int j = t.size() - 1;

    while(true)
    {
        // 1.对s的字符往前遍历,寻找满足要求的字符
        while(i >= 0)
        {
            if(s[i] == '#')   // 当前为#,则累加要删除的元素个数,指针前移
            {
                skip_s++;
                i--;
            }
            else   // 当前不是#,则根据要删除的元素个数,指针前移
            {
                if(skip_s > 0)  // 需要前移,则前移
                {
                    skip_s--;
                    i--;
                }
                else    // 不需要前移,则找到了当前需要比较的的s[i]
                {
                    break;
                }
            }
        }

        // 2.对t的字符执行上述相同的操作
        while(j >= 0)
        {
            if(t[j] == '#')   // 当前为#,则累加要删除的元素个数,指针前移
            {
                skip_t++;
                j--;
            }
            else   // 当前不是#,则根据要删除的元素个数,指针前移
            {
                if(skip_t > 0)  // 需要前移,则前移
                {
                    skip_t--;
                    j--;
                }
                else    // 不需要前移,则找到了当前需要比较的的t[j]
                {
                    break;
                }
            }
        }

        // 3.运行到这里,找到了需要匹配的s[i]和t[j]
        if(i == -1 && j == -1)  // 如果都到了尽头,说明相等
        {
            return true;
        }
        else if(i != -1 && j != -1)  // 如果都没有到尽头,则需要判断是否相等
        {
            if(s[i] != t[j])
            {
                return false;
            }
            else   // 否则当前字符相等,就要i--,j--,继续判断之前的字符
            {
                i--;
                j--;
            }
        }
        else   // 如果一个到尽头,一个没到尽头,肯定不相等
        {
            return false;
        }  
    }

    return true;   //不可能运行到这里
}
  • 时间复杂度:O(n + m)
  • 空间复杂度:O(1)

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

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

相关文章

MySQL数据库的索引

文章目录一、索引是什么&#xff1f;索引的作用二、索引的使用查看索引创建索引删除索引三、索引的底层一、索引是什么&#xff1f; 索引是一种特殊的文件&#xff0c;包含着对数据表里所有记录的引用指针。可以对表中的一列或多列创建索引&#xff0c;并指定索引的类型&#…

[附源码]java毕业设计医疗预约系统

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

SQL注入原理、过程、防御方案、RASP概念

一、sql注入原理 SQL注入即是指web应用程序对用户输入数据的合法性没有判断或过滤不严,攻击者可以在web应用程序中事先定义好的语句上添加额外的SQL语句,在管理员不知情的情况下实现非法操作,以此来实现欺骗数据库服务器执行非授权的任意查询,从而进一步得到相应的数据信息…

第1关:Hive的安装与配置

为了完成本关任务&#xff0c;你需要掌握&#xff1a; 1.Hive的基本安装&#xff1b; 2.Mysql的安装与设置&#xff1b; 3.Hive 的配置。 注意&#xff1a;本关实训Hive的安装与配置建立在Hadoop已安装配置好的情况下。 Hive 的基本安装 从 官网 下载Hive二进制包&#xf…

优维科技CTO黎明访谈实录:“大场景+小算法”构建AiOps运维技术哲学

智能运维、自动化运维发展到现在&#xff0c;已经有将近7成的IT管理者学会利用大数据、人工智能产品及解决方案赋能团队&#xff0c;在生产效率、适应性和决策能力等层面实现了切实有效的正向转型。 今天的中国企业&#xff0c;已经在云端新基建、数字化转型的浪潮中实现降本增…

美食杰项目 -- 菜品信息(五)

目录前言&#xff1a;具体实现思路&#xff1a;步骤&#xff1a;1. 展示美食杰菜谱大全效果2. 引入element-ui3. 代码总结&#xff1a;前言&#xff1a; 本文给大家讲解&#xff0c;美食杰项目中 实现菜品信息页的效果&#xff0c;和具体代码。 具体实现思路&#xff1a; 跳转…

[附源码]java毕业设计疫情防控期间人员档案追寻系统设计与实现论文

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

bash shell 初体验-尚文网络xUP楠哥

~~全文共1139字&#xff0c;阅读需约5分钟。 进Q群11372462&#xff0c;领取专属报名福利&#xff0c;包含云计算学习路线图代表性实战训练大厂云计算面试题资料! # bash shell 简介 我们在操作Linux系统时&#xff0c;绝大部分情况是通过命令行的方式输入指令&#xff0c;Li…

小型企业建立人力资源团队的 5 个步骤

作为小企业主&#xff0c;设置人力资源运营可能不是您的首要任务。但是&#xff0c;随着您扩大运营规模和员工人数&#xff0c;您可能会遇到合规性和员工敬业度问题&#xff0c;从而阻碍您的业务增长。组建一个团队来照顾您的人力资源运营和员工可以让您专注于改进您的产品和满…

【JVM】字节码技术:手撕 多态执行原理

一、源文件 package org.example.classLoading;import java.io.IOException; /*** 演示多态原理&#xff0c;注意加上下面的 JVM 参数&#xff0c;禁用指针压缩* -XX:-UseCompressedOops -XX:-UseCompressedClassPointers*/ public class PolymorphicTest {public static void…

【序列召回推荐】(task2)序列召回GRU4Rec和faiss使用

学习总结&#xff1a; 一般的RNN模型我们的输入和输出是什么&#xff0c;我们对RNN输入一个序列 X[x1,x2,...,xn]X [x^1,x^2,...,x^n]X[x1,x2,...,xn] &#xff0c;注意我们序列中的每一个节点都是一个向量&#xff0c;那么我们的RNN会给我们的输出也是一个序列 Y[y1,y2,...,…

[附源码]SSM计算机毕业设计江苏策腾智能科技公司人事管理系统JAVA

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

.net----特性

特性特性的概念和使用特性&#xff08;Attribute&#xff09;特性形式特性类参数预定义通用特性类ConditionalAttribute类ObsoleteAttribute类AttributeUsageAttribute类全局特性自定义特性类使用反射访问特性特性的概念和使用 特性&#xff08;Attribute&#xff09; 特性类&…

http请求报头header

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 目录 前言 一.认识请求报头&#xff08;header&#xff09; 1.Host 2.content-length 3.content-type 常见的三种格式 小结 二.User-Agent(简称UA) 三.Referer 四.C…

进程创建进程终止进程等待

目录前言一、进程创建1.fork()函数&#xff08;1&#xff09;fork()函数的基本认识进程调用fork()函数之后&#xff0c;控制权转移到内核中的fork()代码之后&#xff0c;内核做了啥&#xff1f;&#xff08;2&#xff09;实验&#xff1a;使用fork()函数创建进程&#xff08;3&…

跨境电商卖家必知的【圣诞节营销】终极指南(一)

关键词&#xff1a;圣诞节营销、跨境电商卖家 不知不觉又到了年底&#xff0c;而对于跨境电商来说也是非常重要的一段促销时期&#xff0c;也许您已经制定了相关的圣诞节营销大促&#xff0c;但今天我们还是想告诉您一些2022年非常棒的销的创意想法&#xff0c;希望能帮助您提升…

Spring Cloud Alibaba(四)

openFeign配置日志 一、openFeign的日志级别&#xff1a; NONE&#xff1a;不记录日志 (默认). BASIC&#xff1a;只记录请求方法、url、响应状态码和执行时间。 HEADERS&#xff1a;在basic的基础上&#xff0c;增加请求和响应头 FULL&#xff1a;记录请求和响应的头、body…

PyTorch搭建RNN联合嵌入模型(LSTM GRU)实现视觉问答(VQA)实战(超详细 附数据集和源码)

需要源码和数据集请点赞关注收藏后评论区留言私信~~~ 一、视觉问题简介 视觉问答&#xff08;VQA&#xff09;是一种同时设计计算机视觉和自然语言处理的学习任务。简单来说&#xff0c;VQA就是对给定的图片进行问答&#xff0c;一个VQA系统以一张图片和一个关于这张图片形式自…

用HTML+CSS+JS写的切水果小游戏它来了

前言 切水果游戏曾经是一款风靡手机的休闲游戏&#xff0c;今天要分享的就是一款网页版的切水果游戏&#xff0c; 由HTMLCSSJS实现&#xff0c;虽然功能和原版的相差太大&#xff0c;但基本的功能具备&#xff0c;效果逼真。感兴趣的小伙伴可收藏学习&#xff08;完整源码在文…

Heterogeneous Parallel Programming 异构并行编程 - UIUC伊利诺伊大学(持续更新)

Lecture 11.2 Introduction to Heterogeneous异构1.3 Portability and Scalability1.4 Introduction to CUDA 数据并行化 and 执行模型1.5 Introduction to CUDA 内存模型 and 基本函数API1.6 Introduction to CUDA Kernel-based SPMD1.7 更高维的Grid的Kernel-based SPMD例子1…