首页 > 试题广场 >

删除字符串中出现次数最少的字符

[编程题]删除字符串中出现次数最少的字符
  • 热度指数:368722 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32M,其他语言64M
  • 算法知识视频讲解
实现删除字符串中出现次数最少的字符,若出现次数最少的字符有多个,则把出现次数最少的字符都删除。输出删除这些单词后的字符串,字符串中其它字符保持原来的顺序。

数据范围:输入的字符串长度满足 ,保证输入的字符串中仅出现小写字母

输入描述:

字符串只包含小写英文字母, 不考虑非法输入,输入的字符串长度小于等于20个字节。



输出描述:

删除字符串中出现次数最少的字符后的字符串。

示例1

输入

aabcddd

输出

aaddd

//这道题卡我几天。注释很全,牛友可看。

/*实现删除字符串中出现次数最少的字符,若出现次数最少的字符有多个,则把出现次数最少的字符都删除。输出删除这些单词后的字符串,字符串中其它字符保持原来的顺序。*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>

#define LEN_DEL_INDEX 20 //因为题目要求字符串长度不超过20

/*
 * @Brief:打印二维数组;
 * @Note:专门用来debug的;
*/
void print_2D_array(int kv[][2], int rows) {
    for (int i = 0; i < rows; i++) {
        printf("%d %d\n", kv[i][0], kv[i][1]);
    }
}

/*
 * @brief:删除字符串里的指定元素,不论元素的位置。
 * @param:ddel:要删除的元素,s:字符串,len:字符串长度
*/
void proc_del_letter(char ddel, char* str, int* len) {
    int i, j;
    for (i = 0, j = 0; i < *len; i++) {
        if (str[i] != ddel) {
            str[j++] = str[i];  // 仅当当前字符不是要删除的字符时,才将其复制到新位置
        }
    }
    str[j] = '\0';  // 确保字符串以空字符结尾
    *len = j;       // 更新字符串长度
}


/*
 * @brief:冒泡排序二维数组,按照次数升序排列。
 * @param:hash:待排序的二维数组,rows:行数
 * @retval:None
*/
void upsort(int hash[][2], int rows) {
    if (rows < 0) {
        exit(-1);
    }
    if (rows == 1) return;

    for (int i = 0; i < rows - 1; i++) {
        for (int j = 0; j < rows - 1 - i; j++) {
            if (hash[j][1] > hash[j + 1][1]) {
                int temp_char = hash[j + 1][0];
                int temp_freq = hash[j + 1][1];
                hash[j + 1][0] = hash[j][0];
                hash[j + 1][1] = hash[j][1];
                hash[j][0] = temp_char;
                hash[j][1] = temp_freq;
            }
        }
    }
}

/*
 * @brief:处理字符串的主要程序
 * @param:strr:待处理的字符串,len:长度
 * @retval:成功返回1
*/
int proc(char* strr, int len) {
    if (len < 1 || len > 20)
        return -1;

    int i = 0;

    // 定义哈希表。26个小写字母。第一列是字母,第二列是次数。
    // 第一列是0说明是字符'a',第二列是0说明字符'a'出现0次。
    int hash[26][2] = {0};
    for (i = 0; i < 26; i++) { // 初始化二维数组
        hash[i][0] = i;
        hash[i][1] = 0;
    }

    for (i = 0; i < len; i++) {
        if (!islower(strr[i])) {
            perror("Capital letter occur!\n");
            return -1;
        }
    }

    for (i = 0; i < len; i++) {
        hash[strr[i] - 'a'][1] += 1; // 更新字符出现次数
    }

    int rows = sizeof(hash) / sizeof(hash[0]);
    // printf("debug: orginal is: %s\n", strr);
    // print_2D_array(hash, rows);
    upsort(hash, 26);
    // printf("debug: after sort:\n");
    // print_2D_array(hash, rows);

    //没排序值也是0,所以从0开始若某个元素不是0说明已经到排序后的字母了。
    int index_not_zero = -1; //非零元素行的值的首下标
    for (i = 0; i < 26; i++) {
        if (hash[i][1] != 0) {
            index_not_zero = i;
            break;
        }
    }

    int count_hash_min_indiex = 0; //统计哈希表里最小下标有几个,至少有一个但从零计数
    int temp_hash_min_index = hash[index_not_zero][1];
    for (i = index_not_zero; i < 26; i++) {        
            if (hash[i][1] == temp_hash_min_index) {
                count_hash_min_indiex += 1;
            }
    }

    int count_hash_min_to_elem =  1; //统计哈希表里最小下标的对应元素有几个,至少为1。
    for ( i = 0; i < len; i++) {
        if (strr[i] - 'a' == *hash[index_not_zero]) {
            count_hash_min_to_elem += 1;
        }
    }

    for ( i = 0; i < count_hash_min_indiex; i++) {
        proc_del_letter(hash[index_not_zero + i][0] + 'a', strr, &len);
    }

    return 1;
}

