又是一道因为不注意基础知识然后出错的题。
题目
题解
最近做题有一个心得,一定要仔细审题!一审题目要求;二审各数值的范围。二审非常重要,这关系到我们最终选择哪种方法解决问题,也关系到解答时是否需要注意数值溢出的问题。举例,如果参数的范围比较小,那么也许我们就可以考虑比较简单、直接的方式求解题目。但是如果这道题参数范围过于大,那么暴力求解就不开行,我们就要考虑别的节省时间和空间的方法。
这道题里,road的最大长度是100000,不算太大,所以我就可以考虑构建一个stack[100000]来保存每个连续坑洼的具体数量。但是如果road的最大长度更大,那我就要考虑一种不会产生空间错误的解法。
这道题的思路,总体分为两步:
1.遍历road的,获取每个连续坑洼的具体数量。存于stack里,然后将stack降序排序。例如: x...xx.xxx.....xxxxx。在stack中就存为:{5,3,2,1};
2.从头遍历stack,保证budget>0,做如下操作:
tem=min(budget-1,stack[i]);
cnt=cnt+tem;
budget=budget-(tem+1);
实现的代码如下:
#define Max_lenth 100000
// 比较函数,用于降序排序
int cmp(const void *a, const void *b) {
return (*(int *)b - *(int *)a);
}
int min(int a, int b) {
return a < b ? a : b;
}
int maxPotholes(char* road, int budget) {
if (!strlen(road)) return 0;
int res = 0, cnt = 0, top = 0;
int stack[Max_lenth];
// 初始化 pre 为一个无效字符
char pre = '\0';
int road_len = strlen(road);
// 遍历数组,得到连续的坑洼数量
for (int i = 0; i < road_len; i++) {
char c = road[i];
if (c == 'x') {
if (top == 0 || pre == '.') {
stack[top++] = 1;
}
if (pre == 'x') {
stack[top - 1]++;
}
}
pre = c;
}
if (top) {
qsort(stack, top, sizeof(int), cmp);
}
for (int i = 0; i < top && budget > 0; i++) {
int tem = min(budget - 1, stack[i]);
cnt += tem;
budget -= 1 + tem;
}
return cnt;
}
踩的坑
排序这里踩了大坑!
我使用的c语言的内置排序方法qsort,它的使用格式为:
qsort(a, n, sizeof(sizeof(a[0]), compare);
a:要排序的数组
n:数组里元素的个数
sizeof(sizeof(a[0]):元素类型的大小
compare:自己定义的比较函数
刚开始我定义的compare函数如下:
int cmp(int a, int b) {
return b-a;
}
然后我就发现,有的测试用例排序这步有问题,没按照降序排,我就猜测是排序方法出了问题。
改进compare函数,使用标准的写法:cmp
函数现在接受两个 const void*
参数,根据具体需要进行适当的类型转换。如下:
int cmp(const void *a, const void *b) {
return (*(int *)b - *(int *)a);
}
为什么第一个compare不稳定?
好叭,我暂时没找到具体原因,先记录下来,以后补充。但是得到一个经验:尽量使用标准的写法。