Sort Integers by The Power Value solution and explanation
9 more videos on this problem
17. Sort Integers by The Power Value | Dynamic Programming Series | LeetCode Medium 1387AceCoder Academy · 16:44 · 2K views
Sort Integers by The Power Value (Leetcode 1387)Coding Interviews · 7:01 · 2K views
LeetCode 1387 - Sort Integers by The Power ValueLight Of Truth · 18:22 · 1K views
1387.Sort Integers by The Power|leetcode dp series|leetcodeDp wale · 9:24 · 742 views
Leetcode 1387 Sort Integers by The Power ValueMath Geeks · 3:37 · 304 views
LeetCode 1387 | Sort Integers by The Power Value | PriorityQueue | HashMap | JavaSleepy Cracker · 9:54 · 247 views
小飞羊 LeetCode 1387. Sort Integers by The Power Value - 套路得人薪C++Willy小飞羊 DJ · 5:37 · 240 views
LeetCode 1387 SortIntegers ByPowerValuekomal seelam · 2:33 · 111 views
1387. Sort Integers by The Power ValueLeonardo Vo · 34:00 · 3 views
LeetCode 1387: Sort Integers by The Power ValueAlitaCode · 30:01 · 1 view
The problem
The power of an integer x is defined as the number of steps needed to transform x into 1 using the following steps:
- if
xis even thenx = x / 2 - if
xis odd thenx = 3 * x + 1
For example, the power of x = 3 is 7 because 3 needs 7 steps to become 1 (3 --> 10 --> 5 --> 16 --> 8 --> 4 --> 2 --> 1).
Given three integers lo, hi and k. The task is to sort all integers in the interval [lo, hi] by the power value in ascending order, if two or more integers have the same power value sort them by ascending order.
Return the kth integer in the range [lo, hi] sorted by the power value.
Notice that for any integer x (lo <= x <= hi) it is guaranteed that x will transform into 1 using these steps and that the power of x is will fit in a 32-bit signed integer.
Example 1:
Input: lo = 12, hi = 15, k = 2 Output: 13 Explanation: The power of 12 is 9 (12 --> 6 --> 3 --> 10 --> 5 --> 16 --> 8 --> 4 --> 2 --> 1) The power of 13 is 9 The power of 14 is 17 The power of 15 is 17 The interval sorted by the power value [12,13,14,15]. For k = 2 answer is the second element which is 13. Notice that 12 and 13 have the same power value and we sorted them in ascending order. Same for 14 and 15.
Example 2:
Input: lo = 7, hi = 11, k = 4 Output: 7 Explanation: The power array corresponding to the interval [7, 8, 9, 10, 11] is [16, 3, 19, 6, 14]. The interval sorted by power is [8, 10, 11, 7, 9]. The fourth number in the sorted array is 7.
Constraints:
1 <= lo <= hi <= 10001 <= k <= hi - lo + 1
Approach overview
Problem Overview: Given integers lo, hi, and k, compute the power value for every number in the range. The power value is the number of steps required to reduce a number to 1 using the Collatz rules: if even divide by 2, if odd multiply by 3 and add 1. After computing power values, sort the integers by power (and by value if tied) and return the k-th element.
Approach 1: Direct Power Calculation and Sorting (Time: O(n log n * k), Space: O(n))
Iterate through every integer from lo to hi and compute its power value by repeatedly applying the Collatz transformation until reaching 1. Store pairs like (power, value) in a list. Once all values are processed, sort the list by power first and by integer value as a tiebreaker using standard sorting. Finally return the value at index k - 1. This approach is straightforward and works well for the given constraints, but many power calculations repeat the same intermediate numbers.
Approach 2: Memoization for Power Calculation (Time: O(n log n), Space: O(n))
The Collatz sequence frequently revisits numbers whose power values were already computed. Use memoization to cache results in a hash map where memo[x] stores the power of x. When computing the power for a new number, check the cache before continuing the sequence. If an intermediate value already exists in the map, reuse it and stop the traversal early. This reduces repeated work significantly. After computing powers for all numbers, sort the (power, value) pairs using the same rule as before. The memo table effectively turns repeated sequence work into constant-time lookups and behaves like a lightweight dynamic programming cache.
Recommended for interviews: The memoization approach is what most interviewers expect. The direct calculation demonstrates understanding of the Collatz process and sorting mechanics, but caching intermediate results shows awareness of repeated subproblems and optimization using dynamic programming techniques.
Approach 1: Direct Power Calculation and Sorting
This approach involves calculating the power value of each integer in the range [lo, hi] by simulating the steps to transform the number into 1. Once the power values are calculated, the list of integers is sorted by their power value (breaking ties using their magnitude). Finally, the k-th integer is retrieved.
def calculate_power(x):
steps = 0
while x != 1:
if x % 2 == 0:
x //= 2
else:
x = 3 * x + 1
steps += 1
return steps
def get_kth(lo, hi, k):
power_values = [(i, calculate_power(i)) for i in range(lo, hi+1)]
power_values.sort(key=lambda x: (x[1], x[0]))
return power_values[k-1][0]
# Example usage:
print(get_kth(12, 15, 2)) # Output: 13
print(get_kth(7, 11, 4)) # Output: 7function calculatePower(x) {
let steps = 0;
while (x !== 1) {
if (x % 2 === 0) x /= 2;
else x = 3 * x + 1;
steps++;
}
return steps;
}
function getKth(lo, hi, k) {
const powerValues = [];
for (let i = lo; i <= hi; i++) {
powerValues.push({ number: i, power: calculatePower(i) });
}
powerValues.sort((a, b) => a.power === b.power ? a.number - b.number : a.power - b.power);
return powerValues[k - 1].number;
}
// Example usage:
console.log(getKth(12, 15, 2)); // Output: 13
console.log(getKth(7, 11, 4)); // Output: 7using System;
using System.Collections.Generic;
public class Solution {
private static int CalculatePower(int x) {
int steps = 0;
while (x != 1) {
if (x % 2 == 0) x /= 2;
else x = 3 * x + 1;
steps++;
}
return steps;
}
public int GetKth(int lo, int hi, int k) {
List<(int Number, int Power)> powerList = new List<(int, int)>();
for (int i = lo; i <= hi; i++) {
int powerValue = CalculatePower(i);
powerList.Add((i, powerValue));
}
powerList.Sort((a, b) => a.Power == b.Power ? a.Number.CompareTo(b.Number) : a.Power.CompareTo(b.Power));
return powerList[k - 1].Number;
}
}
// Example usage:
// Solution sol = new Solution();
// Console.WriteLine(sol.GetKth(12, 15, 2)); // Output: 13
// Console.WriteLine(sol.GetKth(7, 11, 4)); // Output: 7The function calculate_power(x) computes the power value of x by iterating until x becomes 1. For each integer in the range [lo, hi], the power value is calculated and stored in a list. This list is then sorted by power value and magnitude. The k-th integer is returned from this sorted list.
Time Complexity: O(n * m), where n is the number of integers between lo and hi, and m is the average number of steps to reduce an integer to 1.
Space Complexity: O(n) for storing the power values.
Approach 2: Memoization for Power Calculation
This approach improves on the first by using memoization to store previously calculated power values, which reduces redundant calculations and enhances performance when calculating power for subsequent numbers.
import java.util.*;
class Solution {
Map<Integer, Integer> powerCache = new HashMap<>();
private int calculatePower(int x) {
if (x == 1) return 0;
if (powerCache.containsKey(x)) return powerCache.get(x);
int next = (x % 2 == 0) ? x / 2 : 3 * x + 1;
int power = 1 + calculatePower(next);
powerCache.put(x, power);
return power;
}
public int getKth(int lo, int hi, int k) {
List<int[]> powerList = new ArrayList<>();
for (int i = lo; i <= hi; i++) {
int powerValue = calculatePower(i);
powerList.add(new int[]{i, powerValue});
}
Collections.sort(powerList, (a, b) -> a[1] == b[1] ? a[0] - b[0] : a[1] - b[1]);
return powerList.get(k - 1)[0];
}
}
// Example usage:
// Solution sol = new Solution();
// System.out.println(sol.getKth(12, 15, 2)); // Output: 13
// System.out.println(sol.getKth(7, 11, 4)); // Output: 7#include <iostream>
#include <vector>
#include <unordered_map>
#include <algorithm>
std::unordered_map<int, int> powerCache;
int calculatePower(int x) {
if (x == 1) return 0;
if (powerCache.count(x)) return powerCache[x];
int next = (x % 2 == 0) ? x / 2 : 3 * x + 1;
int power = 1 + calculatePower(next);
powerCache[x] = power;
return power;
}
int getKth(int lo, int hi, int k) {
std::vector<std::pair<int, int>> powerList;
for (int i = lo; i <= hi; ++i) {
int powerValue = calculatePower(i);
powerList.emplace_back(i, powerValue);
}
std::sort(powerList.begin(), powerList.end(), [](auto& a, auto& b) {
return a.second == b.second ? a.first < b.first : a.second < b.second;
});
return powerList[k - 1].first;
}
int main() {
std::cout << getKth(12, 15, 2) << std::endl; // Output: 13
std::cout << getKth(7, 11, 4) << std::endl; // Output: 7
return 0;
}The calculatePower method utilizes memoization by storing calculated power values in a hashmap to avoid recalculating them. The result is a more efficient computation for subsequent numbers. Power values for the range [lo, hi] are computed, stored, and sorted as before, allowing retrieval of the k-th element.
Time Complexity: O(n log n) for sorting, as calculations are faster with memoization.
Space Complexity: O(n) for the power cache and list storage.
Approach 3: Custom Sorting
First, we define a function f(x), which represents the number of steps required to transform the number x into 1, i.e., the power value of the number x.
Then, we sort all the numbers in the interval [lo, hi] in ascending order based on their power values. If the power values are the same, we sort them in ascending order based on the numbers themselves.
Finally, we return the k-th number in the sorted list.
The time complexity is O(n times log n times M), and the space complexity is O(n). Here, n is the number of numbers in the interval [lo, hi], and M is the maximum value of f(x), which is at most 178 in this problem.
function getKth(lo: number, hi: number, k: number): number {
const f = (x: number): number => {
let ans = 0;
for (; x !== 1; ++ans) {
if (x % 2 === 0) {
x >>= 1;
} else {
x = x * 3 + 1;
}
}
return ans;
};
const nums = new Array(hi - lo + 1).fill(0).map((_, i) => i + lo);
nums.sort((a, b) => {
const fa = f(a),
fb = f(b);
return fa === fb ? a - b : fa - fb;
});
return nums[k - 1];
}func getKth(lo int, hi int, k int) int {
f := func(x int) (ans int) {
for ; x != 1; ans++ {
if x%2 == 0 {
x /= 2
} else {
x = 3*x + 1
}
}
return
}
nums := make([]int, hi-lo+1)
for i := range nums {
nums[i] = lo + i
}
sort.Slice(nums, func(i, j int) bool {
fx, fy := f(nums[i]), f(nums[j])
if fx != fy {
return fx < fy
}
return nums[i] < nums[j]
})
return nums[k-1]
}impl Solution {
pub fn get_kth(lo: i32, hi: i32, k: i32) -> i32 {
let f = |mut x: i32| -> i32 {
let mut ans = 0;
while x != 1 {
if x % 2 == 0 {
x /= 2;
} else {
x = 3 * x + 1;
}
ans += 1;
}
ans
};
let mut nums: Vec<i32> = (lo..=hi).collect();
nums.sort_by(|&x, &y| f(x).cmp(&f(y)));
nums[(k - 1) as usize]
}
}Complexity comparison
| Approach | Complexity |
|---|---|
| Direct Power Calculation and Sorting | Time Complexity: O(n * m), where n is the number of integers between lo and hi, and m is the average number of steps to reduce an integer to 1. |
| Memoization for Power Calculation | Time Complexity: O(n log n) for sorting, as calculations are faster with memoization. |
| Custom Sorting | – |
Complexity analysis
| Approach | Time | Space | When to Use |
|---|---|---|---|
| Direct Power Calculation and Sorting | O(n log n * k) | O(n) | Good baseline solution when implementing Collatz steps directly without optimization. |
| Memoization for Power Calculation | O(n log n) | O(n) | Best choice when many sequences share intermediate values; avoids recomputation. |
Frequently asked questions
Is Sort Integers by The Power Value easy or hard?
Sort Integers by The Power Value is rated Medium difficulty. The main challenge is recognizing that many Collatz sequences overlap and can be optimized using memoization instead of recomputing every step for every number.
Sort Integers by The Power Value Python/Java solution
In Python or Java, iterate from lo to hi, compute each number's power using a loop that follows the Collatz rules, and cache results in a dictionary or HashMap. Store (power, value) pairs in a list, sort them, and return the element at index k-1.
How to solve Sort Integers by The Power Value in O(n)?
Pure O(n) is difficult because the problem requires sorting by power value. The closest practical solution is computing powers with memoization and then sorting, which results in O(n log n) time. Memoization reduces repeated Collatz calculations and keeps the preprocessing step close to linear.
What is the best approach for Sort Integers by The Power Value?
Memoization with sorting is the most efficient approach. Compute the Collatz power value for each integer while caching intermediate results in a hash map. This avoids recalculating power values for numbers that appear multiple times in sequences. After computing powers, sort the integers by (power, value) and return the k-th element.
Is Sort Integers by The Power Value asked at Google/Amazon/Meta?
This problem is tagged as a medium-level algorithm question and appears in coding interview preparation lists for companies like Amazon and Google. It tests knowledge of sorting, memoization, and recognizing repeated subproblems in sequences like the Collatz transformation.
What data structure is used in Sort Integers by The Power Value?
A hash map (dictionary) is commonly used to store memoized power values for intermediate numbers in the Collatz sequence. An array or list stores pairs of (power, integer) which are then sorted using a standard sorting algorithm.
What is the time complexity of Sort Integers by The Power Value?
The optimized solution runs in O(n log n) time where n = hi - lo + 1. Sorting the numbers dominates the runtime, while memoization ensures each power value is computed only once. Space complexity is O(n) for storing power values and the memoization cache.