int main() {
    char strr[21] = "\0";

    fgets(strr, sizeof(strr), stdin);
    strr[strcspn(strr, "\n")] = '\0';

    int length = strlen(strr);

    if (length < 1 || length > 20) return 0;

    if (!proc(strr, length)) {
        return 0;
    }

    printf("%s\n", strr);

    return 0;
}
发表于 2024-04-16 22:25:44 回复(0)
#include "stdio.h"
#include "string.h"
//思路:输入后遍历字符串,录入出现次数,之后挑出最小的数。然后遍历输出任何大于这个出现次数的数组元素。
//注意:本题的难点和核心思想在于找准两个数组之间的下标之间的关系,以做到互不干扰却又相互影响。
int main()
{
    //输入部分
    char str[27] = {'0'};//因为之后用到了26个字母的遍历,所以所有数组都设置的大一点,防止越界。另外吐槽一点,Windows下的VS code就没越界而输出一些奇怪的东西,牛客就会,6.
    int num[27]= {0},temp, a = 0;
    scanf("%s",str);
    int length = strlen(str),i = 0;
    //遍历并录入出现次数
    for(; i < length; i++)
    {
        if (str[i] >= 'a' && str[i] <= 'z' ) 
        {
            num[(int)str[i]-97]++;//a的ASCII为97,这样做刚好可以把a放进num[0],也就是num的第一个,实现字符与其出现次数的数组的下标的对应。
        }
    }
    //获取最小输入次数。
    temp = 500;//把temp初始值设定的非常大,可以保证后面的找最小出现次数被正确地放入temp中。
    for (i = 0; i < 26; i++) 
    {
        if (temp > num[i] && num[i] != 0) 
        {
            temp = num[i];
        }
    }
    for(i = 0; i < 26; i++)
    {
        if(num[str[i] - 'a'] > temp&&num[str[i] - 'a'] !='0')//此处是本题的核心。str[i]-'a'刚好由于上文构建的对应而能和i对应上;与此同时这里不使用num[i],又可以保证不会对输出环节产生无法准确对应的干扰。
        {
            printf("%c",str[i]);
        }
    }
}
//以下是开发过程中使用的部分检验过程和弯路。

//此时,各个字符出现次数录入正确。
    /*for (i = 0; i < length; i++) 
    {
        if (num[i] > 0) 
        {
            printf("%d",num[i]);
        }
    }
    */
//原本的输出方式:这个输出方式会导致实质上是打出了出现次数更多的字符,而不是按照字符串的原顺序进行输出。
/*for(i = 0; i < 26; i++)
    {
        if(num[i] > temp)
        {
            for(a = 0; a < num[i]; a++)
            {
                printf("%c",(char) (i+97));
            }
        }
    }*/
//printf("temp is %d\n",temp);

发表于 2024-04-06 00:39:37 回复(0)
#include <stdio.h>

int main() {
    int alp[26]={0}, min=20;
    char arr[20];
    while(scanf("%s", arr) != EOF){
        for(int i=0;i<strlen(arr);i++){
            alp[arr[i]-97]++;
        }
        for(int j=0;j<26;j++){
            if(alp[j]==0) continue;
            else if(alp[j]<min) min=alp[j];
        }
        for(int k=0;k<strlen(arr);k++){
            if(alp[arr[k]-97]==min) continue;
            printf("%c", arr[k]);
        }
    }
    return 0;
}
发表于 2024-03-12 17:36:59 回复(0)
#include <stdio.h>
#include <string.h>
int main() {
    char str[21] = {'\0'};
    int con[26] = {0};
    int min = 20;
    gets(str);
    for (int i = 0; i < strlen(str); i++) con[str[i] - 'a']++;
    for (int i = 0; i < 26; i++) if (con[i] > 0 && con[i] < min) min = con[i];
    for (int i = 0; i < 26; i++) {
        if (con[i] == min) {
            for (int j = 0; j < strlen(str); j++) {
                if (str[j] == i + 'a') str[j] = '0';
            }
        }
    }
    for (int j = 0; j < strlen(str); j++) if (str[j] != '0') putchar(str[j]);
    return 0;
}

