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

186 阅读3分钟

描述

实现删除字符串中出现次数最少的字符,若出现次数最少的字符有多个,则把出现次数最少的字符都删除。输出删除这些单词后的字符串,字符串中其它字符保持原来的顺序。

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

输入描述:

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

输出描述:

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

题目来源

题目来源

示例1

输入:

aabcddd

复制

输出:

aaddd

思路

  • 法1:手动实现hash表

    • 1.统计各个字符出现的次数,用char c[127],O(n)
    • 2.找到统计次数中最小的次数,赋值为min,O(n)
    • 3.遍历字符串,将字符出现的次数对比min,大于min则加入到ans字符串中,小于则不管
  • 法2:hash表法

    • 1.设置hash表,map<char,int>
    • 2.统计各个字符出现的次数
    • 3.找到统计次数中最小的次数,赋值为min
    • 同思路1.3

时间复杂度

法1:时间复杂度:O(3n),空间复杂度:O(n)

法2:时间复杂度:O(n),空间复杂度O(n)

具体实现

#include <math.h>
#include <algorithm>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>
#include <stdlib.h>
#include <cstdlib>
#include <cstring>
​
using namespace std;
​
const int INF = 1e8;
​
​
//day4,
//实现删除字符串中出现次数最少的字符,若出现次数最少的字符有多个,则把出现次数最少的字符都删除。输出删除这些单词后的字符串,字符串中其它字符保持原来的顺序。
//法1:非原地算法
//时间复杂度:O(n),空间复杂度O(n)
/**
 * @description: 
 * @param {string &} s
 * @return {*}
 */
string DeletAllMinCharacter(string s){
    char c[127] = {0};//记录对应字符出现的次数
    char c_m[127] = {0};//记录最小字符数的对应字符
    string ans;//答案字符串
    int len_s = s.length();
    int min = INF;//记录最少的字符数
    for(int i = 0; i < len_s; i++){
        c[s[i]]++;//记录对应的字符数
    }
    //统计最小的字符数据
    for(int i = 0; i < 127; i++){
        if(c[i] < min && c[i] != 0) min = c[i];
    }
    //将答案字符串直接赋给ans
    for(int i = 0; i < len_s; i++){
        if(c[s[i]] > min) ans += s[i];
    }
    return ans;
}
​
//法2:利用库函数的hash表进行统计遍历
/**
 * @description: 时间复杂度:O(n) 空间复杂度O(n)
 * @param {string} s
 * @return {*}
 */
string DeletAllMinCharacterII(string s){
    unordered_map<char,int>hash;//记录出现次数的hash表
    int degree = INF;
    string ans;
    for(int i = 0; i < s.length(); i++){
        hash[s[i]]++;
    }
    //统计出出现最少的次数
    for(auto & k : hash){
        degree = min(degree, k.second);
    }
    //printf("%d",degree);
    //根据最少次数进行遍历,将大于最少次数的字符统一加到s[i]中
    for(int i = 0; i < s.length(); i++){
        if(hash[s[i]] > degree) ans += s[i];
    }
    return ans;
}
​
​
int main(){
    string s;
    string ans;
    //用到getline
    getline(cin,s);//将输入流直接赋给s字符串
    //char c;
    //cin >> c;
    //int lastans = CountDifferentCharacter(s);
    ans = DeletAllMinCharacter(s);
    for(int i = 0; i < ans.lenght(); i++){
        printf("%c",ans[i]);
    }
    //printf("%d",lastans);
    
    system("pause");
    return 0;
}
​

image.png

小结

此类统计字符的次数,第一次思考对象为hash表法,法1和法2均为非原地算法,但是因为输入字符<=20,那么空间复杂度为O(1),并不影响空间复杂度;

但如果是出现输入字符不限制,原地算法较为好,无额外空间消耗,但是原地算法我并没有想出来,后序查询百度是否可以实现原地删除