面试 | 双法妙解压缩字符串【遍历统计 + 双指针】

在这里插入图片描述

一、题目描述

原题传送门

在这里插入图片描述

二、思路分析

首先我们来分析一下解决本题所需要的思路

  • 题目的意思很简单,就是统计原本的字符串中的每个字符出现的次数,然后以【字符,出现的次数】这样的结构来字符串,以起到一个压缩的效果,那么对于这样的结构,详细很多力友都会想到map这个键值对的结构,但是认真查看题目本身的话却发现我们不可以用这种结构

输入:“aabcccccaaa”
输出:“a2b1c5a3”

  • 我们以第一个为例,从左往右分别是2个a、1个b、5个c和3个a,此时若我们通过map去做遍历的话,开头的【a】和结尾的【a】就会合并在一起变为5个a,那么最后在拼接字符串的时候就会出现问题,所以map的这种结构我们是不能使用
unordered_map<char, int> count
for(char c : S)
{
    count[c]++;
}

接下去就来看看下面的两种做法👇

Way1 : 遍历统计

  • 首先是第一种方法,既然题目给到了一个字符串,那我们就去遍历它并进行一个统计,那既然是统计某个字符出现了多少次的话,就需要有一个字符变量去记录,这里我们拿ch首先保存下第一个字符,后面遍历的时候再做更新
char ch = S[0]; 
  • 当然,我们还需要一个计数器cnt
  • 接下去这段逻辑就是在遍历这个字符串的同时去统计里面的每个字符出现了多少次,如果当前所遍历的字符和ch是相同的话,计数器cnt就去做一个累加,如果不相同的话,我们就可以去拼接字符串了,ch即为当前所需要统计的字符,cnt即为这个字符所出现的次数,不过我们要使用到C++里的一个库函数叫做 to_string ,不清楚的力友可以先去了解一下
  • 当这个字符拼接完后,我们就要去统计下一个字符了,这个时候就要更新【ch】和【cnt】了
string compressStr = "";
for(int i = 1;i < sz; ++i)
{
    if(S[i] == ch){
        cnt++;      // 如果当前所遍历到的字符与需统计字符相同的话,则计数器 + 1
    }else{
        compressStr += ch + to_string(cnt);
        ch = S[i];
        cnt = 1;
    }
}
  • 最后呢,在遍历结束之后我们还需要在去做一个拼接,因此当最后遍历最后跳出循环并没有把最后一个字符给拼接上去
// 最后在遍历结束后添加最后一个字符的统计结果
compressStr += ch + to_string(cnt);
  • 当字符拼接完后,就将其返回,但是题目中说到如果压缩之后的字符串长度比原字符串还长的话,就返回原先的串
return compressStr.size() >= sz ? S : compressStr;
  • 不过这里还有隐藏的一个测试案例,我们应该要考虑到压缩后的字符串和原串相等的情况,也是需要返回原串的

1.jpg

代码展示:

class Solution {
public:
    string compressString(string S) {
        int sz = S.size();

        if(sz == 0)
            return S;   // 如果是空串的话,则返回自己本身

        string compressStr = "";
        int cnt = 1;        // 统计每一个字符个数
        char ch = S[0];     // 记录当前所要统计的字符

        // 循环直接从1开始即可,第一个字符一定算一个
        for(int i = 1;i < sz; ++i)
        {
            if(S[i] == ch){
                cnt++;      // 如果当前所遍历到的字符与需统计字符相同的话,则计数器 + 1
            }else{
                compressStr += ch + to_string(cnt);
                ch = S[i];
                cnt = 1;
            }
        }
        // 最后在遍历结束后添加最后一个字符的统计结果
        compressStr += ch + to_string(cnt);

        // 三目运算符:若是压缩后的字符串长度 >= 原字符串的长度,则返回原串
        return compressStr.size() >= sz ? S : compressStr;
    }
};

最后展示一下AC后的结果

2.jpg

Way2 : 双指针

接下去要介绍的就是另一种解法,此解法来自 K神 很是巧妙,力友可以学习一下这种解法

图解分析

总体思路概述:

  • 这种方法很巧妙地利用了双指针,首先让指针ij指向当前字符串的首位,然后让指针j不断地先后遍历,比较 s[i] 和 s[j] 的的字符是否相同,若是相同的话则让j继续后移,直到二者不相同为止。
  • 此时我们便去计算当前的这个字符出现了多少次,使用【指针 - 指针】的办法算出来。然后再去统计下一个字符的位置,此时让i移动到j的位置来即可,因为二者不相同后j一定指向了一个新的字符
  • 然后继续重复上面的逻辑就可以了,直到这个字符串遍历完之后也就压缩完了

然后我们就根据 示例1 来分布细述一下

  • 首先双指针都指向字符串的首位置

