【数据结构和算法】压缩字符串

news2024/11/17 6:22:24

其他系列文章导航

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

设计模式合集

多线程合集

分布式合集

ES合集


文章目录

其他系列文章导航

文章目录

前言

一、题目描述

二、题解

2.1 方法一:双指针

三、代码

3.1 方法一:双指针

四、复杂度分析


前言

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


一、题目描述

题目有点小坑,在下面提到了。

给你一个字符数组 chars ,请使用下述算法压缩:

从一个空字符串 s 开始。对于 chars 中的每组 连续重复字符 :

  • 如果这一组长度为 1 ,则将字符追加到 s 中。
  • 否则,需要向 s 追加字符,后跟这一组的长度。

压缩后得到的字符串 s 不应该直接返回 ,需要转储到字符数组 chars 中。需要注意的是,如果组长度为 10 或 10 以上,则在 chars 数组中会被拆分为多个字符。

请在 修改完输入数组后 ,返回该数组的新长度。

你必须设计并实现一个只使用常量额外空间的算法来解决此问题。(说白了就是要在原字符数组上改)

示例 1:

输入:chars = ["a","a","b","b","c","c","c"]
输出:返回 6 ,输入数组的前 6 个字符应该是:["a","2","b","2","c","3"]
解释:"aa" 被 "a2" 替代。"bb" 被 "b2" 替代。"ccc" 被 "c3" 替代。

示例 2:

输入:chars = ["a"]
输出:返回 1 ,输入数组的前 1 个字符应该是:["a"]
解释:唯一的组是“a”,它保持未压缩,因为它是一个字符。

示例 3:

输入:chars = ["a","b","b","b","b","b","b","b","b","b","b","b","b"]
输出:返回 4 ,输入数组的前 4 个字符应该是:["a","b","1","2"]。
解释:由于字符 "a" 不重复,所以不会被压缩。"bbbbbbbbbbbb" 被 “b12” 替代。

提示:

  • 1 <= chars.length <= 2000
  • chars[i] 可以是小写英文字母、大写英文字母、数字或符号

注:这个题是要求修改原数组,即在原空间,然后,返回新的长度,在测试机中的是根据我们计算出来的新长度来输出而不是使用chars.length或者char ch:chars之类的控制输出。


二、题解

2.1 方法一:双指针

思路与算法:

首先我们要令输入数组 chars 长度为 n。

使用两个指针 i 和 j 分别指向「当前处理到的位置」和「答案待插入的位置」:

  1. 当字符一样的时候,i 指针一直往后处理,每次找到字符相同的连续一段 [i,idx),令长度为 cnt;
  2. 将当前字符插入到答案,并让 j 指针后移:chars [j++] = chars [i];
  3. 检查 cnt 的长度是否大于 1,如果大于 1,需要将数字拆分存储。由于简单的实现中,我们只能从个位开始处理 cnt,因此需要使用 start 和 end 记录下存储数字的部分,再处理完 cnt 后,将 [start,end) 部分进行翻转,并更新 j 指针;
  4. 最后我们更新 i 为 idx,代表循环处理下一字符。

三、代码

3.1 方法一:双指针

Java版本(带注释):

class Solution {
    public int compress(char[] chars) {
        int len = chars.length;
        int i = 0; //当前处理下标
        int j = 0; //当前被替换下标

        while(i < len) {
            int idx = i;
            //找连续相同字符
            while(idx < len && chars[idx] == chars[i]) idx++; 
            int cnt = idx - i; //连续相同字符长度
            chars[j++] = chars[i];//要替换的下标对准 连续字符串 的第一个下标
            if(cnt > 1) {
                int start = j, end = start;
                //替换cnt
                while(cnt != 0) {
                    chars[end++] = (char)(cnt % 10 + '0');
                    cnt /= 10;
                }
                //由于从个位开始替换, 需要将数字翻转
                reverse(chars, start, end-1);
                //替换完成后, 更新j
                j = end;
            }
            i = idx;//处理完一串, 移动下标
        }
        return j;
    }

    //翻转chars 下标start .. 下标end 之间的字符
    void reverse(char[] chars, int start, int end) {
        while(start < end) {
            char tmp = chars[start];
            chars[start] = chars[end];
            chars[end] = tmp;
            start++;
            end--;
        }
    }
}

C++版本:

#include <vector>
#include <string>
using namespace std;

class Solution {
public:
    int compress(vector<char>& cs) {
        int n = cs.size();
        int i = 0, j = 0;
        while (i < n) {
            int idx = i;
            while (idx < n && cs[idx] == cs[i]) idx++;
            int cnt = idx - i;
            cs[j++] = cs[i];
            if (cnt > 1) {
                int start = j, end = start;
                string cnt_str = to_string(cnt);
                for (char c : cnt_str) {
                    cs[end++] = c;
                }
                reverse(cs, start, end - 1);
                j = end;
            }
            i = idx;
        }
        return j;
    }

