请大家再来思考一下这个问题
题目:给定正整数 k 和 n 位正整数 a (0 <= k <= n)。
从 a 中删掉任意 k 位数字,将剩下的给位数字按原次序排列组成一个新的正整数。
对于给定的 n 位正整数 a 和正整数 k,编程计算从 a 中删去 k 位数字后能够得到的最小的数。
[例]
输入: 5412873 3
输出: 1273
请大家贴出自己的思考也好,分析也好,算法也好,代码也好,多多交流,共同进步。
以下是我的思路和实现:
程序代码:
/* 分析: 以 a[i], (0 <= i < n)表示 n 位正整数 a 的第 i 位, a[0] 为最高位, a[n - 1] 为最低位, n 位数字 a 可以写成以下形式: a[0] * 10 ^ (n - 1) + a[1] * 10 ^ (n - 2) + a[2] * 10 ^ (n - 3) + ... + a[n - 2] * 10 ^ 1 + a[n - 1] * 10 ^ 0 经观察可知 d[0] 比 d[k], (0 < k < n) 对数字 a 的值的影响比 d[k] 更为明显, 我们说 d[0] 比 d[k] 更为重要. 一般而论, d[i] 比 d[k], (i < k < n) 更为重要. 题目要求“剩下的数字按原次序排列组成一个新的正整数”和“对于给定的正整数 a,编程计算删去 k 个数字后得到的最小数”. 因此思考的重点为如何得到最小的数. 设 n - k = m, 题目的正确答案为 m 位数字 b, 则 b[0] 必然是 a[0] ~ a[k] 中的一位数字, 且 b[0] 为 a[0] ~ a[k] 中 最小的一位数字, 如下例: n = 4, a = 4123, k = 2; 从 4 位正整数 a 中删掉任意 2 位后,可能的结果为: 12 13 23 41 42 43 b = 12, b[0] = 1 = a[2] 为 a[0] ~ a[2] (即 4, 1, 2) 中最小的数字. 因此我们所设计的程序应首先找出a[0] ~ a[k] 中最小的一位 a[j], 并将此位作为答案的最高位 b[0]. 要达到此目的,必须从 n 为正整数 a 中删除 a[0] ~ a[j - 1] 共 j 位. 因 a[j] 需要保留作为答案 b 的最高位,因此应将 j 从剩下的需要继续删除的数字中排除. 至此我们已经从 n 位正整数 a 中删除了 j 位,并排除了 1 位,接下来我们还需要删除 k - j 位. 为了保证最后的答案 b 最小, 必须保证从剩下的 n - j 位中删除 k - j位后所得的数字最小,为此我们只需要重复上述过程, 直至一共删除 k 位为止. 算法: 1. s = 0; s 表示搜索的起始位置 2. 找出 a[j] == min(a[s], a[s + 1], ... , a[k]) 3. a[0] = -1, a[1] = -1 ... a[j - 1] = -1; a[0] = -1 表示删除a[0]; 4. s = j + 1, k -= j - s; 从 a[j] 的下一位开始进行下一次的搜索, 即将 a[j] 从待删除数字中排除 5. 重复 2 ~ 4, 直至 k == 0 || n - s == k; n - s == k 时不需要再进行搜索, 只要把 a[s] ~ a[n] 全部删掉即可 代码: */ #include <stdio.h> #include <string.h> int main() { char a[100] = {0}, i, j = 0, n, s = 0, is_1st_digit = 1; int k; printf("Please input number a: "); scanf("%s", a); n = strlen(a); printf("Please tell me how many digits to be deleted: "); scanf("%d", &k); while (k > 0 && k < n - s) { // find the minimun digit a[j] for (i = s; i <= s + k; i++) { if (a[i] < a[j]) { if (!is_1st_digit || a[i] != '0') { j = i; } } } // delet digits a[s] ~ a[j - 1] for (i = s; i < j; i++) { a[i] = -1; } // calculate how many more digits need to be deleted k -= j - s; // next search will start from a[j + 1] j++; s = j; // there is only one 1st digit and we've already found it, so is_1st_digit = 0; } if (k > 0) { // delete digits d[s] ~ d[n] n = s; } // printf() the answer. for (i = 0; i < n; i++) { if (a[i] != -1) { printf("%c", a[i]); } } printf("\n"); return 0; }
[ 本帖最后由 voidx 于 2011-4-18 14:04 编辑 ]