今天碰到需要给二维数组分配动态内存的题目,理了理.
给你一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?请你找出所有和为 0 且不重复的三元组。
注意:答案中不可以包含重复的三元组。
代码放在这里 :
int compare(const void* e1, const void* e2)
{
return *(int*)e1 - *(int*)e2;
}
int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){
*returnSize = 0;
if(nums==NULL || numsSize < 3)
{
return 0;
}
qsort(nums, numsSize, sizeof(int), compare);
int** ret = (int**)malloc(numsSize*numsSize*sizeof(int*));
*returnColumnSizes = (int*)malloc(numsSize*numsSize*sizeof(int*));
for(int i =0;i<numsSize-1;i++)
{
if(nums[i]>0)
{
break;
}
if (i > 0 && nums[i] == nums[i - 1])
{
continue;
}
int l = i + 1, r = numsSize - 1;
while(l<r)
{
if(nums[i]+nums[l]+nums[r]==0)
{
ret[*returnSize] = (int*)malloc(sizeof(int)*3);
ret[*returnSize][0] = nums[i];
ret[*returnSize][1] = nums[l];
ret[*returnSize][2] = nums[r];
(*returnColumnSizes)[*returnSize] = 3;
(*returnSize)++;
while(l<r && nums[l]==nums[++l]);
while(l<r && nums[r]==nums[--r]);
}
else if(nums[i]+nums[l]+nums[r] < 0)
{
l++;
}
else
{
r--;
}
}
}
return ret;
}
不过,很多人都会遇到一个问题:
这里去重为什么写成 while (left < right && nums[left] == nums[left + 1]) {left ++;} while (left < right && nums[right] == nums[right - 1]) {right --;} 这样就不行了.
原因是:
在判断的同时++,判断失败,前置++依然有效;
但是放在判断之后,left++,条件为否,就不执行了.
两者有这个区别
剩下我们来讲讲二维数组的动态内存分配,其实也不难理解
int n;
//二维数组动态分配内存
//为分配n行内存
int **arr = (int **)malloc(sizeof(int)*n);
//为每行n列内存
for(int i = 0; i < n; i++){
arr[i] = (int *)malloc(sizeof(int)*n);
}
相当于要给第一列的信息分配内存,让我们可以找到每一行,然后再给每一行分配对应个数的内存,让我们可以储存n个数.
在C语言中二维数组其实是数组的数组.但有时我们会写出越界的bug却没有报错,原因是:
编译器在处理如上代码时,并不是真的就给每行分配n个int大小的内存空间,在gcc 4.7.2-2中,通常会多分配一个int大小的内存空间。而在VC6.0中会多分配14个。
虽然从你分配的内存空间中"越界",此时它用的是空白区域的某一块内存,而C语言对数组不会进行越界检查,所以编译器并没有报错。