user-0 提问: 三数之和——貌似是内存分配和数组索引问题

回复:
user: user-1
content: 引用 9 楼 Stranger_Green 的回复:[quote=引用 8 楼 u013962723 的回复:] 大兄弟，你觉得这个算法的瓶颈是在排序上？？？你有更好的算法？除去排序不谈，这已经是我找到的省时的方法了。 两个for处理。虽然里面还有两个while，但那也是为了去重，也是为了减少外面循环的次数。[/quote]  赌5毛，你传一个有序数列进去，把排序删掉一样超时 你可以自己想一下你核心算法的复杂度是多少，快排的复杂度是多少

user: user-0
content: 引用 10 楼 遇见女神 的回复:1)排序可以用c语言提供的qsort函数； 2)去重不用while循环并且先去重再下一步骤，参考你自己的代码if(XXX)continue；后来是用的qsort过的超时。 去重开始是计划把j和k的两个for放在前面的。但是后来考虑到，如果有三个或以上连续的0，0,  0，会将这组结果排除掉。 所以后来改为在确认了一组数据后，排除相同的数。这样逻辑比较直观，也不会把可能的数据除掉。

user: user-1
content: 大兄弟，你觉得这个算法的瓶颈是在排序上？？？

user: user-2
content: 1)排序可以用c语言提供的qsort函数； 2)去重不用while循环并且先去重再下一步骤，参考你自己的代码if(XXX)continue；

user: user-0
content: 引用 8 楼 u013962723 的回复:大兄弟，你觉得这个算法的瓶颈是在排序上？？？你有更好的算法？除去排序不谈，这已经是我找到的省时的方法了。 两个for处理。虽然里面还有两个while，但那也是为了去重，也是为了减少外面循环的次数。

user: user-0
content: 自己找到这个问题了，temp == 0后，赋值结束后，没有对j++和k--，以至于陷在循环里了。 但是代码改好后，竟然还是超时。郁闷啊，快排不够快吗？ void quickSort(int* nums, int left, int right); int** threeSum(int* nums, int numsSize, int* returnSize, int** returnColumnSizes){          if(numsSize < 3)     {         *returnSize = 0;         return NULL;     }       int **re = (int**)malloc(sizeof(int*) * numsSize * 2);     *returnColumnSizes = (int*)malloc(sizeof(int) * numsSize * 2);        quickSort(nums, 0, numsSize - 1);     int geshu = 0;     for(int i = 0; i < numsSize - 2 && nums[i] <= 0; i++)     {         if(i > 0 && nums[i] == nums[i-1])             continue;         for(int j = i + 1, k = numsSize - 1; j < k && nums[k] >= 0;)         {                                              long temp = nums[i] + nums[j] + nums[k];             if(temp == 0)             {                 re[geshu] = (int*)malloc(sizeof(int) * 3);                 re[geshu][0] = nums[i];                 re[geshu][1] = nums[j];                 re[geshu][2] = nums[k];                 (*returnColumnSizes)[geshu++] = 3;                 while(j < k && nums[j] == nums[j + 1])                     j++;                 while(j < k && nums[k] == nums[k - 1])                     k--;                 j++;                 k--;             }             else if(temp > 0)             {                 k--;             }             else             {                 j++;             }                              }             }         * returnSize = geshu;     return re; } void quickSort(int* nums, int left, int right) {     if(left >= right)         return;     int i = left, j = right, key = nums[left];     while(i < j)     {         while(i < j && nums[j] >= key)             j--;         nums[i] = nums[j];         while(i < j && nums[i] <= key)             i++;         nums[j] = nums[i];     }     nums[i] = key;     quickSort(nums, 0, i - 1);     quickSort(nums, i + 1, right); }

