c语言开辟二维数组_1_13

回到 3Sum 那题里,我们确实没有像“rowCount 循环 malloc 每一行”那样去分配二维数组的每一行空间;而是每找到一个解,就:

  1. malloc(3个int) 得到 array(或 triple
  2. 把这个指针直接放进 ans[ansTop]

这两种写法本质不同,但都合法。关键在于:你到底把“二维数组”理解成哪一种内存结构


1)3Sum 那种返回值结构,本质是什么?

LeetCode 的签名是:

int** threeSum(...)

这意味着返回的是:

“指针数组 + 每行分别独立 malloc 的 int 数组”

也就是这种结构:

ans  (int**,行指针数组)
 │
 ├── ans[0] ──▶ [a, b, c]   (malloc 3 个 int)
 ├── ans[1] ──▶ [a, b, c]   (malloc 3 个 int)
 ├── ans[2] ──▶ [a, b, c]   (malloc 3 个 int)
 └── ...

注意:
每一行确实是独立开辟的malloc(3*sizeof(int))
只是它不是在“先开 rowCount 行”的循环里统一开,而是按需逐行生成


2)你说的“没有循环开辟每行空间,而是直接存 array[]”

你的代码是这样:

int* array = malloc(3 * sizeof(int));
...
ans[ansTop++] = array;

是:

把“这一行的首地址”存进 ans 的某个位置

也就是存指针。

这一步的前提是:
array 这行内存必须来自 malloc(或其他持久内存)
❌ 不能是局部数组,例如:

int array[3];          // ❌ 局部变量,函数结束就失效
ans[ansTop++] = array; // ❌ 悬空指针

3)为什么 3Sum 不适合用“先算 rowCount,再一次性循环开辟行”?

因为在 3Sum 里:

  • 你一开始不知道会有多少个三元组(rowCount 不确定)
  • 你也不知道结果会不会很多
  • 所以通常做法是:
    • 先给 ans 一个容量 cap
    • 找到一个解就 malloc(3) 生成一行
    • ans 不够就 realloc 扩容

这就是典型的“边生成边分配”。


4)两种二维数组分配方式对比(你要记住)

✅ A. 预先知道行数 rowCount(你刚才那段)

适用于:行数已知(比如读文件、固定矩阵)

ans = malloc(rowCount * sizeof(int*));
for i in rowCount:
    ans[i] = malloc(colCount * sizeof(int));

特点:先把每行都分配好,再往里填。


✅ B. 行数未知(3Sum 这种)

适用于:结果数量不确定、动态增长

cap = 128;
ans = malloc(cap * sizeof(int*));

每找到一个解:
    if ansTop == cap: realloc 扩容
    row = malloc(3 * sizeof(int));
    填 row
    ans[ansTop++] = row;

特点:找到一行分配一行,按需增长。


5)你这句话里最关键的“正确点”

“并没有循环开辟二维数组的每行空间,而是直接复制 array[]”

  • 如果 arraymalloc 出来的:✅ 这就是“逐行开辟”,完全正确
  • 如果 array 是栈数组:❌ 会出大错(悬空指针)
posted @ 2026-01-18 12:22  Leon_LL  阅读(0)  评论(0)    收藏  举报