3.jpg

  • 然后因为【a = a】,所以j++i不动

4.jpg

  • 继续还是一样,【a = a】,j++

5.jpg

  • 那么接下来【a != b】,遇到不相等了,此时我们就需要去统计当前这个字符所出现的此处,使用j - i就可以计算得到,那么此时就可以将这结果追加到压缩后的字符串中了。接下去便是更新指针i的位置到j这里来,进行下一个字符串个数的统计

6.jpg

  • 接下去就开始统计字符b出现的个数了,但是呢在比较了一次够就不相等了,于是立马就得出这个字符只出现了一次,步骤和上述一样

7.jpg

  • 接下去就是字符【c】了,利用j - i可以算出其出现了5次,继续拼接到压缩串compressStr中

8.jpg

  • 最后当这个串遍历完之后,因为没有再进入循环了,所以我们在最后还要拼接一次

9.jpg

  • 最后的话当我们要返回结果的时候还需要比较一下压缩后的串和原串的长度,只有当压缩后的串来得短的时候才可返回,否则一律返回原串

10.jpg

代码展示:

class Solution {
public:
    string compressString(string S) {
        if(S.size() == 0)   return S;
        int i = 0, j = 0;
        string compressStr = "";

        while(j < S.size())
        {
            // 持续比较双指针上的位置,直到不相同为为止
            while(S[i] == S[j]){
                j++;
            }
            compressStr += S[i];
            compressStr += to_string(j - i);
            i = j;      // i换位到新字符的位置
        }
        
        return compressStr.size() >= S.size() ? S : compressStr; 
    }
};

最后从提交的结果就可以看出效率提升了不少 ↑

11.jpg

认真看完上面这个例子后,其他的示例相信你一定也能推敲出来🌹

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

概率论和随机过程的学习和整理--番外16,N合1的合成问题的求平均个数,次数,阶数

目录 1 问题 2 用条件期望&#xff0c;求合成的次数 2.1 思路1 2.2 思路2 3 用条件期望&#xff0c;求合成的个数 3.1 令X表示用材料1往上合成时&#xff0c;合成材料2的个数 3.2 令Y表示用材料1往上合成时&#xff0c;合成材料3的个数 4 用条件期望&#xff0c;求合成…

【算法基础:数学知识】4.4 快速幂

文章目录 快速幂例题列表875. 快速幂⭐⭐⭐⭐⭐&#xff08;重要&#xff01;&#xff09;代码写法1——递归代码写法2——迭代递归写法 与 迭代写法的 对比 876. 快速幂求逆元&#x1f6b9;&#xff08;需要理解逆元的概念&#xff09;TODO乘法逆元介绍解法代码 快速幂 https…

[MySQL]MySQL用户管理

[MySQL]MySQL用户管理 文章目录 [MySQL]MySQL用户管理1. 用户的概念2. 用户信息3. 创建用户4. 修改用户密码5. 删除用户6. MySQL中的权限7. 给用户授权8. 回收权限 1. 用户的概念 MySQL中的用户分为超级用户&#xff08;root&#xff09;和普通用户。超级用户的操作是不受权限…

奇舞周刊第500期:TQL,巧用 CSS 实现动态线条 Loading 动画

记得点击文章末尾的“ 阅读原文 ”查看哟~ 下面先一起看下本期周刊 摘要 吧~ 奇舞推荐 ■ ■ ■ TQL&#xff0c;巧用 CSS 实现动态线条 Loading 动画 最近&#xff0c;群里有个很有意思的问题&#xff0c;使用 CSS 如何实现如下 Loading 效果&#xff1a; leaferjs&#xff0c…

4.3 Bootstrap CSS编码规范

文章目录 Bootstrap CSS编码规范语法声明顺序不要使用 import媒体查询&#xff08;Media query&#xff09;的位置带前缀的属性单行规则声明简写形式的属性声明Less 和 Sass 中的嵌套注释class 命名选择器代码组织编辑器配置 Bootstrap CSS编码规范 语法 用两个空格来代替制表…

Java方法重载和Java方法重写

Java方法重载 Java允许同一个类中定义多个同名方法&#xff0c;只要它们的形参列表不同即可。如果同一个类中包含了两个或两个以上方法名相同的方法&#xff0c;但形参列表不同&#xff0c;这种情况被称为方法重载&#xff08;overload&#xff09;。 例如&#xff0c;在 JDK …

【多模态】16、DetCLIP | 构建超大词汇字典来进行开放世界目标检测

论文&#xff1a;DetCLIP: Dictionary-Enriched Visual-Concept Paralleled Pre-training for Open-world Detection 代码&#xff1a;无。。。 出处&#xff1a;NIPS2022 | 华为诺亚方舟 | 中山大学 | 香港科技大学 效果&#xff1a; 在 LVIS 的 1203 个类别上超越了 GLIP…

