Two solutions - O(logB) and O(1)
python\nclass Solution:\n    def __init__(self, N: int, blacklist: List[int]):\n        intervals, s, count, isize = [], 0, 0, 0\n        for b in sorted(blackl
```python\nclass Solution:\n    def __init__(self, N: int, blacklist: List[int]):\n        intervals, s, count, isize = [], 0, 0, 0\n        for b in sorted(blacklist) + [N]:\n            if s != b:\n                intervals.append((count, count + b - s - 1, s, b - 1))\n                count += b - s\n                isize += 1\n            s = b + 1\n        self.intervals = intervals\n        self.isize = isize\n        self.count = count\n\n    def pick(self) -> int:\n        l, r, picked = 0, self.isize - 1, random.randrange(0, self.count)\n        while l <= r:\n            m = l + ((r - l) // 2)\n            ls, le, ps, pe = self.intervals[m]\n            if picked < ls:\n                r = m - 1\n            elif picked > le:\n                l = m + 1\n            else:\n                return ps + (picked - ls)\n```\n\n----\n\n```python\nclass Solution:\n    def __init__(self, N: int, blacklist: List[int]):\n        self.remapped = {}\n        self.count = N - len(blacklist)\n        i, blocked = self.count, set(blacklist)\n        for b in blacklist:\n            if b < self.count:\n                while i in blocked:\n                    i += 1\n                self.remapped[b] = i\n                i += 1\n\n    def pick(self) -> int:\n        r = random.randrange(0, self.count)\n        return self.remapped.get(r, r)\n```
[]