Skip to content

Latest commit

 

History

History
73 lines (39 loc) · 1.45 KB

File metadata and controls

73 lines (39 loc) · 1.45 KB

Problem

There are N prisoners standing at a circle, waiting to be executed. Executions start with the Kth person, and goes on clockwise, removing every successive Kth person until there's no one left.

Given N and K, determine where the prisoner should stand in order to be the last survivor.

For example, if N = 5, and k = 2, order of executions will be [2, 4, 1, 5, 3] so return 3.

def last_executed(n, k):
    # create list of size n
    prisoners = [i for i in range(1, n + 1)]
    # use zero-based index
    i = k - 1
    
    # loop through cyclicly over prisoners list, until last visited prisoner
    while (n > 1):
        prisoners.pop(i)
        i = (i + k - 1) % len(prisoners)
        n -= 1
    return prisoners[0]
last_executed(5, 2)
3

Since popping from a random index in a list is O(N) and we are doing this N times, the solution runs in O(N^2).

We can improve the efficiency by using a double-ended queue.

We will rotate our list in O(k) time by using a deque, so that we can pop elements at the end. This allows us to eliminate each prisoner in O(k) time, thereby making the whole solution run in O(k * N)

from collections import deque

def last_one_standing(n, k):
    prisoners = deque(range(1, n + 1))
    
    while (n > 1):
        prisoners.rotate(-k)
        prisoners.pop()
        
        n -= 1
        
    return prisoners[0]
last_one_standing(5, 2)
3