1. 程式人生 > >三數之和

三數之和

分配 urn 三元組 裏的 動態分配內存 call 跳過 must 怎麽

給定一個包含 n 個整數的數組 nums,判斷 nums 中是否存在三個元素 a,b,c ,使得 a + b + c = 0 ?找出所有滿足條件且不重復的三元組。

註意:答案中不可以包含重復的三元組。

例如, 給定數組 nums = [-1, 0, 1, 2, -1, -4],

滿足要求的三元組集合為:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

這條題目應該是典型的算法優化題了吧。從方法到循環語句到判斷條件,幾乎每個地方都要寫得完美才不會TLE,雖然我寫得可能還是破綻百出。。。

碰到這種題目我都是一股腦地排列組合,也就是窮舉。。。後來在循環裏加了幾個判斷條件可以減少很多時間,但還遠遠不夠。。後來從別人那裏看到了使用左右指針的思路,不再需要排列組合,終於提交過了。。

這題主要的幾個點:

1、不能有重復的三元組。遍歷的時候判斷一下跟上一個相不相同,相同就跳過。

2、返回數組的內存分配。一開始我算出了所有排列組合的數量,但是我不知道怎麽總結出公式(我真是個智障)。。。然後愛咋咋地吧,直接分配了n*n個內存,勉強是提交過了。之後在別人的答案裏發現了realloc函數,簡直如獲至寶啊哈哈哈哈!


                a=(int **)realloc(a,sizeof(int *)*(size+1));

通過這樣就可以動態分配內存了,原先內存裏的內容也不會被覆蓋掉。

3、算法。遍歷就不提了,時間復雜度達到O(n^3),真的蠢。。主要是先取一個數,它的相反數就是我們要的target,然後就變成了twoSum,twoSum使用左右指針,每次只要o(n)的時間,最後時間復雜度只有O(n^2)。

/**
 * Return an array of arrays of size *returnSize.
 * Note: The returned array must be malloced, assume caller calls free().
 */
int cmp(const void *a,const void *b)
{
    return *(int *)a-*(int *)b;
}
int** threeSum(int* nums, int numsSize, int* returnSize) {
    int i,j,k;
    qsort(nums,numsSize,
sizeof(int),cmp); int **a=0; int size=0; int size_2=numsSize-2; int target,l,r; for(i=0;i<size_2;i++) { if(nums[i]>0) break; if(i>0&&nums[i]==nums[i-1]) continue; target=0-nums[i]; l=i+1;r=numsSize-1; while(l<r) { if(nums[l]+nums[r]==target) { a=(int **)realloc(a,sizeof(int *)*(size+1)); a[size]=(int *)malloc(sizeof(int)*3); a[size][0]=nums[i]; a[size][1]=nums[l]; a[size][2]=nums[r]; size++; while(nums[l]==nums[l+1]&&l<r) l++; while(nums[r]==nums[r-1]&&l<r) r--; l++; r--; } else if(nums[l]+nums[r]>target) r--; else l++; } } *returnSize=size; return a; }

三數之和