Как найти числа с повторяющимися цифрами в векторе? - PullRequest
0 голосов
/ 02 февраля 2020

Учитывая диапазон чисел от a до b, мне нужно найти все числа, которые имеют повторяющиеся цифры. Они не должны быть последовательными повторяющимися цифрами - например, 121 будет считаться одним из этих чисел. Я уже закодировал ввод самого векторного списка - я просто не знаю, как анализировать цифры каждого отдельного элемента в этом векторе.

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

int main(){
    //variables
    int a, b, i = 0; // a & b inputs, i for iterating

    //entering number range
    cout << "Enter the first number" << endl;
    cin >> a;
    cout << "Enter the second number" << endl;
    cin >> b;


    //making a vector to contain numbers between a and b
    vector<int> listofnums((b-a)+1); 
    int initialvalue = a;
    while (i <= (b-a)) {  
        listofnums[i] = initialvalue;                                 
        initialvalue++; 
        i++;
    }

    //printing the completed vector
    for ( const auto &item : listofnums ){
        std::cout << item << ' ';
    }

    std::cout << '\n';

    //analyzing the digits of each item in the vector
    //code for finding repeating digits here

    return 0;
}

Ответы [ 3 ]

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

Вот, пожалуйста.

#include <iostream>
#include <bitset>
#include <tuple>
#include <vector>
#include <algorithm>

bool duplicated_digits( int value )
{
    const int Base = 10;
    std::bitset<Base> b;

    bool is_duplicate = false;

    do
    {
        int digit = value % Base;

        if ( digit < 0 ) digit = -digit;

        b.flip( digit );
        is_duplicate = not b.test( digit );
    } while ( not is_duplicate && ( value /= Base ) != 0 );

    return is_duplicate;
}

int main()
{
    int a = 0, b = 0; 

    std::cout << "Enter the first number: ";
    std::cin >> a;
    std::cout << "Enter the second number: ";
    std::cin >> b;

    std::tie( a, b ) = std::minmax( { a, b } );

    std::vector<int> v; 

    int current_value = a;
    do
    {
        if ( duplicated_digits( current_value ) ) v.push_back( current_value );
    } while ( current_value++ != b );

    if ( not v.empty() )
    {
        std::cout << "There are the following numbers with duplicated digits "
                     "in the range [ "
                  << a << ", " << b << " ]\n";                   
        for ( const auto &item : v )
        {
            std::cout << item << ' ';
        }
        std::cout << '\n';
    }
    else
    {
        std::cout << "There are no numbers with duplicated digits in the range [ "
                  << a << ", " << b << " ]\n";                   
    }

    return 0;
}

Вывод программы может выглядеть, например, следующим образом

Enter the first number: 50
Enter the second number: -50
There are the following numbers with duplicated digits in the range [ -50, 50 ]
-44 -33 -22 -11 11 22 33 44 

Или другим примером возможного вывода программы

Enter the first number: -100
Enter the second number: -130
There are the following numbers with duplicated digits in the range [ -130, -100 ]
-122 -121 -119 -118 -117 -116 -115 -114 -113 -112 -111 -110 -101 -100 
1 голос
/ 02 февраля 2020

Вы можете получить значение наименьшего (наименее значимого) ди git десятичного числа, взяв остаток после деления его на 10; в C++ это легко выполнить с помощью оператора по модулю (%). Таким образом, с учетом переменной integer , a, со значением 123, оператор int b = a % 10; назначит 3 b.

Теперь, запустив al oop, в котором мы последовательно делим «тестовое» число на 10 (пока оно не достигнет нуля), мы можем получить значения для каждого di git. Если мы сохраняем массив значений bool, устанавливая каждое из них на true, когда мы находим заданную ди git, мы можем быстро обнаружить повторную ди git.

Таким образом, эта функция будет выполните работу:

bool HasRepeatDigit(int x)
{
    bool hasDigit[10] = {false, false, false, false, false, false, false, false, false, false};
    while (x > 0) {
        int digit = x % 10;
        if (hasDigit[digit]) return true; // We already have this digit!
        hasDigit[digit] = true; // Flag the digit we just found
        x /= 10; // Divide by 10, to move onto the next digit
    }
    return false; // If we get here, there is no repeat digit!
}

Затем вы можете вызвать эту функцию для каждого из ваших «тестовых» номеров за секунду l oop, добавив те числа, которые имеют повторяющиеся цифры, к новому вектору:

vector<int> withRepeats;
for (auto i : listofnums) { // Tests "i" for every element in listofnums
    if (HasRepeatDigit(i)) withRepeats.push_back(i); // Append this to the new vector
}

Не стесняйтесь обращаться за дополнительными объяснениями и / или разъяснениями.

Кроме того, вы можете уменьшить код, который заполняет ваш listofnums вектор, используя std::iota функция (определена в заголовке <numeric>):

#include <numeric>
//...
std::iota(begin(listofnums), end(listofnums), a);
0 голосов
/ 02 февраля 2020

Существует миллион решений. Каждый может делать то, что он хочет

Стандартный подход в C ++ для этих типов проблем заключается в использовании std::map в качестве счетчика. У std :: map есть оператор индекса. Оператор индекса возвращает ссылку на значение, если ключ существует. Если ключ не существует, он создаст новую запись и затем вернет ссылку на инициализированное значение по умолчанию.

Затем мы увеличим ссылку.

Перед этим мы преобразуем целое число в строка, а затем работать над символами (цифрами). Подсчет тогда так же прост, как:

for (const char& digit : numberAsString) counter[digit]++;

Мы помещаем все операции в функцию и затем можем использовать это в алгоритмах C ++.

Пожалуйста, см .:

#include <iostream>
#include <vector>
#include <string>
#include <map>
#include <algorithm>
#include <iterator>

bool check(const int& i) {
    // Convert int to string
    std::string numberAsString{ std::to_string(i) };

    // We will use a map as counter
    std::map<char, size_t> counter{};

    // Count the digits
    for (const char& digit : numberAsString) counter[digit]++;

    // Search for a digit count > 1
    bool result{};
    for (const auto& [digit, count] : counter)  if (count > 1) { result = true; break; };

    return result;
}


using namespace std;

int main() {
    //variables
    int a, b, i = 0; // a & b inputs, i for iterating

    //entering number range
    cout << "Enter the first number" << endl;
    cin >> a;
    cout << "Enter the second number" << endl;
    cin >> b;


    //making a vector to contain numbers between a and b
    vector<int> listofnums((b - a) + 1);
    int initialvalue = a;
    while (i <= (b - a)) {
        listofnums[i] = initialvalue;
        initialvalue++;
        i++;
    }

    //printing the completed vector
    for (const auto& item : listofnums) {
        std::cout << item << ' ';
    }

    cout << '\n';

    //analyzing the digits of each item in the vector
    //code for finding repeating digits here

    // Example 1
    // print out all values in the vector having this property
    cout << "\n\n Result:\n";
    copy_if(listofnums.begin(), listofnums.end(), ostream_iterator<int>(cout,"\n"), check);

    // Example 2
    // copy all thos values to a new vector
    vector<int> result;
    copy_if(listofnums.begin(), listofnums.end(), back_inserter(result), check);

    return 0;
}

...