problem:
Given an array of n integers nums and a target, find the number of index triplets with i, j, k
that satisfy the condition nums[i] + nums[j] + nums[k] < target
.
For example, given nums = [-2, 0, 1, 3]
, and target = 2.
Return 2. Because there is triplets which sums is less than 2:
[-2, 0, 1] [-2, 0, 3]
Follow up:
Could you solve it in O(n2) runtime?
General Analysis:
This problem are easy, but really tricky! 1:the Nums may still has duplicates, but we don ' t need-care about it, since the Problme ask us to "find the Number of index triplets I, J ", which means as long as the elements is different (not value), we could record it. 2:it asks us to find all combinations smaller than "target", which was not the same as "equal" Uting answer should be different. I have made following mistakes -to-figure out the solution:
Wrong solution 1:
Public classSolution { Public intThreesumsmaller (int[] Nums,inttarget) { if(Nums = =NULL) Throw NewIllegalArgumentException ("Nums is null"); List<Integer> ret =NewArraylist<integer> (); Ret.add (0); Arrays.sort (Nums); for(inti = 0; i < nums.length-2; i++) {Twosumsmaller (nums, I+ 1, Target-Nums[i], ret); } returnRet.get (0); } Private voidTwosumsmaller (int[] Nums,intIintTarget, list<integer>ret) { intFront =i; intEnd = Nums.length-1; while(Front <end) { if(Nums[front] + Nums[end] <target) {Ret.set (0, Ret.get (0) + 1); End--; } Else{End--; } } }}
MistakesAnalysis:
Error cases:input:[3,1,0,-2], 4Output:2expected:3the above solution almost share the same code structure with 3Sum problem, excpet the condition to add"Item" into "RET" list. And we don ' t need to care about duplicates things. However, the above logic of shirking the available range is wrong for Thisproblem. Recall, for3Sum problem, we have,---------------------------------------------------if(Nums[front] + nums[end] = =target) {... front+ + (end--); <suppose we have no duplicates>}---------------------------------------------------We can move both front and end pointers. Since"Nums[front] + nums[end] = = Target", whether we move front or end pointer, iff Nums[front_new]! = Nums[front] (which is guaranteed), we still need to move end pointer. Thus, we actually need to move both pointers forpossible available ranges, no possible answer would be skipped. but for Thisproblem, it has great difference. Problemetic part:if(Nums[front] + Nums[end] <target) {... end--;} For above code, the end is still in available range, but we discard it, thus we lose some answers."Nums[front+1" + Nums[end] < target "May is possible. Fix:if(Nums[front] + Nums[end] <target) {... front++;}
Wrong Solution 2:
Public classSolution { Public intThreesumsmaller (int[] Nums,inttarget) { if(Nums = =NULL) Throw NewIllegalArgumentException ("Nums is null"); List<Integer> ret =NewArraylist<integer> (); Ret.add (0); Arrays.sort (Nums); for(inti = 0; i < nums.length-2; i++) {Twosumsmaller (nums, I+ 1, Target-Nums[i], ret); } returnRet.get (0); } Private voidTwosumsmaller (int[] Nums,intIintTarget, list<integer>ret) { intFront =i; intEnd = Nums.length-1; while(Front <end) { if(Nums[front] + Nums[end] <target) {Ret.set (0, Ret.get (0) + 1); Front++; } Else{End--; } } }}
MistakesAnalysis:
Error cases:input:[3,1,0,-2], 4Output:2expected:3even though we fix the problem forMoving pointer of Thisproblem, we still face the other important problem. The problem with above solution are that:use the same counting method of 3sum.problemetic part:if(Nums[front] + Nums[end] <target) {Ret.set (0, Ret.get (0) + 1); Front++;} If"Nums[front] + Nums[end] < target" is meet, all numbers from {Nums[front] to Nums[end-1]} must also meet the answer, with front fixed. Thus we should have following counting Method.ret.set (0, Ret.get (0) + End-front); Wander wheather it would incure duplicates in counting. Nope! Since after we move front++, forCeratin "Nums[i]", the same "nums[front]" would not appear again.
Analysis:
This New genre of problem. for (int i = 0; i < nums.length-2; i++) { + 1, target-"Nums[front] + nums[end] Meets cert Ain condition "to control the searching in available ranges and couting right answer!!! It' s an art!!! right!
Solution:
Public classSolution { Public intThreesumsmaller (int[] Nums,inttarget) { if(Nums = =NULL) Throw NewIllegalArgumentException ("Nums is null"); List<Integer> ret =NewArraylist<integer> (); Ret.add (0); Arrays.sort (Nums); for(inti = 0; i < nums.length-2; i++) {Twosumsmaller (nums, I+ 1, Target-Nums[i], ret); } returnRet.get (0); } Private voidTwosumsmaller (int[] Nums,intIintTarget, list<integer>ret) { intFront =i; intEnd = Nums.length-1; while(Front <end) { if(Nums[front] + Nums[end] <target) {Ret.set (0, Ret.get (0) + End-front); Front++; } Else{End--; } } }}
[leetcode#259] 3Sum Smaller