深入学习 Redis - 深挖经典数据类型之 list

目录 前言 一、list 类型 1.1、操作命令 lpush / rpush&#xff08;插入元素&#xff09; lrange&#xff08;查看范围元素&#xff09; lpushx / rpushx &#xff08;有约束的插入&#xff09; lpop / rpop&#xff08;头删尾删&#xff09; lindex&#xff08;获取下…

实现锂电池形状的数据可视化css+js

1.效果图 2.需求根据后端返回数据改变里面的高度 HTML&#xff1a; <div class"dianchichi"><div class"limian" id"divElementId"></div></div> css: .dianchichi {width: 84px;height: 146px;display: flex;justify-…

【Visual Studio】Qt 在其他 cpp 文件中调用操作 ui 界面控件

知识不是单独的&#xff0c;一定是成体系的。更多我的个人总结和相关经验可查阅这个专栏&#xff1a;Visual Studio。 还整了一个如何相互之间调用函数的文章&#xff0c;感兴趣可以看&#xff1a;【Visual Studio】Qt 在其他 cpp 文件中调用主工程下文件中的函数。 文章目录 …

react 实现小球加入购物车动画

代码 import React, { useRef } from react;const ProductLayout () > {const box useRef(null);const createBall (left, top) > {const ball document.createElement(div);ball.style.position absolute;ball.style.left left - 10 px;ball.style.top top - 1…

四个现实中的商品样例,帮助你理解如何使用css【前端CSS入门样例】

实现商品列表 <!DOCTYPE html> <html><head><meta charset"utf-8"><title>商品列表图片</title><style>.row > img {width: 15%;}</style></head><body><div class"row"><img sr…

C/C++ 程序 IDE 开发工具 CLion

下载地址&#xff1a; https://www.jetbrains.com/clion/ https://www.jetbrains.com/clion/ 下载地址&#xff1a; https://www.jetbrains.com/clion/download/ https://www.jetbrains.com/clion/download/ 历史版本&#xff08;老版本&#xff09;下载地址&#xff1a; h…

计算机科学cs/电子信息ei面试准备——python复习|理解题|简答题

目录 1 请简要概述python技术的主要应用场景? 2 python的基本数据类型是那几种? 3 python数组和列表有什么区别? 4 Python中的函数是什么&#xff1f; 5 请写出删除列表中的元素有几种方式? 6 描述python函数中递归的理解? 7 请介绍join()和split()的区别? 8 介绍…

每天五分钟机器学习:多项式非线性回归模型

本文重点 在前面的课程中,我们学习了线性回归模型和非线性回归模型的区别和联系。多项式非线性回归模型是一种用于拟合非线性数据的回归模型。与线性回归模型不同,多项式非线性回归模型可以通过增加多项式的次数来适应更复杂的数据模式。在本文中,我们将介绍多项式非线性回…

dpdpdp

这里写目录标题 139. 单词拆分322. 零钱兑换300. 最长递增子序列120. 三角形最小路径和64. 最小路径和63. 不同路径 II5. 最长回文子串&#xff08;回文dp&#xff09;⭐97. 交错字符串⭐&#xff08;抽象成路径问题&#xff09;221. 最大正方形⭐ 139. 单词拆分 class Soluti…

文心千帆为你而来

1. 前言 3月16号百度率先发布了国内第一个人工智能大语言模型—文心一言。文心一言的发布在业界引起了不小的震动。而文心一言的企业服务则由文心千帆大模型平台提供。文心千帆大模型平台是百度智能云打造出来的一站式大模型开发与应用平台&#xff0c;提供包括文心一言在内的…

Observability:Synthetic monitoring - 动手实践

在我之前的如下文章里&#xff1a; Observability&#xff1a;Synthetic monitoring - 合成监测入门&#xff08;一&#xff09;&#xff08;二&#xff09; Observability&#xff1a;Synthetic monitoring - 创建浏览器监测&#xff0c;配置单独的浏览器监测器及项目 我详…

408-2009

一、选择题&#xff08;2 分/题&#xff09; 1.为解决计算机主机与打印机之间速度不匹配问题&#xff0c;通常设置一个打印数据缓冲区&#xff0c;主机将要输出的数据一次写入该缓冲取&#xff0c;而打印机则依次从该缓冲区中取出数据。该缓冲区的逻辑结构应该是______。 A.栈 …

【JavaEE】Servlet常用的API

目录 前言 一、HttpServlet类 1、Servlet的生命周期 ✨tomcat的两个端口 ✨设置告诉浏览器使用那种字符集解析响应 ✨Java中Unicode和utf8字符集的使用 二、HttpServletRequest类 1、获取请求的信息 2、 前端给后端传递数据的三种方式 2.1、通过query string传递 2.2…