求比指定数大且最小的“不重复数”问题
给定任意一个正整数,求比这个数大且最小的“不重复数”,“不重复数”的含义是相邻两位不相同,例如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
" , find(num)); return 0; } void str_reverse(unsigned char *str,unsigned length) { unsigned char *prv = NULL; unsigned char *cur = NULL; unsigned char swap = ' ' ; 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] = { ' ' }; 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 reset 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; } |
总结:
- find 函数定义不是很好,char * find(char *,int) 会更好。
- 最好不要用指针,影响效率。
- 不要直接处理字符传,先处理成数组,再进行处理,等到处理完成时再处理字符串。
- 效率和可读性优先 可读,效率本来就不是个问题。
思路
- 加一
- 从高位找重复,如果存在记住重复出现的位置,该位置加一,再从进位影响的前一位开始重复这个操作。
- 在第一次找重复位置之后的数依次替换为 01。输出结果。
最后,这个程序我简单测试过,可能还会存在错误。