    void reverse(vector<char>& cs, int start, int end) {
        while (start < end) {
            char t = cs[start];
            cs[start] = cs[end];
            cs[end] = t;
            start++; end--;
        }
    }
};

C++简洁版: 

class Solution {
public:
    int compress(vector<char>& chars) {
        int i=0,j=0,n=chars.size();
        while(i<n){
            int idx=i;
            while(idx<n && chars[idx]==chars[i]) idx++;
            int cnt=idx-i;
            chars[j++]=chars[i];
            if(cnt>1){
                string s=to_string(cnt);
                for(auto c:s) chars[j++]=c;
            }
            i=idx;
        }
        return j;
    }
};

Python版本:

def compress(cs):
    n = len(cs)
    i, j = 0, 0
    while i < n:
        idx = i
        while idx < n and cs[idx] == cs[i]:
            idx += 1
        cnt = idx - i
        cs[j] = cs[i]
        j += 1
        if cnt > 1:
            start = j
            end = start
            cnt_str = str(cnt)
            for c in cnt_str:
                cs[end] = c
                end += 1
            cs[start:end] = cs[start:end][::-1]
            j = end
        i = idx
    return j

四、复杂度分析

没有用到除常量以外额外的空间,满足题目的要求!

  • 时间复杂度:O(n)
  • 空间复杂度:O(1)

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

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

相关文章

如何搭建适合自己的数字人源码系统?

随着数字人技术的快速发展&#xff0c;数字人直播软件成为了直播行业的热门话题。数字人源码部署成为了创业者在这个领域看中的新商机&#xff0c;数字人直播软件给市场带来很多机会的同时也给商家带来了更多的收益。但是&#xff0c;选择一个适合自己的数字人直播软件源码并不…

模型数据-HttpServletRequest使用

