Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Greedy - Session 2

Caren
July 27, 2018
70

Greedy - Session 2

Caren

July 27, 2018
Tweet

Transcript

  1. Task Scheduler (Continued) Given a char array representing tasks CPU

    need to do. It contains capital letters A to Z where different letters represent different tasks. Tasks could be done without original order. Each task could be done in one interval. For each interval, CPU could finish one task or just be idle. However, there is a non-negative cooling interval n that means between two same tasks, there must be at least n intervals that CPU are doing different tasks or just be idle. You need to return the least number of intervals the CPU will take to finish all the given tasks. Example 1:
 Input: tasks = ["A","A","A","B","B","B"], n = 2
 Output: 8
 Explanation: A -> B -> idle -> A -> B -> idle -> A -> B.
  2. Task Scheduler (Continued) Have a size 26 array coolDownTimeLeft, each

    index represents the cool down time needed for a particular task. Iterate through each task. When we want to try and schedule a task to run, check the array to see if that’s allowed. Update coolDownTimeLeft after every iteration [A, A, B, C] 
 schedule A - > [2, 0, 0 .. 0]
 try to schedule A, can’t. schedule B instead -> [1, 2, 0 .. 0]
 try to schedule A, can’t. schedule C instead -> [0, 1, 2 .. 0]
 try to schedule A again -> [2, 0, 1, 0]
 A -> B -> C -> A
  3. Task Scheduler (Continued) Have a size 26 array coolDownTimeLeft, each

    index represents the cool down time needed for a particular task. Iterate through each task. When we want to try and schedule a task to run, check the array to see if that’s allowed. Update coolDownTimeLeft after every iteration Inefficient because:
 1) We have to remove / mark tasks from the array when it’s scheduled.
 2) We have to repeatedly check if we can run a task
 3) we might end up scheduling frequent tasks in the end, which would cause us to use up unnecessary idle time.
  4. Task Scheduler (Continued) Biggest efficiency problem: 
 If a certain

    type of task has a lot of instances, we want to run those instances as soon as we can
  5. Task Scheduler (Continued) Biggest efficiency problem: 
 If a certain

    type of task has a lot of instances, we want to run those instances as soon as we can IE : 
 If we have A A A A A A A B C D 
 and cool down time = 2
 We don’t want the run sequence to be:
 A B C D A idle idle A idle idle …
 
 We want it to be
 A B C A D idle A idle idle A …
  6. Task Scheduler (Continued) Biggest efficiency problem: 
 If a certain

    type of task has a lot of instances, we want to run those instances as soon as we can IE : 
 If we have A A A A A A A B C D 
 and cool down time = 2
 We don’t want the run sequence to be:
 A B C D A idle idle A idle idle …
 
 We want it to be
 A B C A D idle A idle idle A … What should we do?
  7. Task Scheduler (Continued) Biggest efficiency problem: 
 If a certain

    type of task has a lot of instances, we want to run those instances as soon as we can Sort by most instances first so those can run first
  8. Task Scheduler (Continued) Biggest efficiency problem: 
 If a certain

    type of task has a lot of instances, we want to run those instances as soon as we can Sort by most instances first so those can run first
 BUT as we figured out previously, we can’t just run the most 
 common task first and wait till to end to run the last 
 instances
 IE : A A A A B C -> sorted
 We don’t want to run A B C A A A A
  9. Task Scheduler (Continued) Biggest efficiency problem: 
 If a certain

    type of task has a lot of instances, we want to run those instances as soon as we can Sort by most instances first so those can run first
 BUT as we figured out previously, we can’t just run the most 
 common task first and wait till to end to run the last 
 instances
 So we should be more efficient and sort again after a cool
 down period has passed. IE after we’ve gone through a
 ‘cycle’
  10. Task Scheduler (Continued) Biggest efficiency problem: 
 If a certain

    type of task has a lot of instances, we want to run those instances as soon as we can Sort by most instances first so those can run first
 BUT as we figured out previously, we can’t just run the most 
 common task first and wait till to end to run the last 
 instances
 So we should be more efficient and sort again after a cool
 down period has passed. But also, how do we even sort?? The tasks are just letters?
  11. Task Scheduler (Continued) Biggest efficiency problem: 
 If a certain

    type of task has a lot of instances, we want to run those instances as soon as we can Sort by most instances first so those can run first
 BUT as we figured out previously, we can’t just run the most 
 common task first and wait till to end to run the last 
 instances
 So we should be more efficient and sort again after a cool
 down period has passed. But also, how do we even sort?? The tasks are just letters?
 Our first idea was to put tasks and their instances in a HashMap. But if we put tasks an their instances in an array, we can more easily sort them
  12. Task Scheduler (Continued) Sorting tasks Given input : B B

    B D A B B C A A Z C , cool down time = 2
 3 A’s, 5 B’s, 2 C’s, 1 D, 1 Z 3 5 2 1 0 0 0 0 0 … 1 <- size 26 array (26 letters in alphabet)
 
 

  13. Task Scheduler (Continued) Sorting tasks Given input : B B

    B D A B B C A A Z C , cool down time = 2
 3 A’s, 5 B’s, 2 C’s, 1 D, 1 Z 3 5 2 1 0 0 0 0 0 … 1 <- size 26 array (26 letters in alphabet)
 
 First …. sort tasks by frequency
 5 3 2 1 1 0 0 0 … 
 

  14. Task Scheduler (Continued) Sorting tasks Given input : B B

    B D A B B C A A Z C , cool down time = 2
 3 A’s, 5 B’s, 2 C’s, 1 D, 1 Z 3 5 2 1 0 0 0 0 0 … 1 <- size 26 array (26 letters in alphabet)
 
 First …. sort tasks by frequency
 5 3 2 1 1 0 0 0 …
 
 First iteration (cool down time = 2)
 Do the task that has 5 instances
 Now our array looks like … 4 3 2 1 1 0 0 … 
 

  15. Task Scheduler (Continued) Sorting tasks Given input : B B

    B D A B B C A A Z C , cool down time = 2
 3 A’s, 5 B’s, 2 C’s, 1 D, 1 Z
 
 First iteration (cool down time = 2)
 Do the task at index 0 
 Now our array looks like … 4 3 2 1 1 0 0 … 
 
 Second iteration ( cool down time = 1)
 Do the task in at index 1 
 Now our array looks like … 4 2 2 1 1 0 0 … 
 

  16. Task Scheduler (Continued) Sorting tasks Given input : B B

    B D A B B C A A Z C , cool down time = 2
 3 A’s, 5 B’s, 2 C’s, 1 D, 1 Z
 
 First iteration (cool down time = 2)
 Do the task at index 0 
 Now our array looks like … 4 3 2 1 1 0 0 … 
 
 Second iteration ( cool down time = 1)
 Do the task in at index 1 
 Now our array looks like … 4 2 2 1 1 0 0 … Third iteration (cool down time = 0) 
 Do the task at index 2. Array is now … 4 2 1 1 1 0 0 …
  17. Task Scheduler (Continued) Sorting tasks Given input : B B

    B D A B B C A A Z C , cool down time = 2
 3 A’s, 5 B’s, 2 C’s, 1 D, 1 Z Third iteration (cool down time = 0) 
 Do the task at index 2. Array is now … 4 2 1 1 1 0 0 … Now our cool time down is 0. 
 Let’s move pointer index back to 0 (ie schedule the task at index 0)
 Now our array looks like … 3 2 1 1 1 0 0 

  18. Task Scheduler (Continued) Sorting tasks Given input : B B

    B D A B B C A A Z C , cool down time = 2
 3 A’s, 5 B’s, 2 C’s, 1 D, 1 Z Third iteration (cool down time = 0) 
 Do the task at index 2. Array is now … 4 2 1 1 1 0 0 … Now our cool time down is 0. 
 Let’s move pointer index back to 0 (ie schedule the task at index 0)
 Now our array looks like … 3 2 1 1 1 0 0 Does this always work? Are we missing anything?

  19. Task Scheduler (Continued) Sorting tasks Given input : B B

    B D A B B C A A Z C , cool down time = 2
 3 A’s, 5 B’s, 2 C’s, 1 D, 1 Z Third iteration (cool down time = 0) 
 Do the task at index 2. Array is now … 4 2 1 1 1 0 0 … Now our cool time down is 0. 
 Let’s move pointer index back to 0 (ie schedule the task at index 0)
 Now our array looks like … 3 2 1 1 1 0 0 We have to re-sort every time our cool down time has run down
  20. Task Scheduler (Continued) Sorting tasks We have to resort again

    every time our cool down time has run down 5 3 3 0 … 0 cool down time = 1
 
 First iteration:
 4 3 3 0 <- run first task
 4 2 3 0 <- run second task
 

  21. Task Scheduler (Continued) Sorting tasks We have to resort again

    every time our cool down time has run down 5 3 3 0 … 0 cool down time = 1
 
 First iteration:
 4 3 3 0 
 4 2 3 0
 
 Second iteration after cool down time has run down
 3 2 3 0
 3 1 3 0 (third task is going to get delayed and cause idle time in end) Now our third task is going to get super delayed
  22. Task Scheduler (Continued) Final approach: 1) Store task instances in

    a size 26 array. Each element in the array represents the number of instances the task needs to run

  23. Task Scheduler (Continued) Final approach: 1) Store task instances in

    a size 26 array. Each element in the array represents the number of instances the task needs to run
 
 2) Sort the task in descending order (task with most instances in front)
  24. Task Scheduler (Continued) Final approach: 1) Store task instances in

    a size 26 array. Each element in the array represents the number of instances the task needs to run
 
 2) Sort the task in descending order (task with most instances in front) 3) Iterate through array while cool down time is non-zero
  25. Task Scheduler (Continued) Final approach: 1) Store task instances in

    a size 26 array. Each element in the array represents the number of instances the task needs to run
 
 2) Sort the task in descending order (task with most instances in front) 3) Iterate through array while cool down time is non-zero 4) When cool down time is over, re-sort array
  26. Task Scheduler (Continued) Final approach: 1) Store task instances in

    a size 26 array. Each element in the array represents the number of instances the task needs to run
 
 2) Sort the task in descending order (task with most instances in front) 3) Iterate through array while cool down time is non-zero 4) When cool down time is over, re-sort array 5) We’re finished when the first element is 0 after re-sorting
  27. Task Scheduler (Continued) But wait! Is there an even more

    efficient solution? If we can somehow just figure out how many idle slots are needed … then we can return idleSlotsNeeded + tasks
  28. What to do when stuck? Write out test cases
 sometimes

    in the process of going through test
 cases to get the output a general approach
 will start to appear
  29. What to do when stuck? Write out test cases
 sometimes

    in the process of going through test
 cases to get the output a general approach
 will start to appear Start with the most inefficient solution you can think of that just gets the job done
  30. Mock Interviewing Prep : Understanding the solution (20 minutes) Naive

    solution is usually straight-forward but optimal solution can be hard to understand even when the approach is presented. To fully understand it, take an input and run it through the solution to see how the solution processes the input
  31. Mock Interviewing Try to implement solution in codepad or collabedit

    first Run solution in Leetcode to make sure it passes and is Accepted (ie : No Time Limit Exceeded) Practice communication with your interviewer
  32. Mock Interviewing Try to implement solution in codepad or collabedit

    first Run solution in Leetcode to make sure it passes and is Accepted (ie : No Time Limit Exceeded) Practice communication with your interviewer Try to time constrain to 35 minutes a problem
 still do Understanding, Matching, Prototype / Pseudocoding, Implement, Recheck, Evaluate!
 Don’t be tempted to start coding too early Mentors will be popping in (me and Jing)
  33. Greedy : Summarized At every step, we do what’s best

    for us How do we know we should go with an approach like this? 
 can the problem be broken down into small sub- problems?
 can the smaller sub-problems and that their optimal solution be part of the optimal solution of the whole problem?