C 去除字符串中重复字母(LeetCode)

news2025/1/11 4:26:29

🌟前言

摆烂太久,好久没有更文了,小九和大家一起看看题写写题找回手感吧,也希望这篇文章可以帮助正在寻找解题答案的朋友,你们的支持就是我最大的动力!求三连!求关注呀!


🌟题目

去除重复字母,给你一个仅包含小写字母的字符串,请你去除字符串中重复的字母,使得每个字母只出现一次。需保证返回结果的字典序最小 (要求不能打乱其他字符的相对位置)示例1:

输入:"bcabc"

输出:"abc"

示例2:

输入:"cbacdcbc"

输出:"acdb" cbad,bacd,adcb

字典序: apple book

  1. 字典序最小,不能出现打乱字母相对位置;

🌟解题前捋清思路

特殊条件

在写代码时要考虑会遇到的特殊情况,例如题目所指的“给你一个仅包含小写字母的字符串”,这个字符串它可能会给一个空字符,或者甚至一个字符,长度为1,这种情况我们就可以不用再进行去重这操作了写代码时,我们也要有这种意识,例如在写链表时,考虑链表为空


记录字母出现频率

用一个数组record记录字符串中字母出现的次数,次数我们遍历一遍字符串即可,因为要统计的是小写字母,而有且只有26个,所以我们的数组定义26个空间即可,record[26]


建字符栈stack

这里的栈呢,本质上就是一个连续的数组,用来模拟栈的思想,但不用完全按照栈的格式去写,我们只需要参考栈的一个特点:“先进后出”,作用:存储去除重复字母的结果,利用栈来正确次序。


遍历字符串

遍历字符串会有一个特殊的地方,那就是当前字符,对其进行判断,在0~top的空间里,判断当前字符是否存在栈中,用一个标记即可

如果已经存在,就让record[s[i]]--,代表去除了一个重复的s[i]位置上对应的字母,表示stack已经有了这个字符,不需要再进行存入又取出,然后继续遍历下一个字符;



若不存在,则通过while循环找到正确位置。以bcabc字符串为例,此时的字符a,通过循环,判断栈中元素是否要出栈,找到a的正确位置

判断条件

  1. 栈不能为空top>-1

  1. 栈顶元素要大于遍历到的当前字符 stack[top]>s[i]

  1. 栈顶字符对应的record>0,(为0代表字符串后面不再有此元素,所以不能出栈)

🌟代码实现

判断特殊直接输出条件

s为空,长度为0;s长度为1,直接输出

    if(s ==NULL || strlen(s) == 0){
        return "";
    }
    if(strlen(s) == 1){
        return s;
    }

实现两个数组,一个用来计数一个用来做栈

//写两个数组,一个record一个stack
    char record[26] = {0};
    int len = (int)strlen(s);   //先看字符串长度是多少
    //申请一个空间,指向字符数组
    char *stack = (char *)malloc(len * sizeof(char)+1);
    //对stack赋初值
    memset(stack, 0, len * sizeof(char)+1);

    int top = -1;

此处的空间开辟有伏笔,末尾的+1是为了输出成字符串,在程序运行的最后会让stack的最后一个位置加上‘\0’,所以此时+1空间正好

 //统计字母出现次数
    int i;
    for(i = 0;i< len; i++){
        /*s[i]若为a,则s[i]-'a'=0,所表达的意思就是record[0]这个位置
        +1,就这样记录下了a的个数,同理,s[i]为b,则s[i]-'a'=1,record[1]++*/
        record[s[i]-'a']++;
    }

    //遍历字符串s
    for(i = 0; i<len;i++){
        //定义一个标记,标记当前字母是否已经存在在stack里,0表示不存在
        int isExist = 0;

        for(int j = 0; j<=top; j++){
                if(s[i] == stack[j]){
                    isExist = 1;
                    break;
                }
        }
}

给字符元素标记,标记与栈中相同时就把它的record移除一位,然后若不存在于栈中,就进行while循环给它找出合适的位置(字典序最小)

if(isExist == 1){
            record[s[i]-'a']--;
        }else{
            //栈不为空;栈顶元素大于当前元素;栈顶元素还有
            while(top > -1 && stack[top] > s[i] && record[stack[top]-'a'] > 1){
                //跳出该元素,频次减一
                record[stack[top]-'a']--;
                //出栈
                top--;
            }

            top++;
            stack[top] = s[i];
        }
    }
    //此时stack只是一个字符数组,要变成字符串还要进行如下操作
    stack[++top] = '\0';
    return stack;

附上leetcode运行结果,可能是卡bug了,不应该是0ms哈哈

完整代码如下:

#include <stdio.h>
#include <stdlib.h>

