2010-01-25 18 views
11

Вам задано целое число 51234 (скажем), нам нужно отсортировать цифры номера, который будет выводиться 12345.Сортировка цифр целого числа

Как это сделать без использования массива?

+23

Я не хочу работа для компании, которая не позволяет мне использовать массив. – Karl

+15

@Karl: массивы не из дешевых, и с финансовым кризисом понятно, что они не хотят их использовать! :-) –

+2

Я бы использовал карту из злобы: p – meagar

ответ

26

Вы можете использовать цикл и % 10 для извлечения каждой цифры. Внешний цикл от 0 до 9 может использоваться для проверки наличия цифры. Если он существует, распечатайте его.

В псевдокоде:

n = integer // 51234 
FOR digit = 0 TO 9 
    temp = n 
    REPEAT 
    IF temp % 10 = digit THEN PRINT digit 
    temp /= 10 
    UNTIL temp = 0 

Edit: Этот тест в GCC показывает, что он обрабатывает нули и повторяющиеся цифры:

$ cat sortdigits.c 
#include <stdio.h> 
main() { 
int n,digit,temp; 
n = 43042025; 
for (digit=0;digit<9;digit++) 
    for (temp=n;temp>0;temp/=10) 
    if (temp%10==digit) printf("%d",digit); 
printf("\n"); 
} 
$ ./sortdigits 
00223445 
+0

+1 Я согласен с этим :) Псевдокода не понадобится, хотя :) –

+0

Красивая ... Хм ... в некотором роде. –

+0

@ Паскаль: Наверное. Если вы хотите перебирать число в 10 раз вместо одного. Это экономит память, хотя :-). –

3

Разделить на 10 заданных целых чисел в цикле. Распечатайте напоминание на каждой итерации.

Или «сортировка» означает, что здесь? Для реальной сортировки вам понадобятся две петли. Один из них будет от 0 до 9. Еще один будет описан ранее.

int main() 
{ 
    int x = 0; 
    cin >> x; 

    for (int l = 0; l < 10; ++l) 
    { 
     int rem = x % 10; 
     int tx = x/10; 
     while (rem || tx) 
     { 
      if (rem == l) cout << rem; 
      rem = tx % 10; 
      tx = tx/10; 
     } 
    } 
    cout << endl; 
} 
4

Общий обзор:

  • петля для i = 0 до 9
  • в каждой итерации цикла пройдите цифры в цифре (используя другой цикл, который выполняет операцию «mod 10», чтобы отключить цифры до тех пор, пока число не уменьшится до нуля) - если оно соответствует цифре, в которой вы сейчас работаете, распечатайте это

Единственный потенциально сложный бит может быть правильно обрабатывать нули - вам не нужно слишком много, и вам нужно обработать край, где вход нуль правильно.

Фактическая реализация остается в качестве упражнения ...

4

Easy:

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

static void pput(int n, int c) 
{ 
    int i; 
    for (i=0; i < n; ++i) putchar(c); 
} 

int main(int argc, char *argv[]) 
{ 
    int zeros = 0; 
    int ones = 0; 
    int twos = 0; 
    int threes = 0; 
    int fours = 0; 
    int fives = 0; 
    int sixes = 0; 
    int sevens = 0; 
    int eights = 0; 
    int nines = 0; 
    long num = 0; 

    if (argc > 1) { 
     char *eptr; 
     num = strtol(argv[1], &eptr, 0); 
     if (*eptr) { 
      fprintf(stderr, "Invalid number: '%s', using 0.\n", argv[1]); 
      num = 0; 
     } 
    } 
    do { 
     switch (num % 10) { 
      case 0: ++zeros; 
        break; 
      case 1: ++ones; 
        break; 
      case 2: ++twos; 
        break; 
      case 3: ++threes; 
        break; 
      case 4: ++fours; 
        break; 
      case 5: ++fives; 
        break; 
      case 6: ++sixes; 
        break; 
      case 7: ++sevens; 
        break; 
      case 8: ++eights; 
        break; 
      case 9: ++nines; 
        break; 
      default: 
        break; 
     } 
    } while ((num /= 10)); 
    pput(zeros, '0'); 
    pput(ones, '1'); 
    pput(twos, '2'); 
    pput(threes, '3'); 
    pput(fours, '4'); 
    pput(fives, '5'); 
    pput(sixes, '6'); 
    pput(sevens, '7'); 
    pput(eights, '8'); 
    pput(nines, '9'); 
    putchar('\n'); 
    return 0; 
} 

Компиляция и запуск:

$ gcc -Wextra -Wall -ansi -pedantic -Wfloat-equal -Wundef -Wshadow \ 
    -Wpointer-arith -Wcast-qual -Wcast-align -Wstrict-prototypes \ 
    -Wswitch-default -Wswitch-enum -Wstrict-overflow=5 \ 
    -Wdeclaration-after-statement -Wwrite-strings -Wconversion \ 
    -Waggregate-return -Wunreachable-code a.c 
$ ./a.out 
0 
$ ./a.out 54321 
12345 
$ ./a.out 9834346 
3344689 
$ ./a.out hello 
Invalid number: 'hello', using 0. 
0 

