首先,here is my code只是为了让您能够跟上。
#include <stdio.h>
#include <stdlib.h>
#define MAX 10000000
long long min(long long a, long long b, long long c) {
long long temp_min = a;
if (b < temp_min) temp_min = b;
if (c < temp_min) temp_min = c;
return temp_min;
}
long long numOp (long long n, long long memo[]) {
memo[1] = 0;
for (int i = 2; i <= n; i++) {
long long guess_1 = MAX, guess_2 = MAX, guess_3 = MAX;
guess_1 = memo[i - 1] + 1;
if (i % 2 == 0) guess_2 = memo[i / 2] + 1;
if (i % 3 == 0) guess_3 = memo[i / 3] + 1;
memo[i] = min(guess_1, guess_2, guess_3);
}
return memo[n];
}
int main (void) {
// Read the input from the user
long long n, v = 0, N;
scanf ("%lld", &n);
N = n;
long long num_operations[n + 1];
long long sequence[n];
for (long long i = 1; i <= n; i++) {
num_operations[i] = -1;
}
for (long long l = 0; l < n; l++) {
sequence[l] = -1;
}
// Compute the minimum number of operations required to get to n starting form 1
long long op = numOp (n, num_operations);
// Print the result
printf ("%lld\n", op);
sequence[v++] = n;
while (n > 1) {
if (num_operations[n - 1] < num_operations[n]) {
//printf("%lld ", n - 1);
sequence[v++] = n - 1;
n = n - 1;
} else {
long long temp1 = -1,
temp2 = -1;
if (n % 2 == 0) {
temp1 = num_operations[n / 2];
}
if (n % 3 == 0) {
temp2 = num_operations[n / 3];
}
if (temp2 < temp1) {
//printf("%lld ", n / 2);
sequence[v++] = n / 2;
n = n / 2;
} else {
//printf("%lld ", n / 3);
sequence[v++] = n / 3;
n = n / 3;
}
}
}
// Print the intermediate numbers from 1 up through n
for (long long k = N - 1; k >= 0; k--) {
if (sequence[k] != -1)
printf("%lld ", sequence[k]);
}
printf("\n");
return 0;
}
所以我正在研究这个输入n的问题,使得n在1到1,000,000之间。该程序适用于高达100,000的输入,但一旦达到(甚至低于)1,000,000,我就会遇到分段错误。
我调试了程序以缩小可能性并发现分段错误发生在第52行,我尝试访问数组元素。
我唯一的猜测是,对于C中的数组有多大可以获得某种限制,如果是这样的话,你们有什么方法可以解决它吗?
答案 0 :(得分:1)
当然,因为索引不能大于SIZE_MAX
。但是,在堆栈中分配自动变量时,这不是问题。堆栈的大小非常有限。您可以使用malloc
函数系列在堆上分配更多内容。当然,您受程序堆可用的限制
答案 1 :(得分:1)
您使用VLA作为call stack分配的自动变量。因此,您受限于调用堆栈的最大大小(通常只有几兆字节,详细信息是操作系统和计算机特定的)。
您应该在堆上分配这些。阅读C dynamic memory allocation。所以代码改为
long long *num_operations = calloc (n + 1, sizeof(long long));
long long *sequence = calloc(n, sizeof(long long));
不要忘记测试calloc
的失败:
if (!num_operations)
{ perror("num_operations calloc"); exit(EXIT_FAILURE); }
同样适用于calloc
sequence
不要忘记free
(例如,在main
结束时)
free (num_operations);
free (sequence);
避免memory leaks(使用valgrind调试这些)。在您的特定情况下,您可能不会free
,因为当virtual address space结束时,程序的process(在Linux或Windows上等等)被删除。
仅供参考malloc
,calloc
和free
正在使用system calls(例如mmap(2))来更改虚拟地址空间。但通常C标准库不会向操作系统发布(使用munmap
)free
- d内存,但会将其标记为未来malloc
- s或{{1}可重用} -s
在实践中,一旦它变得不必要,你就会有更好的calloc
记忆(所以你经常可以在同一个例程中free
和calloc
。阅读garbage collection技术,概念和术语是值得的。
当然,堆分配的内存也是有限的(因为您的计算机资源有限),但限制可能取决于计算机,并且通常要大得多(笔记本电脑至少为千兆字节,超级计算机可能为太字节);即使资源耗尽,有时free
似乎也可以工作(阅读memory overcommitment)(这是我通常禁用的操作系统功能)。在POSIX和Linux系统上setrlimit(2)可以用来降低(或改变一下)这个限制。