编辑于 2023-12-02 16:53:57 回复(0)
#include <stdio.h>
#include <string.h>

int main() {
    char str[21]={0};
    int count[26]={0},min;
    gets(str);
    int len=strlen(str);
    for(int i=0;i<len;i++)
        count[str[i]-'a']++;//统计次数
    for(int i=0;i<26;i++)
    {
        if(count[i]!=0)
            min=count[i];//找到第一个不为零
    }
    for(int i=0;i<26;i++)
    {
        if(count[i]!=0&&count[i]<min)
            min=count[i];//新的最小
    }
    for(int i=0;i<len;i++)
    {
        if(count[str[i]-'a']!=min&&count[str[i]-'a']!=0)
            printf("%c",str[i]);
    }
    return 0;
}
发表于 2023-09-03 19:04:24 回复(0)
//利用下标与数值的关系
#include <stdio.h>
#include <string.h>
int main() {
char s[21],p[21];
int count[26]={0};
int len,i,j,min;
min=20;
j=0;
gets(s);
len=strlen(s);

for(i=0;i<len;i++){
    count[s[i]-'a']++;
}

for(i=0;i<26;i++){
    if(count[i]<min&&count[i]!=0)
    min=count[i];
}

for(i=0;i<len;i++){
    if(count[s[i]-'a']!=min)
    {
        p[j]=s[i];
        printf("%c",p[j]);
        j++;
    }
}
p[j]='\0';
return 0;
}
发表于 2023-07-30 09:57:45 回复(0)
#include <stdio.h>
#include <string.h>

int main() {
    char str[21];
    int count[26] = {};
    int min = 20;

    scanf("%s", str);
    for (int i = 0; i < strlen(str); i++)
        count[str[i] - 'a'] ++;
    for (int i = 0; i < 26; i++)
        if (count[i] < min && count[i])
            min = count[i];
    for (int i; i < strlen(str); i++)
        if (count[str[i] - 'a'] != min)
            printf("%c", str[i]);
}


发表于 2023-03-19 20:33:36 回复(0)
int main(void){
    int flag[26] = {0};    
    char input[20];
    gets(input);
    int i = 0;
    int count = strlen(input);
    for(i=0;i<count;i++){
        flag[input[i]-97]++;        
    }
    int jojo = count;
    for(i=0;i<26;i++){
        if(jojo >= flag[i] && flag[i]!= 0){
            jojo = flag[i];
        } 
    }
    for(int i=0;i<count;i++){
        if(flag[input[i]-97] != jojo){
            printf("%c",input[i]);            
        }   
    }

}

发表于 2022-08-25 15:46:08 回复(1)
#include <stdio.h>

int main()
{
  char buf[20], num[26] = {0};
  char buf_len, i, j, min;
  
  scanf("%s", buf);
  buf_len = strlen(buf);
  min = buf_len + 1;
  
  /* 计算各字符出现次数 */
  for(i = 0; i < buf_len; i++)
  {
    num[buf[i] - 'a']++;
  }

  /* 获取最小字符串出现概率 */
  for(i = 0; i < 26; i++)
  {
    if(num[i] && num[i] < min)
      min = num[i];
  }
  
  /* 删除最少字符 */
  for(i = 0, j = 0; i < buf_len; i++)
  {
    if(num[buf[i] - 'a'] > min)
      buf[j++] = buf[i];
  }
  
  /* 输出结果 */
  buf[j] = 0;
  printf("%s", buf);
}

发表于 2022-07-04 23:47:33 回复(0)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define LETTER_NUM ('z' - 'a' + 1)
int main(void)
{
    char str[20] = {'\0'};
    char dst_str[20] = {'\0'};
    char map[LETTER_NUM] ={0};
    scanf("%s",str);
    int i = 0,j = 0,min_count = 0;;
    int len = strlen(str);
    //统计a-z的次数
    for( i = 0; i < len; i++ )
    {
        map[str[i] - 'a']++;
    }
    
    //寻找最小次数min_count
    min_count = len;
    for(i = 0; i < LETTER_NUM; i++)
    {
        if(map[i] != 0 && (map[i] < min_count) )
        {
            min_count = map[i];
        }      
    }
    //保存大于最小次数的字符
    for(i = 0; i < len; i++)
    {
        if(map[str[i] - 'a'] > min_count)
        {
            dst_str[j] = str[i];
            j++;
        }
    }
    printf("%s\n",dst_str);
    return 0;
}
发表于 2022-06-16 18:26:28 回复(0)
#include <stdio.h>
#include <string.h>