char *removeDuplicateLetters(char *s){
    /*s为空,长度为0;s长度为1,直接输出*/
    if(s ==NULL || strlen(s) == 0){
        return "";
    }
    if(strlen(s) == 1){
        return s;
    }

    //写两个数组,一个record一个stack
    char record[26] = {0};
    int len = (int)strlen(s);   //先看字符串长度是多少
    //申请一个空间,指向字符数组
    char *stack = (char *)malloc(len * sizeof(char)+1);
    //对stack赋初值
    memset(stack, 0, len * sizeof(char)+1);

    int top = -1;

    //统计字母出现次数
    int i;
    for(i = 0;i< len; i++){
        /*s[i]若为a,则s[i]-'a'=0,所表达的意思就是record[0]这个位置
        +1,就这样记录下了a的个数,同理,s[i]为b,则s[i]-'a'=1,record[1]++*/
        record[s[i]-'a']++;
    }

    //遍历字符串s
    for(i = 0; i<len;i++){
        //定义一个标记,标记当前字母是否已经存在在stack里,0表示不存在
        int isExist = 0;

        for(int j = 0; j<=top; j++){
                if(s[i] == stack[j]){
                    isExist = 1;
                    break;
                }
        }
        if(isExist == 1){
            record[s[i]-'a']--;
        }else{
            //栈不为空;栈顶元素大于当前元素;栈顶元素还有
            while(top > -1 && stack[top] > s[i] && record[stack[top]-'a'] > 1){
                //跳出该元素,频次减一
                record[stack[top]-'a']--;
                //出栈
                top--;
            }

            top++;
            stack[top] = s[i];
        }
    }
    //此时stack只是一个字符数组,要变成字符串还要进行如下操作
    stack[++top] = '\0';
    return stack;
}


int main(int argc,const char * argv[]){

    system("pause");
    return 0;
}

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

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

相关文章

信息系统项目管理师第4版教材的变化:PMBOK第六版和第七版的叠加

昨天下午&#xff0c;软考官方网站突然发布了第4版考纲和教材&#xff0c;这让很多在准备今年上半年信息系统项目管理师考试的考生们有些紧张。那么这次教材改版主要的变化是什么&#xff0c;5月份的考试是否会按照新版的教材来考呢&#xff1f;让我们逐个章节进行分析。信息化…

Spark RDD编程基本操作

RDD是Spark的核心概念&#xff0c;它是一个只读的、可分区的分布式数据集&#xff0c;这个数据集的全部或部分可以缓存在内存中&#xff0c;可在多次计算间重用。Spark用Scala语言实现了RDD的API&#xff0c;程序员可以通过调用API实现对RDD的各种操作&#xff0c;从而实现各种…

数据结构刷题(二十三):47全排列II、51N皇后、37解数独

1.全排列II题目链接思路&#xff1a;回溯之排列问题并且有数组排序标记数组。 回溯三部曲同46. 全排列。过程图&#xff1a;https://programmercarl.com/0047.%E5%85%A8%E6%8E%92%E5%88%97II.html#%E6%80%9D%E8%B7%AF注意&#xff1a;本题的去重操作主要在树层上。就是说同一树…

2.JVM常识之 运行时数据区

1.JVM核心组成 2.JVM 运行时数据区&#xff08;jdk8&#xff09; 程序计数器&#xff1a;线程私有&#xff0c;当前线程所执行字节码的行号指示器 jvm栈&#xff1a;线程私有&#xff0c;Java 虚拟机栈为 JVM 执行 Java 方法服务 本地方法栈&#xff1a;线程私有&#xff0c;本…

SpringBoot接口 - 如何统一异常处理

SpringBoot接口如何对异常进行统一封装&#xff0c;并统一返回呢&#xff1f;以上文的参数校验为例&#xff0c;如何优雅的将参数校验的错误信息统一处理并封装返回呢&#xff1f;为什么要优雅的处理异常如果我们不统一的处理异常&#xff0c;经常会在controller层有大量的异常…

【Java】初识Java

Java和C语言有许多类似之处&#xff0c;这里就只挑不一样的点来说&#xff0c;所以会比较杂乱哈~ 目录 1.数据类型 2.输入与输出 2.1三种输出 2.2输入 2.3循环输入输出 //猜数字小游戏 //打印乘法口诀表 3.方法 //交换两个数&#xff08;数组的应用&#xff09; //模…

栈的应用-算数

本题要求你为初学数据结构的小伙伴设计一款简单的利用堆栈执行的计算器。如上图所示&#xff0c;计算器由两个堆栈组成&#xff0c;一个堆栈 S1​ 存放数字&#xff0c;另一个堆栈 S2​ 存放运算符。计算器的最下方有一个等号键&#xff0c;每次按下这个键&#xff0c;计算器就…

Form Generator扩展 文本 组件

一、form-generator是什么?✨ ⭐️ 🌟 form-generator的作者是这样介绍的:Element UI表单设计及代码生成器,可将生成的代码直接运行在基于Element的vue项目中;也可导出JSON表单,使用配套的解析器将JSON解析成真实的表单。 但目前它提供的组件并不能满足我们在项目中的…

