Easy interview question got harder: given numbers 1..100, find the missing number(s) given exactly k are missing

前端 未结 30 1220
时光说笑
时光说笑 2020-11-22 07:02

I had an interesting job interview experience a while back. The question started really easy:

Q1: We have a bag containing numbers

30条回答
  •  北海茫月
    2020-11-22 08:02

    The problem with solutions based on sums of numbers is they don't take into account the cost of storing and working with numbers with large exponents... in practice, for it to work for very large n, a big numbers library would be used. We can analyse the space utilisation for these algorithms.

    We can analyse the time and space complexity of sdcvvc and Dimitris Andreou's algorithms.

    Storage:

    l_j = ceil (log_2 (sum_{i=1}^n i^j))
    l_j > log_2 n^j  (assuming n >= 0, k >= 0)
    l_j > j log_2 n \in \Omega(j log n)
    
    l_j < log_2 ((sum_{i=1}^n i)^j) + 1
    l_j < j log_2 (n) + j log_2 (n + 1) - j log_2 (2) + 1
    l_j < j log_2 n + j + c \in O(j log n)`
    

    So l_j \in \Theta(j log n)

    Total storage used: \sum_{j=1}^k l_j \in \Theta(k^2 log n)

    Space used: assuming that computing a^j takes ceil(log_2 j) time, total time:

    t = k ceil(\sum_i=1^n log_2 (i)) = k ceil(log_2 (\prod_i=1^n (i)))
    t > k log_2 (n^n + O(n^(n-1)))
    t > k log_2 (n^n) = kn log_2 (n)  \in \Omega(kn log n)
    t < k log_2 (\prod_i=1^n i^i) + 1
    t < kn log_2 (n) + 1 \in O(kn log n)
    

    Total time used: \Theta(kn log n)

    If this time and space is satisfactory, you can use a simple recursive algorithm. Let b!i be the ith entry in the bag, n the number of numbers before removals, and k the number of removals. In Haskell syntax...

    let
      -- O(1)
      isInRange low high v = (v >= low) && (v <= high)
      -- O(n - k)
      countInRange low high = sum $ map (fromEnum . isInRange low high . (!)b) [1..(n-k)]
      findMissing l low high krange
        -- O(1) if there is nothing to find.
        | krange=0 = l
        -- O(1) if there is only one possibility.
        | low=high = low:l
        -- Otherwise total of O(knlog(n)) time
        | otherwise =
           let
             mid = (low + high) `div` 2
             klow = countInRange low mid
             khigh = krange - klow
           in
             findMissing (findMissing low mid klow) (mid + 1) high khigh
    in
      findMising 1 (n - k) k
    

    Storage used: O(k) for list, O(log(n)) for stack: O(k + log(n)) This algorithm is more intuitive, has the same time complexity, and uses less space.

提交回复
热议问题