int main(void) {
    char str[21];
    int index[21] = {0};
    int hash[21] = {0};

    scanf("%s", str);

    int length = (int) strlen(str);

    for (int i = 0; i < length; ++i) {
        index[i] = 1;
        for (int j = 0; j < length; ++j) {
            if (i == j)
                continue;
            else {
                if (str[i] == str[j])
                    index[i]++;
                else
                    continue;
            }
        }
    }
    for (int i = 0; i < length; ++i) {
        if (index[i] == 1)
            continue;
        else {
            for (int j = 0; j < length; ++j) {
                if (i == j)
                    continue;
                else {
                    if (index[i] > index[j]) {
                        hash[i] = 1;
                        break;
                    }
                }
            }
        }

    }

    for (int k = 0; k < length; ++k) {
        if (hash[k] == 1)
            printf("%c", str[k]);
        else
            continue;
    }
    return 0;
}

发表于 2022-04-25 13:11:50 回复(0)
#include <stdio.h>
#define    N    21
int main()
{
    char str[N],temp;
    int i=0,s=1,arr[26]={0},min=N,j;    //arr[26],下标对应字母'a'到'z',数值表示出现的次数
    scanf("%s",str);                    //min先初始化为21,后续有比它小的就修改
    while(str[i]!='\0')
    {
        if(str[i]<'a'||str[i]>'z')
        {
            s=0;                    //s为小写字母标志,如果出现非小写字母,s=0
            break;
        }
        i++;
    }
    if(s==1)
    {
        i=0;
        while(str[i]!='\0')
        {
            arr[str[i]-'a']+=1;
            i++;
        }
        for(i=0;i<26;i++)
        {
            if(arr[i]!=0&&arr[i]<min)
            {
                min=arr[i];        //min记录字符串中出现相同字符次数的最小值
            }
        }
        for(i=0;i<26;i++)
        {
            if(arr[i]==min)        //可能出现多个字符出现次数最少
            {
                temp=i+'a';        //下标i+'a'==出现次数最少的字符
                j=0;
                while(str[j]!='\0')
                {
                    if(str[j]==temp)
                    {
                        str[j]=' ';    //将该字符置为空格,后续打印的时候直接跳过
                    }
                    j++;
                }
            }
        }
        i=0;
        while(str[i]!='\0')
        {
            if(str[i]!=' ')
            {
                printf("%c",str[i]);
            }
            i++;
        }
    }
    return 0;
}

发表于 2022-04-16 15:57:55 回复(0)
#include<stdio.h>
#include<string.h>

struct{
    int index;//字符个数
    char ch;//对应字符
}data[21],buf;

int main()
{
    //得到输入字符串
    char str[21];
    char val[(int)'z'+1]={0};
    char num[21] = {0};
    int j=0;
    scanf("%s",str);
    
    for(int i=0; i<strlen(str); i++){        
        //统计各个字符个数
        val[(int)str[i]] += 1;         
    }
    for(int i=(int)'a'; i<=(int)'z'; i++){        
        //统计各个字符个数  
        if(val[i] != 0){
            data[j].index = val[i];//将含有元素的数组重新赋值
            data[j].ch = i;//
            j++;//不等于0字符种类//要排序的个数
        }        
    }    
    //将字符个数排序,找最小的字符
    for(int i=0; i<j; i++){
        for(int k=i+1; k<j; k++){
            if(data[i].index > data[k].index){
                buf = data[i];
                data[i] = data[k];
                data[k] = buf;
            }
        }
    }
    //找是否有和最小字符相同的字符
    num[0] = data[0].ch;
    for(int k=1; k<j; k++){
        if(data[0].index == data[k].index){
            num[k] = data[k].ch;//记住和最小相同的字符,到时候不打印
        }
    }
    //打印数量最多的字符
    for(int i=0; i<strlen(str); i++){  
        int flg=0;//是否打印的标识
        for(int h=0; h<j; h++){
            if(str[i] == num[h]){
                flg = 1;
                break;
            }
        }
        if(flg == 0){
            printf("%c",str[i]);
        }  
    }
    printf("\n");    
    
    return 0;
}
发表于 2022-04-02 21:45:14 回复(0)
#include<stdio.h>
int main()
{
    char str[20] = {0};
    char map[26] = {0};
    int i=0;
    char x;
    char min = 20;
    scanf("%s",str);
    // 记录个数
    while(*(str+i))
    {
        x = *(str+i)-'a';
        map[x]++;
        i++;
    }
    // 寻找最小值
    for(i=0;i<26;i++)
    {
        if(map[i] && map[i]<min)
            min = map[i];
    }
    // 判定输出
    i=0;
    while(*(str+i))
    {
        if(map[*(str+i)-'a'] != min)
            printf("%c",*(str+i));       
        i++;
    }
        
    
    return 0;
}