:-)

Другое решение, не используя массивов и довольно коротких строк на линии:

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

int main(int argc, char *argv[]) 
{ 
    long num = 0; 
    int i; 
    size_t *freq; 

    if (argc > 1) { 
     char *eptr; 
     num = strtol(argv[1], &eptr, 0); 
     if (*eptr || errno == ERANGE) { 
      fprintf(stderr, "Invalid number: '%s', using 0.\n", argv[1]); 
      num = 0; 
     } 
    } 

    if ((freq = calloc(10, sizeof *freq)) == NULL) { 
     perror("malloc failure"); 
     return EXIT_FAILURE; 
    } 

    do 
     ++freq[num % 10]; 
    while ((num /= 10)); 

    for (i=0; i < 10; ++i) { 
     size_t j; 
     for (j=0; j < freq[i]; ++j) 
      putchar(i + '0'); 
    } 
    putchar('\n'); 
    free(freq); 

    return EXIT_SUCCESS; 
} 

Да, я знаю о «правильном» решении. Но почему бы не использовать массивы для этой проблемы? Как один из комментаторов сказал, что я не хотел бы работать в компании, которая не позволит мне использовать массивы в С.

+2

Howz that easy ?? !! Все эти строки действительно необходимы? : O –

+0

@nthgreek: Я хочу сказать, что вопрос действительно плохой. Почему бы вам не использовать массив здесь? –

+0

Использование массива сделает так просто, что даже ребенок может это сделать! : P –

6
// Bubblesort 
long sortNum(long n) { 
    while (true) { 
    long a = n % 10, p = 9; 
    bool s = false; 
    for (long r = n/10; r; r/= 10) { 
     long b = r % 10; 
     if (a < b) { 
     n -= p * (b - a); 
     s = true; 
     } else a = b; 
     p *= 10; 
    } 
    if (!s) return n; 
    } 
} 

#include <iostream> 

int main(int argc, char **argv) { 
    if (argc > 1) { 
    long n = strtol(argv[1], 0, 0); 
    std::cout << "Unsorted: " << n << std::endl; 
    n = sortNum(n); 
    std::cout << "Sorted: " << n << std::endl; 
    } 
    return 0; 
} 

$ g++ -Wall -Wextra bubble-int.cpp && ./a.exe 183974425 
Unsorted: 183974425 
Sorted: 123445789 
+0

Умный - я даже не выглядел близко к этому, пока я не увидел комментарий Стива Джессопа в другом ответе. Для обработки нулей требуется немного. Все еще очень умно. –

+0

Спасибо. «Ответ на трюк» на трюк. Если бы кто-то действительно дал мне этот ответ в интервью, я бы спросил: «Почему так сложно? Почему бы не использовать std :: map?» Хорошо иметь людей, которые ** могут делать такие вещи, но также и знать, когда лучше не делать этого. – Dan

+0

Красивые.Избегает преобразования строк (обычная вещь, которую люди, похоже, предлагают для сортировки цифр), и имеет то преимущество, что отсортированный номер доступен для дальнейшего использования. – Tony

0

Можно попробовать что-то вроде вставки рода. По существу, создайте новый номер, взяв одну цифру из старой за раз и положив ее в нужное место. Что-то вроде этого.

while(num!=0){ 

dig = num%10; // get the last digit 
if(newNum=0) newNum+=dig; 
else{ 
    newNumTemp = 0; flag =1;i =1; 
    while (newNum != 0){ 
    Newdig = newNum%10; 
    if(flag){ 
     if (Newdig >= dig) 
     {NewNumTemp = Newdig*(10^i)+ NewNumTemp; } 
     else { flag=0; NewNumTemp = dig*(10^i) +NewNumTemp; i++;NewNumTemp = Newdig* (10^i)+ NewNumTemp;} 

    } // end of outer if 
    i++; 
    newNum/=10; 

    } // end of while 
    newNum= newNumTemp; 
}// end of else 

num/=10; 

}// end of outer while 
+0

извините за формат. Как вставить фрагмент кода? –

+0

Любая строка, начинающаяся с четырех пробелов, остается нетронутой. Нажать на "?" в правом верхнем углу окна справки. –

+0

@Alok: Спасибо за отзыв –

4

Вам не нужно написать программу на всех, просто сделать это с помощью команд оболочки:

echo "51234" | sed 's+\(.\)+\1\n+g' | sort | tr -d '\n' 
+0

50 лет назад это будет считаться высокоуровневым программированием. :-) – Ken

0

Создание интерфейса контейнера над междунаром (что-то вроде вектора), где оператор ссылается i-я десятичная цифра. Вам придется определять итераторы и другие вещи. Затем вызовите std :: sort. ;)

1

Конечно массивы, но у нас есть лучший контейнер в любом случае:

void foo(unsigned i) { 
    std::set<char> digits; 
    do { 
    digits.insert(`0` + i % 10); 
    i /= 10; 
    while(i!=0); 
} 

Используйте multiset, если ваш вклад включает в себя номера, как 887, которые должны быть напечатаны в 788

+0

Я думаю, что если массивы не разрешены, то на самом деле любые контейнеры не допускаются. –

Смежные вопросы