本题来自@陈利人 微信公众账户:待字闺中
原题
对于一个n位正整数a,去掉其中任意k(k<=n)个数字后,剩下的数字按原次序排列可以组成一个新的正整数。设计一个删除算法,使得剩下的数字组成的正整数最小。
例如,a=13243221,k=5,输出:121
对于题目中的例子,数字13243221,删除5个数字之后,使得剩下的几个数字组成的整数最小。先考虑简单的解决办法:
当k=1时,如果要删除13243221中的一个数字使得剩下的几个数字组成的整数最小,很显然,应该删除第二位数字3,这样剩下的整数为1243321
对于1243321整数1243321,当k=1时,要使剩下的整数最小,那么应该删除数字4,这样剩下的整数为123321
对于整数123321,当k=1时,要使剩下的整数最小,那么应该删除一个数字3,剩下的整数为12321
从上面的分析可以发现,对于k=1,如果所给定的整数的数字从左到右时升序,那么应该删除最右边的一个数,剩下的数字组成的整数最小,如果所给定的整数的数字从左到右为降序,那么应该删除最左边的数字使得剩下的数字所组成的整数最小。例如k=1时,整数123,应该删除最右边的3,所得的整数最小,又如k=1时,整数321,那么应该删除最左边的3,所得的整数最小。
那么k>1时,只需重复上面的步骤,直至k=0。
所以,对于整数a,删除k个数字后使所得整数最小的算法如下:
1.从左到右扫描整数a,比较相邻的位的数字a[i]与a[i+1]的大小;
2.若a[i] < a[i+1],那么i++,直到a[i] >= a[i+1]或者到达整数最右边;
3.删除a[i],k--,若k > 0则重复步骤1。
对应算法如下:
void deleteNum(char *input, int k) {
int len, i;
len = strlen(input);
if(k > len) {
printf("error:K > strlen(input)\n");
return;
}
while(k > 0) {
for(i = 0; i < len-1; i++){
if(input[i] > input[i+1])
break;
}
for(; i < len; i++) {
input[i] = input[i+1];
}
k--;
len--;
}
}
void deleteNumOptimized(char *input, int k) {
int len, i, j;
len = strlen(input);
if(k > len)
{
printf("error\n");
return;
}
i = 0;
while(k > 0) {
if(i == 0 || input[i] < input[i+1]){
while(i < len-1 && input[i] < input[i+1]) {
i++;
}
} else {
while(i >0 && input[i] < input[i-1]) {
i--;
}
}
for(j = i; j < len; j++) {
input[j] = input[j+1];
}
k--;
len--;
}
}
这题属于比较简单的题型,从这个题中可以看出多应用已经得到的信息,可以对算法进行优化。
在面试笔试过程中,写代码要先判断数字的长度是否小于k值,这个细节也比较重要。