Tutorial for Not a Triangle |
The problem Not a Triangle asks us to find out the number of triplets from the given list that do not form a triangle. Let us revise a fundamental property - "Three numbers cannot form a triangle if the sum of any two is less than the third". Keeping this in mind, we can start building our solution.
Let us take a look at a naive solution. Consider all possible triplets and for each triplet check if the numbers are such that they do not form a triangle. Such a solution would work, but will it run within the time limit? Let us take a look at the time complexity of such a solution. It is of the order O(n^3). The value of 'n' can go up to 2000. So we are looking at more than 10^9 operations. This will not work in the given time period. So, we need to reduce the time complexity of our solution.
One thing we need to observe is that we don't need the actual triplets, we just need the number of triplets. In the solution described above, given 2 numbers, we need roughly 'n' comparisons in the worst case to find the number of values for which, having fixed the other two values, the sum of the two values selected is lesser than the third value we select. Now, if we are able to find such a value X for the selected 2 values such that X > sum_of_the_two_values, then any value greater than or equal to X will also satisfy the equation. So, our problem boils down to finding the lowest value X such that having selected 2 of the numbers, X > sum_of_the_two_values.
In such cases, sorting the values initially can help us. Let us sort the numbers that we take in for each test case. Now, having selected 2 of the numbers, we need to be able to find the number X in a complexity lower than O(n). As we can see, this is possible by using a technique called binary search. Consider that our array(A) of elements in sorted order is {10,20,30,40,50} and the 2 elements we have selected are 10 and 20. Now, we need to find the lowest number X such that X > 10+20. For this, we consider the interval of elements immediately after 20 till the end. In binary search, we make use of the fact that if a number T does not satisfy the given criteria, then either the numbers before T or the ones after T too will not satisfy the criteria. The technique is called binary search as at every stage, we maintain two values 'low' and 'high' which represent the interval that we are searching. We find the midpoint of this interval 'mid'=(low+high)/2. If the value at position 'mid' satisfies our criteria i.e. A[mid]>10+20, then there can be a lower value that satisfies the same criteria in the interval [low,mid]. So, we make the current value of 'mid' as the new value of 'high' and carry out the same procedure in the new interval. If we find that the new value at position 'mid' does not satisfy the criteria, then we can safely disregard all values below that value including it. This gives us our new interval as [mid+1,high]. Eventually, we will reach a state where the values of 'low' and 'high' are the same. This is when we have either found our required value X i.e. the lowest value such that X>sum_of_other_two_values or such a value does not exist in the array that we have.
Considering our array, let us see the values of low and high at every iteration. We start off with low=3 and high=5 which are the positions immediately after 20 and the last position respectively.
| Iteration | Low | High | Mid | A(mid) |
| 1 | 3 | 5 | 4 | 40 |
Now, we see that A[Mid] is 40 which is greater than 10+20. In the worst case, our answer can be 40, though there might be a chance that a better answer below 40 might be found. So, we change our interval to (Low, Mid), which is the same as changing the value of High to that of Mid. So in the second iteration, our values are:
| Iteration | Low | High | Mid | A(mid) |
| 2 | 3 | 4 | 3 | 30 |
We carry out integer division so (3+4)/2 = 3. Now 30 is not greater than 10+20. Thus, we can rest assured that we can't find the required number in the interval Low to Mid inclusive. So we need to search for an answer in the interval (Mid+1, High) which is the same as changing the value of Low to that of Mid+1. So in the next iteration our values change to :
| Iteration | Low | High | Mid | A(mid) |
| 3 | 4 | 4 | 4 | 40 |
We see that the values of Low and High are equal. So we have either found the required value X or such a value does not exist. We break out of the loop and make a final check to see if A[Mid] is greater than 10+20 and we see that it is. So, all numbers greater than and including the value at position Mid will not form a triangle with our selected numbers 10 and 20. This number is '2' and the numbers are 40 and 50. We add this to our final answer and continue finding other triplets.
Some care needs to be taken so that we don't consider the same triplet more than once. For this, selection of the two numbers needs to be done in such a way that the position of the second number being selected is always greater than the position of the first number. Also, the position of the third number is greater than that of the second number.
With a bit of preprocessing and usage of extra memory, it is possible to find the answer with a lower time complexity. We leave that as an exercise for the reader.
Comments


I codded this problem with
I codded this problem with binary search and bubble sort and still for an input of 2000 sticks it gets the answer after 18 secs .
I'm not sure why you're using
I'm not sure why you're using bubble sort which is a slow sort, but even still, you must have coded something wrong to get that sort of time.
how can i get the running tym
how can i get the running tym of my code as karim is getting 18 secs...how can i know this??
i solved the problem
i solved the problem accordingly and getting the right answer but for some test cases which i don't know, answers are wrong........
my selection of two numbers("first" and "second") are like this.....................
at the start first is pointing to the first element and second to the second........and third can be between third to the last element....as said in the tutorial.......
if i get a minimum 'X'.... such that X > first+second;
then my second selection of numbers will be first remains the but second is pointing to third and third can be between fourth and the last.....again if i get a minimum X > first + second... i repeat the same procedure.......n if any time i din get the minmum required 'X' then i check if second - first <= 2..... if so then i abort finding more......or else i do first = intial second(i.e. second pointing to the second)......second = to the very next element of first......... then i repeat the same procedure......... i m posting that part of my code.... plz take a look..... n if possible provide me with some test case which wont work with that........................
int x = 0, y = 1,z = y; bool flag = true;
while(flag){
int a= stick[x],b = stick[z];
int low = z+1, high = n-1,mid = (low+high)>>1;
while(low<n&&high<n&&low!=high){
if(stick[mid]>a+b) high = mid,mid = (low+high)>>1;
else low = mid+1, mid = (low+high)>>1;
}
if(stick[mid]>a+b)count += (n-mid),z++;
else if(z-x<=2)flag =0;
else x = y++,z=y;
}
any one?
any one?