Algorithmic Complexity

Review

Goal:

To get you more comfortable with time complexity so that you can confidently answer questions from SA02

Plan

  • Overview of types of complexity
  • Strategy for determining complexity
  • Examples

Types of Complexity

Imagine you have an electronic copy of a directory of all past and present Hack Reactor students (in alphabetical order, one student per page, with name, picture, current job, and cohort) and you want to mail a directory to each student. 

 

Problem size: # of students 

Major Types of Complexity

Constant: Increasing the problem size does not change the number of operations 

 

O(1)
O(1)

Example: Given a directory and the page a student is on, determine the cohort of the student

 

Major Types of Complexity

Linear: Increasing the problem size by one adds the same number of operations each time

O(n)
O(n)

Example: Given a directory, make a list of all of the alumni from

HR 25 

 

Major Types of Complexity

Quadratic: Increasing the problem size by one adds a number of operations proportional to the problem size

 

O(n^2)
O(n2)

Example: You printed all the copies, but accidentally forgot the first letter of everyone's name. Go through and correct each student in each copy of the directory with a sharpie.

 

Major Types of Complexity

Exponential: Increasing the problem size by one adds a number of operations proportional to some constant raised to the power of the problem size

 

O(c^n)
O(cn)

Example: You are sending a gift card to either blue bottle or chai bar to each student with the directory. You want to make a list of all the possible ways in which you can give out the gift cards.

 

Major Types of Complexity

Logarithmic: Increasing the problem size by one adds a number of operations inversely proportional to problem size (or doubling problem size adds the same number of operations each time)

O(log_cn)
O(logcn)

Example: You are looking for a specific student and you know their name - you find them by starting in the middle and seeing if it is to the left or the right, then repeating process with that section of pages.

 

O(1)
O(1)
O(n)
O(n)
O(log_2n)
O(log2n)
O(n^2)
O(n2)
O(c^n)
O(cn)

Determining Complexity

0. Don't freak out! 

1. Determine what variable(s) represent problem size (this is n)

2. Write number of operations in terms of n

3. Find leading term and drop coefficients

 

Alternative: If you have difficulty writing operations in terms of n, you can try a few different(-ly sized) inputs and make a table, then look for a trend 

 

What about?

1. Function calls inside of functions that add complexity

2. Recursive functions 

Example 1: contains


function contains(array, target){
  return array.indexOf(target) > -1;
}

Problem size: length of array

O(n)
O(n)
//For each element in the array
    //if element equals value
        //save index
//return index if found, or -1 if not

Example 2: gcf

function gcf(num1, num2){
  if(num1 > num2){
    var temp = num1;
    num1 = num2;
    num2 = num1;
  }
  for(var i = num1; i > 1; i--){
    if(num1 % i === 0 && num2 % i === 0){
      return i;
    }
  }
  return 1;
}

Problem size: smaller number of num1, num2

Worst case, must iterate through every integer from num1 to 1

O(n)
O(n)
//if num1 > num2
    //swap num 1 and num 2




//for each integer starting at num1
    //if both num1 and num 2 are evenly 
    //divisible by integer
        //return integer


//return 1

Example 3: countChar

function countChar(string){
  var counts = {};
  var currChar, currCharCount;
  for(var i = 0; i < string.length; i++){
    currChar = string[i];
    currCharCount = 1;
    for(var j = i+1; j < string.length; j++){
      if(currChar === string[j]){
        currCharCount++;
      }
    }
    if(!counts.hasOwnProperty(currChar)){
      counts[currChar] = currCharCount;
    }
  }
  return counts;
}

Problem size: string length

(2 + n-1) + (2 + n-2) + (2 + n-3) + ... + (2 + n - n)

2n + (n-1 + n-2 + n-3 + ... n-n)

2n + (sum of all numbers from n-1 to zero)

 

 

2n +\frac{ (n-1)(n)}{2} = 2n+\frac{n^2}{2} - \frac{n}{2}=\frac{n^2}{2} - 1.5n
2n+2(n1)(n)=2n+2n22n=2n21.5n
O(n^2)
O(n2)
//for each char in string
    //set current character to char
    //start count at 1
    //for each char in rest of the string
        //if char equals current character
            //add one to count


    //if we didn't already save curr char
        //save a value for current character


//return storage of counts

Example 4: factorial

function factorial(x){
  if(x <= 1){
    return 1;
  } else {
    return x*factorial(x-1);
  }
}

Problem size: value of x 

O(n)
O(n)

 

Example: factorial(5)

5*factorial(4)

5*4*factorial(3)

5*4*3*factorial(2)

5*4*3*2*factorial(1)

5*4*3*2*1 

Example 5: tournament

function tournament(players){
  var results;
  if(players.length < 3){
    return players[0];
  } else{
    results = fightToDeath(players);
    numWinners = Math.floor(players.length/3);
    numByes = players.length%3;
    numSurvivors = numWinners + numByes;
    return tournament(results.slice(0,numSurvivors);
  }
}

Assume: fightToDeath() is constant time, and returns players in an order where all surviving players come before non-surviving players in the array.

O(log_3(n))
O(log3(n))

 

Each time, we divide the number of players remaining by 3

Problem size: number of players

//if we have less than three players
    //pick the first as winner

//else if we have more than three players
    //make fight to the death in groups of 3
    //determine # winners (n/3)
    //determine # byes
    //run the tournament again with survivors

Time Complexity Review

By Beth Johnson

Time Complexity Review

  • 819