模型数据-HttpServletRequest使用 三种情况 自己也要添加一些属性到Request域中,可以通过原生Servlet API的request来设置.也可以修改按照默认机制已经放进去 的某些对象.明白默认情况下存放的名字其实就是类名/类型名 首字母小写.(虽然monster100改了,但还是按类名首字母小写…

大模型时代-从0开始搭建大模型

开发一个简单模型的步骤&#xff1b; 搭建一个大模型的过程可以分为以下几个步骤&#xff1a; 数据收集和处理模型设计模型训练模型评估模型优化 下面是一个简单的例子&#xff0c;展示如何使用Python和TensorFlow搭建一个简单的大模型。 数据收集和处理 首先&#xff0c;我…

node-static 任意文件读取漏洞复现(CVE-2023-26111)

0x01 产品简介 node-static 是 Node.js 兼容 RFC 2616的 HTTP 静态文件服务器处理模块&#xff0c;提供内置的缓存支持。 0x02 漏洞概述 node-static 存在任意文件读取漏洞&#xff0c;攻击者可通过该漏洞读取系统重要文件&#xff08;如数据库配置文件、系统配置文件&#…

Java使用Microsoft Entra微软 SSO 认证接入

1. Microsoft Entra Microsoft Entra ID 是基于云的标识和访问管理服务&#xff0c;可帮助员工访问外部资源。 示例资源包括 Microsoft 365、Azure 门户以及成千上万的其他 SaaS 应用程序。 Microsoft Entra ID 还可帮助他们访问你的企业 Intranet 上的应用等内部资源&#x…

行业报告 | 中国工业机器人的“春天”

原创 | 文 BFT机器人 前言&#xff1a; 工业机器人是先进制造业中不可替代的重要装备&#xff0c;是衡量国家制造业水平和科技水平的重要标志。中国作为世界公认的制造业第一大国&#xff0c;随着人口红利的逐渐消退&#xff0c;劳动力成本不断提高&#xff0c;生产自动化和发…

纺织辅料企业网站搭建的效果如何

纺织品是日常生活必需品&#xff0c;服装、鞋帽箱包等品牌企业很多&#xff0c;纺织辅料的需求度也很高&#xff0c;对企业商家来说&#xff0c;市场高需求度的同时也面临着一些痛点&#xff1a; 1、品牌宣传、产品展示难 纺织辅料产品属于国内外都可以拓展&#xff0c;并没有…

Node.js创建一个简单的WebSocket接口,实现通信交互

Node.js创建一个简单的WebSocket接口&#xff0c;实现通信交互 一、为什么使用WebSocket&#xff1f; WebSocket&#xff0c;最大特点就是&#xff0c;服务器可以主动向客户端推送信息&#xff0c;客户端也可以主动向服务器发送信息&#xff0c;是真正的双向平等对话&#xf…

Paper Reading: (U2PL) 基于不可靠伪标签的半监督语义分割

目录 简介目标/动机方法Pseudo-LabelingUsing Unreliable Pseudo-Labels 补充知识InfoNCE LossOHEM 实验Comparison with Existing AlternativesAblationEffectiveness of Using Unreliable Pseudo-LabelsAlternative of Contrastive Learning 总结附录U2PL 与 negative learni…

Unity之OpenXR+XR Interaction Toolkit接入Meta Quest3

前言 随着备受期待的Meta Quest 3与今年10月10日发布,这款来自Meta的下一代VR游戏头戴设备承诺将彻底改变您的游戏方式。 Meta Quest 3,玩家只需轻松一触即可在虚拟现实和真实世界之间无缝切换,无需摘下头戴设备进行快速现实检查。 Meta Quest 3最引人注目的特点之一是其能…

大数据讲课笔记1.2 Linux用户操作

文章目录 零、学习目标一、导入新课二、新课讲解&#xff08;一&#xff09;用户账号管理1、用户与用户组文件2、用户账号管理工作 &#xff08;二&#xff09;用户操作1、切换用户&#xff08;1&#xff09;语法格式&#xff08;2&#xff09;切换到普通用户&#xff08;3&…

Axure元件库的使用

1.基本元件库 1.1Axure的画布范围 Axure是一个绘制项目原型图的软件&#xff0c;它里面的基本原件有&#xff1a; 1.1元件的呈现范围 首先我们要了解基本元件的作用范围在哪里&#xff1f; 浏览效果&#xff1a; 可以看出当我们的基本元件放在画布区域内是可以完全呈现出来…

智能安全用电监控管理系统

智能用电安全监控管理系统是一种基于物联网技术和大数据分析的智能化管理系统&#xff0c;用于监控和管理电力设备的安全运行。该系统依托电力智慧运维工具-电易云&#xff0c;可以实时监测电力设备的运行状态、电力负荷、用电行为等信息&#xff0c;通过智能算法识别设备的异常…

图像截屏公式识别——LaTeX-OCR安装与使用

一、简介 LaTeX-OCR 是一个开源的光学字符识别&#xff08;OCR&#xff09;软件&#xff0c;专为 LaTeX 文档提供支持。其主要目的是帮助用户将扫描的文档转换为 LaTeX 编辑器可以使用的可编辑文本&#xff0c;从而方便进行修改、编辑和排版。LaTeX广泛用于科技、数学、工程等…

leetcode--3. 无重复字符的最长子串[滑动窗口\哈希表 c++]

原题 &#xff1a; 3. 无重复字符的最长子串 - 力扣&#xff08;LeetCode&#xff09; 题目解析&#xff1a; 最长子串可以用滑动窗口解决&#xff0c;无重复字符可以使用哈希表解决。 算法原理&#xff1a; 滑动窗口哈希表 哈希表作为一个数组存放每个字符出现的次数。 …

串口通信(4)-C#串口通信入门实例

本文通过实例讲解C#串口通信。 入门实例设计一个串口助手&#xff0c;能够很好的涵盖串口要点的使用。 目录 一、成品图 二、界面文件 三、后台代码 四、实例中要点 一、成品图 如下&#xff1a; 实现的过程 创建winform项目&#xff0c;将Form1文件的名称改为MainForm&…

【LeetCode刷题】-- 171.EXcel表列序号

171.EXcel表列序号 方法&#xff1a;进制转换 class Solution {public int titleToNumber(String columnTitle) {//进制转换int number 0;int mul 1;for(int i columnTitle.length()-1;i>0;i--){int k columnTitle.charAt(i) - A 1;number mul * k;mul * 26;}return …

1+X大数据平台运维职业技能等级证书中级

该部分是选择题部分&#xff0c;实操题在主页的另一篇文章 考试名称&#xff1a;“1X”大数据平台运维职业技能等级证书&#xff08;中级&#xff09; 1X 大数据平台运维中级测试题一、单选题 以下哪种情况容易引发 HDFS 负载不均问题&#xff1f;&#xff08; C&#xff09…

解决高风险代码:Unreleased Resource: Streams

Abstract 程序可能无法成功释放某一项系统资源。 Explanation 程序可能无法成功释放某一项系统资源。 资源泄露至少有两种常见的原因&#xff1a; &#xff0d; 错误状况及其他异常情况。 &#xff0d; 未明确程序的哪一部份负责释放资源。 大部分 Unreleased Resource 问题只…

定制软件开发的 5 个挑战

对于大公司来说&#xff0c;定制软件开发就像是眼中钉。无论您是要创建内部使用的工具、自动化手动流程还是推出新产品&#xff0c;从头开始构建它历来都是昂贵且危险的。花钱购买领先的现成解决方案之一&#xff0c;却不得不花费更多的时间和金钱对其进行定制来完成工作&#…