Sort Integers by The Power Value

medium memoization sorting collatz

Problem

The power of an integer x is the number of steps to reach 1 using: if x is even, x = x / 2; if x is odd, x = 3·x + 1. Given lo, hi, and k, sort every integer in [lo, hi] by ascending power value (ties broken by ascending value) and return the k-th element.

Inputlo = 12, hi = 15, k = 2
Output13
Powers: 12→9, 13→9, 14→17, 15→17. Sorted by (power, value): [12, 13, 14, 15]. The 2nd element is 13.
Inputlo = 7, hi = 11, k = 4
Output7
Powers: 7→16, 8→3, 9→19, 10→6, 11→14. Sorted: [8, 10, 11, 7, 9]. The 4th element is 7.

def getKth(lo, hi, k):
    memo = {1: 0}
    def power(x):
        if x in memo:
            return memo[x]
        nxt = x // 2 if x % 2 == 0 else 3 * x + 1
        memo[x] = 1 + power(nxt)
        return memo[x]
    nums = list(range(lo, hi + 1))
    nums.sort(key=lambda x: (power(x), x))
    return nums[k - 1]
function getKth(lo, hi, k) {
  const memo = new Map([[1, 0]]);
  function power(x) {
    if (memo.has(x)) return memo.get(x);
    const nxt = x % 2 === 0 ? x / 2 : 3 * x + 1;
    memo.set(x, 1 + power(nxt));
    return memo.get(x);
  }
  const nums = [];
  for (let x = lo; x <= hi; x++) nums.push(x);
  nums.sort((a, b) => power(a) - power(b) || a - b);
  return nums[k - 1];
}
Map<Integer, Integer> memo = new HashMap<>();
int power(int x) {
    if (x == 1) return 0;
    if (memo.containsKey(x)) return memo.get(x);
    long nxt = (x % 2 == 0) ? x / 2 : 3L * x + 1;
    int p = 1 + power((int) nxt);
    memo.put(x, p);
    return p;
}
int getKth(int lo, int hi, int k) {
    List<Integer> nums = new ArrayList<>();
    for (int x = lo; x <= hi; x++) nums.add(x);
    nums.sort((a, b) -> power(a) != power(b) ? power(a) - power(b) : a - b);
    return nums.get(k - 1);
}
unordered_map<int, int> memo;
int power(int x) {
    if (x == 1) return 0;
    if (memo.count(x)) return memo[x];
    long long nxt = (x % 2 == 0) ? x / 2 : 3LL * x + 1;
    int p = 1 + power((int) nxt);
    memo[x] = p;
    return p;
}
int getKth(int lo, int hi, int k) {
    vector<int> nums;
    for (int x = lo; x <= hi; x++) nums.push_back(x);
    sort(nums.begin(), nums.end(), [&](int a, int b) {
        return power(a) != power(b) ? power(a) < power(b) : a < b;
    });
    return nums[k - 1];
}
Time: O(n · log n) Space: O(n + maxChain)