目录
题目
给定一个数 n,如 23121,给定一个数组 A 如 {2,4,9},求由 A 中元素组成的、小于 n 的最大数。
解题思路:考察边界问题。
- 从 n 的高位开始,逐位确定 A 中找到的符合条件(等于或小于)的最大数字;
- 如果存在且等于,直接取数字。
- 如果存在且小于,直接取数字,且打上让位标记。
- 如果不存在,直接取 0,且打上取 0 标记。
- 如果存在让位标记或取 0 标记,则后续所有位直接取 A 中的最大数字。
#include <stdio.h>
#include <stdlib.h>
// 比较函数,用于排序数组 A
int compare(const void *a, const void *b) {
return (*(int *)b - *(int *)a);
}
int find_max_num(int n, int *A, int size) {
char n_str[20]; // 假设最大数不超过 20 位
sprintf(n_str, "%d", n); // 将 n 转换为字符串
printf("n_str: %s\n", n_str);
qsort(A, size, sizeof(int), compare); // 将数组 A 按照从大到小的顺序进行排序,确保选择的数字是最大的。
int result = 0; // 最终结果
int i = 0; // n_str idx
int j = 0; // A idx
/* 边界情况标记 */
int lt_flags = -1; // 标记 A 中存在小于 n_str curr idx 的数字,结果中后续的每位直接取 A 中的最大数字即可
int zero_flags = -1; // 标记 A 中不存在等于或小于 n_str curr idx 的数字,结果中后续的每位直接取 A 中的最大数字即可
// 循环 n_str idx
while (n_str[i] != '\0') {
int found_flags = -1; // 标记从 A 中找到符合条件的(等于或小于 n_str curr idx)的最大数字
int max_num = -1; // 记录 A 中找到符合条件的最大数字
// 循环 A idx
for (j = 0; j < size; j++) {
// 如果存在边界情况,直接返回 A 中最大的数字
if ((lt_flags != -1) || (zero_flags != -1)) {
found_flags = j;
max_num = A[j];
break;
// 否则,从 A 中返回等于或小于的数字,并更新 found_flags 标志
} else {
if (A[j] == (n_str[i] - '0')) {
max_num = A[j];
found_flags = 1;
break;
}
// 小于时,需要更新 lt_flags 边界标志
if (A[j] < (n_str[i] - '0')) {
max_num = A[j];
found_flags = 1;
lt_flags = 1;
break;
}
}
}
// 找到了符合条件的数字,则将该数字添加到结果中
if (found_flags != -1) {
result = result * 10 + max_num;
// 没有找到,则让一位(上 0),并更新 zero_flags 标志
} else {
result = result * 10 + 0;
zero_flags = 1;
}
i++;
}
return result;
}
int main() {
int n = 23121;
// test: int n = 11111;
int A[] = {
2, 4, 9};
int size = sizeof(A) / sizeof(int);
int result = 0;
result = find_max_num(n, A, size);
printf("result: %d\n", result);
}