Удалить дубликаты из строки в CPP - PullRequest
1 голос
/ 16 февраля 2020

Я написал следующий код для удаления дубликатов из заданной строки, т. Е. Если входом является ARRUN, то выводом будет ARUN.

#include <bits/stdc++.h>
using namespace std;
char* removeDuplicates(string &s,int n){
    char arr[n];
    unordered_map<char,int> exists;
    int index = 0;
    for(int i=0;i<n;i++){
        if(exists[s[i]]==0)
        {
            arr[index++] = s[i];
            exists[s[i]]++;
        }
    }
    return arr;
}

//driver code
int main(){
    string str;
    cin >> str;
    cout<<removeDuplicates(str,str.length())<<endl;
    return 0;
}

Код вообще не выводит, однако работает хорошо, если я использую char arr[] вместо строкового класса.

Ответы [ 6 ]

3 голосов
/ 16 февраля 2020

Вам не нужно map. set достаточно.

Обратите внимание, что map и set уже удаляют дубликаты. Вам не нужно ничего проверять.

Вы не можете использовать char arr[n], не будучи n константой constexpr.

Следующий код выполняет работу.

#include<string>
#include<iostream>
#include<unordered_set>

std::string removeDuplicates(const std::string &s){
    std::string arr;
    std::unordered_set<char> exists;

    for(const auto&el:s)
        exists.insert(el);

    for(const auto&el:exists)
        arr+=el;

    return arr;
}

//driver code
int main(){
    std::string str;
    std::cin >> str;
    std::cout<<removeDuplicates(str)<<std::endl;
    return 0;
}
1 голос
/ 16 февраля 2020

Это может быть немного сложнее для новичков в C ++, но другое решение использует идиому erase-remove :

std::string removeDuplicates(const std::string& s) {
    std::string result = s;
    std::unordered_set<char> seen;

    result.erase(std::remove_if(result.begin(), result.end(), [&seen](char c)
        {
            if (seen.find(c) != seen.end())
                return true;

            seen.insert(c);
            return false;
        }),
    result.end());

    return result;
}

В основном он использует набор для хранения символов, которые имеют было замечено, перетасовывает символы, которые будут удалены до хвоста (используя std::remove_if) и стирает хвост из строки.

Рабочая версия здесь .

1 голос
/ 16 февраля 2020

std::string поддержка удаления элементов.

#include <iostream>
#include <string>

std::string removeDuplicates(std::string str) {
    for (int i = 0; i < str.size(); i++) {
        while (true) {
            int j = str.find_last_of(str[i]);
            if (i < j) {
                str.erase(j, 1);
            } else {
                break;
            }
        }
    }
    return str;
}

int main() {
    std::cout << removeDuplicates("ARRUN");
    return 0;
}
1 голос
/ 16 февраля 2020

Если объявление функции выглядит следующим образом

char* removeDuplicates(string &s,int n);

, то это означает, что сам переданный объект будет изменен в функции. В противном случае параметр должен иметь квалификатор const.

Также неясно, почему функция имеет тип возврата char *. Похоже, что объявление функции противоречиво.

Второй параметр функции должен иметь как минимум тип size_t или лучше std::string::size_type. Тип int не может вместить все значения типа std :: string :: size_type.

Функция может быть объявлена ​​без второго параметра.

Простой подход без использования промежуточных контейнеров, для которого требуются промежуточные контейнеры. Dynami c выделение памяти может выглядеть следующим образом

#include <iostream>
#include <string>

std::string & removeDuplicate( std::string &s )
{
    const char *p = s.c_str();

    std::string::size_type pos = 0;

    for ( std::string::size_type i = 0, n = s.size(); i < n; i++ )
    {
        std::string::size_type j = 0;
        while ( j < pos && s[i] != s[j] ) j++;

        if ( j == pos )
        {
            if ( i != pos ) s[pos] = s[i];
            ++pos;
        }
    }

    return s.erase( pos );
}

int main() 
{
    std::string s( "H e l l o" );

    std::cout << "\"" << s <<"\"\n";

    std::cout << "\"" << removeDuplicate( s ) <<"\"\n";

    return 0;
}

Вывод программы:

"H e l l o"
"H elo"
1 голос
/ 16 февраля 2020

@ Арун Сурян, Вы правильно указали. Но вы можете сделать это, не используя vector, используя global char array .

Также не забудьте добавить newline в конце!

Посмотрите на следующий код:

#include<string>
#include<iostream>
#include<unordered_map>

char* removeDuplicates(std::string &s,int n){

    std::unordered_map<char,int> exists;
    char* arr = (char*)(malloc(n*sizeof(char)));
    int index = 0;
    for(int i=0;i<n;i++){
        if(exists[s[i]]==0)
        {
            arr[index++] = s[i];
            exists[s[i]]++;
        }
    }
    arr[index] = '\n';
    return arr;
}

//driver code
int main(){
    std::string str;
    std::cin >> str;
    std::cout<<removeDuplicates(str,str.length())<<std::endl;
    return 0;
}
0 голосов
/ 16 февраля 2020

Итак, после небольшого чтения Inte rnet я понял, что пытаюсь вернуть указатель на локальный массив в функции removeDuplicates().

Это то, что отлично работает

#include <bits/stdc++.h>
using namespace std;
void removeDuplicates(string &s,int n){
    vector<char> vec;
    unordered_map<char,int> exists;
    int index = 0;
    for(int i=0;i<n;i++){
        if(exists[s[i]]==0)
        {
            vec.push_back(s[i]);
            exists[s[i]]++;
        }
    }
    for(auto x: vec)
        cout << x;
}

//driver code
int main(){
    string str;
    cin >> str;
    removeDuplicates(str,str.length());
    return 0;
}

PS: Мы также можем сделать тип возвращаемого значения векторным.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...