Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

While we drop the constant in big O notation, does it matter in real-life situations?

Tags:

While I understand that big O notation simply describes the growth rate of an algorithm, I'm uncertain if there is any difference in efficiency in real life between the following O(n) algorithms.

To print the value of a node in a linked list k places from the end of the list.

Given a node:

/* Link list node */
struct node
{
  int data;
  struct node* next;
};

Solution 1 O(n)

This solution iterates over the list twice, once to find the length of the list, and the second time to get to the end of the list - N.

void printNthFromLast(struct node* head, int n)
{
    int len = 0, i;
    struct node *temp = head;


    // 1) Count the number of nodes in Linked List
    while (temp != NULL)
    {
        temp = temp->next;
        len++;
    }

    // Check if value of n is not more than length of the linked list
    if (len < n)
      return;

    temp = head;

    // 2) Get the (n-len+1)th node from the begining
    for (i = 1; i < len-n+1; i++)
    {
       temp = temp->next;
    }
    printf ("%d", temp->data);

    return;
}

Solution 2 O(n)

This solution only iterates over the list once. The ref_ptr pointer leads, and a second pointer (main_ptr) follows it k places behind. When ref_ptr reaches the end of the list, main_ptr should be pointing at the correct node (k places from the end of the list).

void printNthFromLast(struct node *head, int n)
{
  struct node *main_ptr = head;
  struct node *ref_ptr = head;

  int count = 0;
  if(head != NULL)
  {
    while( count < n )
     {
        if(ref_ptr == NULL)
        {
           return;
        }
        ref_ptr = ref_ptr->next;
        count++;
     }

     while(ref_ptr != NULL)
     {
        main_ptr = main_ptr->next;
        ref_ptr  = ref_ptr->next;
     }
  }
}

The question is: Even though both solutions are O(n) while leaving big O notation aside, is the second solution more efficient that the first for a very long list as it only iterates over the list once?

like image 334
John tarmac Avatar asked Feb 04 '16 23:02

John tarmac


People also ask

Why do we drop constants in Big O notation?

The quote merely means that because the system where the program will run will introduce an unknown constant factor in the run time, it's more-or-less pointless to worry about constant factors at all. But this is just when you're analyzing algorithms.

Does Big O notation ignore constants?

Big O notation ignores constants. For example, if you have a function that has a running time of 5n, we say that this function runs on the order of the big O of N. This is because as N gets large, the 5 no longer matters.

Why do we ignore constant in time complexity?

The reason that we don't use constants with big O notation is because, theoretically they don't matter much. What we are calculating with time-complexity is the speed at which something will grow, having a constant on there will be completely irrelevant when a large enough input is used.

What Big O notation takes constant of time?

O(1) — Constant Time Constant time algorithms will always take same amount of time to be executed. The execution time of these algorithm is independent of the size of the input. A good example of O(1) time is accessing a value with an array index. Other examples include: push() and pop() operations on an array.

Why do we use Big O notation for running time?

But once we set aside constant factors, we are able to clearly describe an algorithm's running time. Big O notation gives us a robust and useful description of how long an algorithm takes, while abstracting away from the technical features of its implementation and execution.

Is big O without constant enough for algorithm analysis?

Big O without constant is enough for algorithm analysis. First, the actual time does not only depend how many instructions but also the time for each instruction, which is closely connected to the platform where the code runs. It is more than theory analysis.

Does Big-O notation care about constants?

The answer to that second question is "no," while the answer to that first question is "absolutely!" Big-O notation doesn't care about constants because big-O notation only describes the long-term growth rate of functions, rather than their absolute magnitudes.

Is Big-O notation relevant to an asymptotic analysis?

However, those constants are absolutely significant; they just aren't relevant to an asymptotic analysis. Hope this helps! Show activity on this post. Big-O notation only describes the growth rate of algorithms in terms of mathematical function, rather than the actual running time of algorithms on some machine.


2 Answers

Yes. In the specific example where the same work occurs, a single loop is likely to be more efficient than looping over a set of data twice. But the idea of O(2n) ~ O(n) is that 2 ns vs 1 ns may not really matter. Big O works better to show how a piece of code might scale, e.g. if you made the loop O(n^2) then the difference of O(n) vs O(2n) is much less than O(n) vs O(n^2).

If your linked list contains terrabytes of data, then it might be worth reducing to the single loop iteration. A big O metric, in this case may not be sufficient to describe your worst case; you would be better off timing the code and considering the needs of the application.

Another example is in embedded software, where 1 ms vs 2 ms could be the difference between a 500 Hz and a 1 kHz control loop.

The lesson learned is that it depends on the application.

like image 150
Fantastic Mr Fox Avatar answered Sep 30 '22 17:09

Fantastic Mr Fox


The constant only matters if the order is the same, and the operations are comparable in complexity. If they aren't of the same order, then the one with the higher order is guaranteed to take longer once you have a large enough n. Sometimes n must be larger than your typical data set, and the only way to pick the most efficient algorithm is to benchmark them.

like image 41
Mark Ransom Avatar answered Sep 30 '22 17:09

Mark Ransom