kubeadm探秘

为什么kubeadm可以用于生产&#xff1f;第一是kubeadm已经被官方收编&#xff0c;可以在官网文档中找到它的身影。另外一个是kubeadm是用golang调用k8s的命令去执行创建k8s集群的。查看一下kubeadm的代码即可知道。本文来源于csdn作者 sunican挨个打开目录查看文件可知&#xf…

Guitar Pro8吉他学习辅助软件

Guitar Pro8最大的特色就是可以直接用鼠标和键盘按标准的六线谱、四线谱进行乐谱输入、查看、打印和试听&#xff0c;可以实时、自动滚屏、多种模式的显示单声部或乐曲总谱&#xff0c;在做弹拨乐器的滑音、倚音、推弦、揉弦、泛音、摇把、闷音、琶音、分解和弦、BASS打弦等方面…

【汽车应用处理器】DRA770PJGACDQ1、TDA4VM88TGBALFR功能应用

DRA770PJGACDQ1 汽车应用处理器旨在满足现代车内数字驾驶舱体验对于处理性能的强烈需求。利用该器件&#xff0c;原始设备制造商(OEM)和原始设计制造商(ODM)得以将创新型连接技术、语音识别和音频流式传输等快速投入实施。Jacinto6 Plus器件通过极其灵活的全集成混合处理器解决…

zigbee学习笔记:IO操作

1、IAR新建工程 &#xff08;1&#xff09;Projetc→Create New Projetc→OK→选择位置&#xff0c;确定 &#xff08;2&#xff09;新建一个c文件&#xff0c;保存在路径中 &#xff08;3&#xff09;点击工程&#xff0c;右键→add→加入c文件 &#xff08;4&#xff09;…

10、go工程化与标准库

目录一、用go mod管理工程二、包引入规则三、init调用链四、可见性五、标准库1 - 时间函数2 - 数学计算3 - I/O操作4 - 编码一、用go mod管理工程 初始化项目&#xff1a;go mod init $module_name&#xff0c;$module_name和目录名可以不一样。上述命令会生成go.mod文件 mod…

除了「加机器」,其实你的微服务还能这样优化

生产实践中&#xff0c;如果遇到业务流量变高导致服务负载升高甚至报警&#xff0c;我们的第一反应往往是「加机器」。 俗话说&#xff0c;能用钱解决的问题都不是问题。 俗话又说&#xff0c;充钱你就能变得更强。 但是&#xff0c;作为一个有理想有抱负的架构师&#xff0c;…

前端——7.图像标签和路径

这篇文章&#xff0c;我们来讲解一下图像标签 目录 1.图像标签 1.1介绍 1.2实际展示 1.3图像标签的属性 1.3.1 alt属性 1.3.2 title属性 1.3.3 width / height 属性 1.3.4 border属性 1.4注意事项 2.文件夹 2.1目录文件夹和根目录 2.2 VSCode打开目录文件夹 3.路…

决策树学习报告

报告 一、基本概念 决策树的定义&#xff1a;首先&#xff0c;决策树是一种有监督的分类算法——即给定X&#xff0c;Y值&#xff0c;构建X&#xff0c;Y的映射关系。不同于线性回归等是多项式&#xff0c;决策树是一种树形的结构&#xff0c;一般由根节点、父节点、子节点、…

MyBatis-Plus的入门学习

MyBatis-Plus入门学习简介特性快速开始MyBatis-Plus的注解详解Tableld主键生成策略1、数据库自动增长 AUTO2、UUID3、Redis生成id4、MP主键自动生成TableNameTableField自动填充测试方法&#xff1a;update乐观锁select查所有根据id查多个id批量查询简单条件查询&#xff08;通…

MySQL性能优化

MySQL性能调优 存储数据类型优化 尽量避免使用 NULL尽量使用可以的最小数据类型。但也要确保没有低估需要存储的范围整型比字符串操作代价更低使用 MySQL 内建的数据类型&#xff08;比如date、time、datetime&#xff09;&#xff0c;比用字符串更快 基本数据类型 数字 整数…

中国巨头在NLP领域的大模型布局

什么是大模型&#xff1f; 大规模模型&#xff08;large-scale model&#xff09;是近年来人工智能领域的一个热点话题&#xff0c;因为它们可以对自然语言处理&#xff08;NLP&#xff09;和其他任务进行更准确和深入的处理。由于大模型需要庞大的计算资源和数据支持&#xf…

论文投稿指南——中文核心期刊推荐(国家财政)

【前言】 &#x1f680; 想发论文怎么办&#xff1f;手把手教你论文如何投稿&#xff01;那么&#xff0c;首先要搞懂投稿目标——论文期刊 &#x1f384; 在期刊论文的分布中&#xff0c;存在一种普遍现象&#xff1a;即对于某一特定的学科或专业来说&#xff0c;少数期刊所含…