题目:
给定一个整数N,求编码函数f,f满足M=f(N),M可以不存在,且M和n的关系满足:
- M的位数和N相同
- M的各个位之和与N的各个位之和相同
- M>N
- M是满足上述条件中,值最小的一个解
分析:
对于整数N = 18990,将其最高位到最低位一次存在数组a[p]={1, 8, 9, 9, 0},那么要求解则需低位-1,次低位+1;但是当位为0,则无法-1;位为9则无法+1;为了找到合适的操作位,进行如下判断:
最低的不为0的位(非0才可以-1)上进行-1;在比进行-1操作高位的区间内,找最低的非9位,进行+1操作。
在进行+1、-1的操作位后,需要对比+1操作的位低的所有位进行排序,按照从高位的低位升序排列,即排列出最小值。
归纳一下,流程如下:
- 从最低位起,找出第一个非0位,如果找到,则对该位上的数进行-1操作;未找到则说明不存在M
- 找到第一个非0位后,继续从低位向高位找第一个非9的位,如果找到,则进行+1操作;未找到则说明不存在
- 比进行+1操作的位低的所有位进行排序,使其从高位到低位按升序排列;排序后的结果即为最终要求的结果M;
代码
// 百度笔试第4题.//
#include "stdio.h"
#include "stdlib.h"
//测试数据
#define N 3 //宽度
#define DATA {1,8,0} //元素依次表示从最高位到最低位
//冒泡排序
void order(int a[], int Start, int End)
{
int i,j,temp;
bool flag = false;//是否已然有序
for (i=0; i<End; i++)
{
flag = true;
for (j= Start; j< (End - i); j++)
{
if (a[j]>a[j+1])
{
temp = a[j+1];
a[j+1] = a[j];
a[j] = temp;
flag = false;
}
}
if (flag)
break;
}
}
bool Make(int a[], int n)
{
if (n<2)
{
return false;
}
int pos_0 = -1; //第一个非0的位置
int pos_9 = -1; //比第一个非0的位置,更高位中第一个非9的位置
int i;
//从最低位开始查找第一个非0的数字,找到则记录其位置,并结束查找
for ( i = n-1; i >=0; i--)
{
if(pos_0 ==-1 && a[i]!= 0)
{
pos_0 = i;
break;
}
}
//继续向高位查找非9的数字,找到则记录其位置,并结束查找
for(i--; i >= 0; i--)
{
if (pos_9 == -1 && a[i] !=9 )
{
pos_9 = i;
break;
}
}
//未找到可以进行-1操作的位
if (pos_9 == -1)
return false;
a[pos_9]++;
a[pos_0]--;
//对通过+1调整过的位置的所有低位,就行升序排列,以生成最小整数
order(a, pos_9+1, n-1);
return true;
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[N] =DATA;
bool res = Make(a, N);
if (res)
{
for(int i=0; i< N; i++)
printf("%d", a[i]);
}
else printf("not exist !!");
system("pause");
return 0;
}