发表于 2022-03-26 16:02:54 回复(0)
#include<stdio.h>
#include<string.h>

int main(){
    char str[21];
    int map[26] = {0};
    int i;
    int min = 21;
    char *p = str;
    fgets(str, 21, stdin);
    while(*p){
        map[*p - 'a']++;
        p++;
    }
    for( i=0; i<26; i++){
        if(map[i] < min && map[i] > 0){
            min = map[i];
        }
    }
    for( i=0; i<strlen(str) - 1; i++){
        if(map[str[i] - 'a'] != min){
            printf("%c", str[i]);
        }
    }
    return 0;
}

发表于 2022-03-21 22:49:29 回复(0)
#include<stdio.h>
#include<string.h>
int main()
{
    char arr[21]={0};
    int num[124]={0},i=0;
    gets(arr);
    while(i<strlen(arr))
    {
        num[arr[i++]]++;
    }
    int min=20;
    for(int i=0;i<124;i++)
    {
        if(num[i]!=0&&num[i]<min)
            min=num[i];
    }
    for(int i=0;i<strlen(arr);i++)
    {
        if(num[arr[i]]!=min)
            printf("%c",arr[i]);
    }
    return 0;
}

发表于 2022-03-21 01:48:47 回复(0)
//二维数组  分别存放字母及对应出现次数
#include<stdio.h>
#include<string.h>

int main(void)
{
    char n[2][20]={0},min;
    gets(n[0]);
    for(int i=0;i<strlen(n[0]);i++)
    {
        for(int j=0;j<strlen(n[0]);j++)
        {
            if(n[0][j]==n[0][i]) n[1][i]++;
        }
    }
    min=n[1][0];
    for(int j=0;j<strlen(n[1]);j++)//找到字符最小出现次数
    {
        if(n[1][j]<min) min=n[1][j];
    }
    for(int j=0;j<strlen(n[1]);j++)//输出出现次数大于min的字符
    {
        if(n[1][j]>min) printf("%c",n[0][j]);
    }
}
发表于 2022-03-03 15:46:08 回复(0)
#include<stdio.h>
#include<string.h>
#include<stdlib.h>

typedef struct table{
    char *elem;
    int *count;
}table;

int main()
{
    char str[32]={'\0'};
    while(scanf("%[^\n]",str)!=EOF){
        scanf("%*[^\n]");scanf("%*c");
        int len=strlen(str);//len非常重要的一个常量;
        table t;
        t.elem=(char*)malloc(len*sizeof(char));//申请存储空间
        t.count=(int*)malloc(len*sizeof(int));

        for(int i=0;i<len;i++){ //把str存入t,并且标记每个字符
            t.elem[i]=str[i];
            t.count[i]=0;
        }

        for(int i=0;i<len;i++){ //统计每个字符出现的次数
            for(int j=0;j<len;j++){
                if(t.elem[i]==t.elem[j])t.count[i]++;
            }
        }

        table m;        //创造新的结构变量m,通过m找到最小次数;这里不能用m=t(改变m会改变t);而要循环赋值
        m.elem=(char*)malloc(len*sizeof(char));
        m.count=(int*)malloc(len*sizeof(int));
        for(int i=0;i<len;i++){
            m.elem[i]=t.elem[i];
            m.count[i]=t.count[i];
        }

        for(int i=1;i<len;i++){  //寻找最小次数count
            if(m.count[0]>m.count[i]){
                int n=m.count[0];
                m.count[0]=m.count[i];
                m.count[i]=n;
            }
        }

        int min_count=m.count[0];//将最小值赋给min_count;
        for(int i=0;i<len;i++){ //将结构变量除了最小次数外,其余都打印
            if(t.count[i]!=min_count){
                printf("%c",t.elem[i]);
            }
        }
        printf("\n");

        free(t.elem);//释放申请的内存
        free(t.count);
        free(m.count);
        free(m.elem);
    }
    return 0;
}


发表于 2022-01-23 01:30:16 回复(0)