user: user-0
content: 引用 4 楼 user-3 的回复:[quote=引用 3 楼 Stranger_Green 的回复:] [quote=引用 2 楼 user-3 的回复:]  int **re = (int**)malloc(sizeof(int*) * 1500);  这个是个什么操作？分配返回的是指针，你强转为二级指针他的值还是指向分配空间的一个指针地址 re存了一个地址A，A地址中存了一个指针B，这个操作是让B=分配的地址 你的固定是返回三个数字的， 直接分配 单个空间*3*总数量的一维来解决, struct num_struct {int num1; int num2; int num3; } num_struct * re=malloc(sizeof(num_struct)*1500; XX XX XX XX XX XX |          |     |          | ________     ________     re[0]       re[1] 二维数组一直都是那样分配内存的。1500那个，是因为事先不知道这个数组geshu多少行。只好先定一个一个大点儿的值。 re[geshu] = (int*)malloc(sizeof(int) * 3);  是为每一行re[geshu]的大小分配，确定是三个数字。re[geshu][0]，re[geshu][1]， re[geshu][2]。 如果按照你说的，只在第一次为re分配内存。每行不单独分配时，运行到下方re[geshu][0] 时，会报错的。[/quote] 只要你分配的够的话，怎么会出错呢，调用改一下re[geshu]->num1; 你目前的是 地址一->指针->指向三个数的地址 地址二->指针->指向三个数的地址 ... 地址N->指针->指向三个数的地址 数组加动态 你不确定的话就用结构体链表来解决动态的问题，需要一个就分配一个。[/quote]题目给的要求是，返回二维数组。并且要给出二维数组大小。 问题就是，我现在测试输入的nums，只是包含五个数的数组，上面的分配，肯定不会不够啊。但不知道为啥就是一直报错。找了一下午都没搞定。

user: user-3
content: 引用 3 楼 Stranger_Green 的回复:[quote=引用 2 楼 user-3 的回复:]  int **re = (int**)malloc(sizeof(int*) * 1500);  这个是个什么操作？分配返回的是指针，你强转为二级指针他的值还是指向分配空间的一个指针地址 re存了一个地址A，A地址中存了一个指针B，这个操作是让B=分配的地址 你的固定是返回三个数字的， 直接分配 单个空间*3*总数量的一维来解决, struct num_struct {int num1; int num2; int num3; } num_struct * re=malloc(sizeof(num_struct)*1500; XX XX XX XX XX XX |          |     |          | ________     ________     re[0]       re[1] 二维数组一直都是那样分配内存的。1500那个，是因为事先不知道这个数组geshu多少行。只好先定一个一个大点儿的值。 re[geshu] = (int*)malloc(sizeof(int) * 3);  是为每一行re[geshu]的大小分配，确定是三个数字。re[geshu][0]，re[geshu][1]， re[geshu][2]。 如果按照你说的，只在第一次为re分配内存。每行不单独分配时，运行到下方re[geshu][0] 时，会报错的。[/quote] 只要你分配的够的话，怎么会出错呢，调用改一下re[geshu]->num1; 你目前的是 地址一->指针->指向三个数的地址 地址二->指针->指向三个数的地址 ... 地址N->指针->指向三个数的地址 数组加动态 你不确定的话就用结构体链表来解决动态的问题，需要一个就分配一个。

user: user-0
content: 引用 2 楼 user-3 的回复:int **re = (int**)malloc(sizeof(int*) * 1500);  这个是个什么操作？分配返回的是指针，你强转为二级指针他的值还是指向分配空间的一个指针地址 re存了一个地址A，A地址中存了一个指针B，这个操作是让B=分配的地址 你的固定是返回三个数字的， 直接分配 单个空间*3*总数量的一维来解决, struct num_struct {int num1; int num2; int num3; } num_struct * re=malloc(sizeof(num_struct)*1500; XX XX XX XX XX XX |          |     |          | ________     ________     re[0]       re[1] 二维数组一直都是那样分配内存的。1500那个，是因为事先不知道这个数组geshu多少行。只好先定一个一个大点儿的值。 re[geshu] = (int*)malloc(sizeof(int) * 3);  是为每一行re[geshu]的大小分配，确定是三个数字。re[geshu][0]，re[geshu][1]， re[geshu][2]。 如果按照你说的，只在第一次为re分配内存。每行不单独分配时，运行到下方re[geshu][0] 时，会报错的。

user: user-3
content: int **re = (int**)malloc(sizeof(int*) * 1500);  这个是个什么操作？分配返回的是指针，你强转为二级指针他的值还是指向分配空间的一个指针地址 re存了一个地址A，A地址中存了一个指针B，这个操作是让B=分配的地址 你的固定是返回三个数字的， 直接分配 单个空间*3*总数量的一维来解决, struct num_struct {int num1; int num2; int num3; } num_struct * re=malloc(sizeof(num_struct)*1500; XX XX XX XX XX XX |          |     |          | ________     ________     re[0]       re[1]

user: user-0
content: 如果把Line222和Line333处改为： int **re = (int**)malloc(sizeof(int*) * (numsSize + 1) * 6); *returnColumnSizes = (int*)malloc(sizeof(int) * (numsSize + 1) * 6);   报错信息就是： ================================================================= ==29==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x613000000190 at pc 0x00000040251a bp 0x7ffc37c0d980 sp 0x7ffc37c0d978 WRITE of size 8 at 0x613000000190 thread T0     #2 0x7f4b2a50c2e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0) 0x613000000190 is located 0 bytes to the right of 336-byte region [0x613000000040,0x613000000190) allocated by thread T0 here:     #0 0x7f4b2bdbb2b0 in malloc (/usr/local/lib64/libasan.so.5+0xe82b0)     #3 0x7f4b2a50c2e0 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x202e0) Shadow bytes around the buggy address:   0x0c267fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   0x0c267fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   0x0c267fff8000: fa fa fa fa fa fa fa fa 00 00 00 00 00 00 00 00   0x0c267fff8010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00   0x0c267fff8020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 =>0x0c267fff8030: 00 00[fa]fa fa fa fa fa fa fa fa fa fa fa fa fa   0x0c267fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa   0x0c267fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa   0x0c267fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa   0x0c267fff8070: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa   0x0c267fff8080: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa Shadow byte legend (one shadow byte represents 8 application bytes):   Addressable:           00   Partially addressable: 01 02 03 04 05 06 07    Heap left redzone:       fa   Freed heap region:       fd   Stack left redzone:      f1   Stack mid redzone:       f2   Stack right redzone:     f3   Stack after return:      f5   Stack use after scope:   f8   Global redzone:          f9   Global init order:       f6   Poisoned by user:        f7   Container overflow:      fc   Array cookie:            ac   Intra object redzone:    bb   ASan internal:           fe   Left alloca redzone:     ca   Right alloca redzone:    cb ==29==ABORTING