数字问题---位数上的数字

来源:互联网 发布:天启知乎 编辑:程序博客网 时间:2024/04/29 01:25

【座右铭】1. 想要成为行家,就必须尝试解决大量的问题;

                    2. 解决大量问题并不代表能解决所有问题,而是表示解决下一个问题的几率变大了


1. 已知一个整数集合T,集合中可以包括0到9之间任意数,集合中数字不重复。现在给出一个整数N,大小按int类型,算法要求是:从上面集合中取出数字所能组成的整数中,比给出的N大的集合里面, 最小的那个整数。比如,整数集合T=『1,2,3』,整数N=300,那么要从集合中取出数字所组成的整数应该是311;再如:T=『1』,N=56,那么要得到的整数应该是111(也就是说集合里面的 数可以取多次);【问题来源于论坛】

第一部分:

思路一: 从小到大遍历[N+1, IntegerMax],找出满足所有数字在集合T中的第一个整数

思路二:对整数N,从N的最高位向最低位扫描,求出满足条件的整数M

1)若Ni位不是最后1位,且在集合T中出现,则Mi=Ni

2)若Ni位是最后1位,或者不在集合T中出现,则

2.1) 若集合T中存在大于Ni且最小的数字a,让Mi=a。然后让余下的位置(比i位要低的位置)都取T中的最小值

2.2) 若集合T中不存在大于Ni的数字,则对Mi-1位进行处理。找出比Mi-1位数字大的且在集合T中的元素,若Mi-1位仍不满足,则继续前进找Mi-2位,直到满足条件为止(最坏情况下多补1个最高位)。然后将余下的位置(比满足条件的位置要低的位置)都取T中的最小值

第二部分:

//java代码,T为集合,len为集合T中元素个数,N为整数

//不考虑异常情况:例如N为负数,或者是整数最大值

public static int greater(int[] T, int len, int N){//初始化集合Tboolean[] set = new boolean[10];int min = 10;for(int i=0;i<len;i++){min = (min>T[i])? T[i]:min;set[T[i]] = true;}//初始化Aifinal int IntegerLen = 11;int[] source = new int[IntegerLen];int j = 0;if(N==0){source[j++] = 0;}else{while(N>0){source[j++] = N%10;N /= 10;}}j--;int[] target = new int[IntegerLen];int k = 1; //预留一位while(j>=0){if(j!=0&&set[source[j]]){//若Ni位在集合T中存在,则Mi=Nitarget[k++] = source[j];j--;}else{//在集合T中选取一个比Ni大且最小的数字int bigger = -1;for(int p=source[j]+1;p<10;p++){if(set[p]){bigger = p;break;}}if(bigger!=-1) //找到{target[k++] = bigger;j--;}else //未找到{int dis = k;k--;boolean flag = false;while(!flag){for(int p=target[k]+1;p<10;p++){if(set[p]){flag = true;target[k++] = p;break;}}if(!flag){k--;}}j += (dis - k);}//后面的数都取集合T中的最小值while(j-->=0){target[k++] = min;}}}//组成新的数字int M = target[0];int position = 0;while(++position<k){M *= 10;M += target[position];}return M;}

第三部分: 测试用例

T = {9,2,3}, N = 0: M = 2

T = {1,2,3}, N = 2: M = 3

T = {1,2,3}, N = 4: M = 11

T = {1,2,3}, N = 23: M = 31

T = {1,2,3}, N = 33: M = 111

T = {1,2,3,9}, N = 9999: M = 11111


2. 有这样一种编码:如,N=134,M=f(N)=143,N=020,M=fun(N)=101,其中N和M的位数一样,N,M可以均可以以0开头,N,M的各位数之和要相等,即1+3+4=1+4+3,且M是大于N中最小的一个,现在求这样的序列S,N为一个定值,其中S(0)=N,S(1)=fun(N),S(2)=fun(S(1))。【问题来源于v_JULY_v的博客:http://blog.csdn.net/v_july_v/article/details/6855788

第一部分:

思路一: 从小到大遍历[N+1, IntegerMax],找出满足数字和相同的第一个整数

思路二:从低位往高位扫描

1)从低位往高位扫描,找出第一位大于0的位数i的数字a,将该位赋值0,将未分配的数字和T加上a-1,即T=T+a-1。将第i-1位(比i位高1位)数字b加1

1.1)若第i-1位的数字b<10,进入第2步

1.2)若第i-1位的数字b=10,则将该位赋值0,且T=T+9;将第i-2位数字c加1。直至找到满足条件的位置(最坏情况下多增加1位),进入第2步

2)将T从最低位向高位分配,直至T=0。分配原则为:小于等于9,全部放在当前配置;大于9,给当前位置放9

第二部分:

//java代码,参数说明:N为整数

//不考虑异常情况:如N负数,或者为0

public static int next(int N){//求出数字和final int IntegerLen = 10;int[] source = new int[IntegerLen];int i = 0, sum = 0;while(N>0){source[i] = N%10;sum += source[i];i++;N /= 10;}//从地位向高位走int j = 0;while(source[j]==0){j++;}//把高1位的位置加1int total = source[j]-1;source[j] = 0;j++;while(true){if(source[j]==9){source[j++] = 0;total += 9;}else{source[j]++;break;}}//将数从地位向高位分配int k = 0;while(total!=0){if(total<=9){source[k] = total;total = 0;}else{source[k++] = 9;total -= 9;}}//组合新数字int M = 0;for(int p=IntegerLen-1;p>=0;p--){M *= 10;M += source[p];}return M;}
第三部分:测试用例

N = 1: M = 10

N = 10: M = 100;

N = 20: M = 101;

N = 101: M = 110;

N = 110: M = 200;

N = 99: M = 189

原创粉丝点击