求比指定數大且最小的“不重復數”問題


給定任意一個正整數,求比這個數大且最小的“不重復數”,“不重復數”的含義是相鄰兩位不相同,例如1101是重復數,而1201是不重復數.

 

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

#define NUMBER_STR_MAX_LENGTH (128)
unsigned find(unsigned);

int main(void)
{
    unsigned num = 0;

    printf("Please input Unsigned Number : ");
    if (scanf("%u", &num) != 1) {
        perror("input error!");
        return 1;
    }

    printf("%u\n", find(num));
    return 0;    
}

void str_reverse(unsigned char *str,unsigned length)
{
    unsigned char *prv = NULL;
    unsigned char *cur = NULL;
    unsigned char swap = '\0';

    for (prv = str, cur = str + (length-1)
            ; prv < cur; ++prv, --cur){
        swap = *prv;
        *prv = *cur;
        *cur = swap;
    }
}

unsigned find(unsigned number)
{
    unsigned char number_str[NUMBER_STR_MAX_LENGTH] = {'\0'};
    unsigned char *prv = NULL;
    unsigned char *cur = NULL;
    unsigned char *finded = NULL;
    unsigned int number_length = 0;
    unsigned int result = 0;  
    int carry = 0;

    ++number;
    number_length = sprintf(number_str, "%u", number);
    str_reverse(number_str, number_length);

    for (cur = number_str + (number_length-1), finded = number_str
            ; cur > finded - 1 ; --cur ){
    
        if (prv != NULL && *prv == *cur){
            finded = cur;
            carry = 1;
            do {
                *cur += carry;
                carry = (*cur - '0') / 10u;
                *cur = (*cur-'0') % 10u + '0';
                ++cur;
            } while (carry != 0 && cur < (number_str + number_length));
            if (carry > 0){
                *cur = '0' + carry ;
                ++number_length;
            }
        }
        prv = cur;
    }

    /* set rests as 010101 */
    for (carry = 0; cur > number_str - 1; --cur){
        *cur = carry + '0';
        carry ^= 1u;
    }
    str_reverse(number_str, number_length);
    sscanf(number_str,"%u",&result);
    return result;
}

 

總結:

  1. find 函數定義不是很好,char * find(char *,int) 會更好。
  2. 不要直接處理字符傳,先處理成數組,再進行處理,等到處理完成時再處理字符串。
  3. 效率和可讀性優先 可讀,效率本來就不是個問題。 
  4. 先感謝 garbageMan對Alexia(minmin)網友代碼的評論及對“求比指定數大且最小的‘不重復數’問題”代碼的改進 中的指點。由於 finded -1  和 number_str -1 屬於 ansi c 中 關於 指針加法運算的結果 不指向 數組內或數組最后一個元素的下一個元素 的行為 沒有定義 。 把相應源碼做以下修改即可。
    for (cur = number_str + number_length, finded = number_str
            ; cur > finded;){
        cur --

    for (carry = 0; cur > number_str ;){
        cur--

   

思路

  1.  加一
  2.  從高位找重復,如果存在記住重復出現的位置,該位置加一,再從進位影響的前一位開始重復這個操作。
  3. 在第一次找重復位置之后的數依次替換為 01。輸出結果。

最后,這個程序我簡單測試過,可能還會存在錯誤。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM