-1

I was solving a question on GeeksforGeeks regarding finding the total number of triangles possible using the three different array elements as sides of the triangle from an unsorted array arr[] of size n. This is the first implementation for the above question. ...

int findNumberOfTriangles(int arr[], int n)
    {
        // code here
        sort(arr,arr+n);
        
        int i,j,k,count=0;
        
        for(i=0;i<n-2;i++)//first side of triangle
        {
            k=i+2; // third side of triangle , ie. rightmost element initialized
            for(j=i+1;j<n;j++)    //second side of triangle
            {    
                // search for all elements less than sum of the 
                // first and second side of the triangle
                while(k<n)
                {
                    if(arr[i]+arr[j]>arr[k]) 
                        k++;                
                }
                
                count=count+ k-j-1; //adds no of triangle possible for each pair of sides
            }
        }
        
        return count;
    }

... The above implementation is correct and should have O(N^2) time complexity. For the above code, I am getiing a TLE(Time Limit exceeded) from GeeksforGeeks platform with expected time limit=1.02 sec.

Now compare the following implementation to the above implementation.

int findNumberOfTriangles(int arr[], int n)
        {
            // code here
            sort(arr,arr+n);
            
            int i,j,k,count=0;
            
            for(i=0;i<n-2;i++)//first side of triangle
            {
                k=i+2; // third side of triangle , ie. rightmost element initialized
                for(j=i+1;j<n;j++)    //second side of triangle
                {    
                    // search for all elements less than sum of the 
                    // first and second side of the triangle
                    while(k<n && arr[i]+arr[j]>arr[k])
                         k++; 
                    
                    count=count+ k-j-1; //adds no of triangle possible for each pair of sides
                }
            }
            
            return count;
        }

The implementation differs only in the while loop inside second for loop.I moved the if condition from inside of the while body to the condition declaration part by using the Logical AND operation. The time complexity for this is same as the first implementation :O(N^2).

But , this implementation was accepted by GeeksforGeeks with time taken = (0/1.0).

Can someone tell me why is there so much performance difference between two equivalent pieces of code. Is this due to GeeksforGeeks platform or due to the features of the C++ language. GeeksforGeeks uses g++5.4 compiler

Link : https://practice.geeksforgeeks.org/problems/count-possible-triangles-1587115620/1

Saurav
  • 19
  • 2
  • first of all if You say (and would press) that Your solution is right, then why the hell You get Time Limit exceeded? ; ) Answer: Because it is not and be curious and not wear blinkers of self-esteem when asking Mate. ;) – badasz Jul 14 '21 at 20:27
  • A good way to find differences (and sometimes trash that self-esteem) is to step through the code in a debugger. The debugger shows you exactly what you told the computer to do regardless of what you wanted it to do. Figure out the reason for the discrepancy between that the computer does and what you wanted it to do and you've solved the bug. – user4581301 Jul 14 '21 at 20:30

1 Answers1

3

They are not equivalent.

            while(k<n)
            {
                if(arr[i]+arr[j]>arr[k]) 
                    k++;                
            }

On the first element that is encountered for which the if condition is false, this loop will continue to loop forever, because k won't be incremented.

This one:

      while(k<n && arr[i]+arr[j]>arr[k])
                     k++; 

Stops the loop when either k<n or on the first element for which arr[i]+arr[j]>arr[k] is false.

Consider this example

          k            arr[i]+arr[j]>arr[k]
          1            true
          2            true 
          3            false 
         ...           false
          n

This first counts till k = 2 and then never stops, because k is not incremented anymore. The second loops till k = 2 and stops when k = 3.

PS: (Disclaimer_ I'll tell you my personal view, though it is was it is) Geeksforgeeks is a good place to find poor tutorials, questionable code that often is non-standard but claims to be good for beginners (it isn't) and misleading and often wrong explanations. Mistakes can happen here as well, but then usually someone comments and answers can be fixed (or downvoted when they are too wrong). If you want to learn C++ I suggest you this instead: The Definitive C++ Book Guide and List

463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • Thanks Chris, I realized the same thing after I posted the question that I never considered the possibility of there being no triangle matches in the first match itself. – Saurav Jul 14 '21 at 20:37
  • And this question is an example of the post script. There was a mistake. It was spotted by another user. And it was promptly corrected. The system works. Mostly. – user4581301 Jul 14 '21 at 20:39
  • Although I know the GeeksforGeeks does have questionable code and poor tests, but it has a well-curated list of questions for beginners and my friends also practice from it . Once I gain enough confidence in 2-3 months, I am planning to switch over practice from Leetcode only. – Saurav Jul 14 '21 at 20:40
  • @Saurav well, I could also have added a PS with a rant about online coding challenges ;). Consider that writing tests and using a debugger are essentials. Online coding challenges don't teach you that. Instead they teach you that programming is about writing a piece of code and pass an online judge, which couldn't be more off from reality. – 463035818_is_not_an_ai Jul 14 '21 at 20:45
  • Here's the problem with online judges: They don't consider the quality of the code. Just the output. A program written for a judge only has to run once and under unrealistically ideal circumstances with sanitized input and a known and fixed target configuration. In the real world a program has to run for years, possibly decades, while suffering malicious attacks and idiot users inputting all manner of crap. The computer it ran on will be retired and replaced or intended for a mass market where you have no control over the underlying hardware, firmware, and software . – user4581301 Jul 14 '21 at 20:49
  • @user4581301 lets start small, they don't teach to work on a software project ;). My biggest worry is that I often have the impression that challengers beleive programming is about writing correct code. Writing tests is not considererd at all. Why write a test when the online judge tests my code? When the judge rejects the code they hit a wall and don't know what to do. – 463035818_is_not_an_ai Jul 14 '21 at 20:56
  • Recommendation: If you want to practice programming, find a few open source project that interest you. Read through the bugtracker, support forums, and dev forums to see if you're a good fit socially--the dev team is non-toxic--and they seem open to taking on a sort-of mentoring role with a new programmer. At the end you'll have learned important skills like teamwork, coding standards, and maintenance, and produced something useful to go on the resume. "I wrote and supported the the Defrobbing module for goobermax." Looks more impressive than "I solved a lot of problems on leetcode." – user4581301 Jul 14 '21 at 20:57
  • @user4581301 you are adressing your comments at the wrong user. I have lots of oppurtunities to practice daily :P – 463035818_is_not_an_ai Jul 14 '21 at 20:58
  • I'm not addressing anyone. You just happen to be the recipient of the notifications since you answered the question. – user4581301 Jul 14 '21 at 20:58
  • @user4581301 comments on my answer are implicitly addressed at me – 463035818_is_not_an_ai Jul 14 '21 at 20:59