Given a non-negative integer num
, represent it as the sum of num = 2i + 2j + 2k + ...
, where i >= 0
, j >= 0
, k >= 0
, ... You may choose the bits i
, j
, k
, ... any number of times. Return an array of integers representing these bits.
Example 1:
Input: num = 10
Output: [2,8]
Explanation:
num = 10 = 2 + 8 = 21 + 23
Example 2:
Input: num = 23
Output: [1,2,4,16]
Explanation:
num = 23 = 1 + 2 + 4 + 16 = 20 + 21 + 22 + 24
Constraints:
1 <= num <= 105
When you get asked this question in a real-life environment, it will often be ambiguous (especially at FAANG). Make sure to ask these questions in that case:
The goal is to find the smallest set of special numbers that can add up to a given target number. We can try every possible combination of these special numbers to see if any of them exactly match the target.
Here's how the algorithm would work step-by-step:
def encode_number_brute_force(special_numbers, target):
# Iterate through different lengths of combinations
for combination_length in range(1, len(special_numbers) + 1):
# Generate all possible combinations of the specified length
combinations = get_combinations(special_numbers, combination_length)
# Iterate through each combination to check for a match
for combination in combinations:
if sum(combination) == target:
return combination
return []
def get_combinations(special_numbers, combination_length):
combinations_list = []
get_combinations_recursive(special_numbers, combination_length, 0, [], combinations_list)
return combinations_list
def get_combinations_recursive(special_numbers, combination_length, start_index, current_combination, combinations_list):
if combination_length == 0:
# If combination length is 0, add current comb to list
combinations_list.append(current_combination[:])
return
# Ensure that the index does not go out of bounds.
for index in range(start_index, len(special_numbers)):
current_combination.append(special_numbers[index])
get_combinations_recursive(special_numbers, combination_length - 1, index + 1, current_combination, combinations_list)
# Backtrack: remove the last element to try other combinations
current_combination.pop()
The best way to encode the number is to think of it as a special kind of pattern. We want to find the smallest set of special numbers that add up to the number, using only numbers that are one less than a power of two.
Here's how the algorithm would work step-by-step:
def encode(number):
encoded_list = []
while number > 0:
power_of_two = 0
# Find the highest power of two minus 1, less than the number
while (1 << (power_of_two + 1)) - 1 <= number:
power_of_two += 1
encoded_list.append(power_of_two)
# Subtract the largest possible 'special' number
number -= (1 << power_of_two) - 1
return encoded_list
Case | How to Handle |
---|---|
Input number is zero | Handle zero as a valid input, and return the corresponding substring from the infinite binary string S based on its index. |
Input number is negative | Define whether negative numbers are allowed; if not, throw an IllegalArgumentException or return an error string; if allowed, handle negative indices appropriately by perhaps shifting them to a positive range or defining them as invalid. |
Input number is one | Input '1' should return the first substring which is '1'. |
Large input number exceeding integer limits in substring generation | Use long data types to avoid overflow issues when calculating the length of the substring and its index within the S string. |
Memory constraints when generating very long prefixes of S | Generate the required portion of S on demand instead of pre-calculating the entire infinite string, to manage memory efficiently. |
No valid solution exists due to Integer.MAX_VALUE limits | If the input number is greater than the largest calculable index given memory/integer limits, define that an error string be returned. |
Correctness of substring calculation | Thoroughly test the substring indexing and extraction logic to ensure it consistently returns the i-th substring of S. |
Performance bottlenecks when repeatedly calculating substrings | Employ memoization to cache already calculated substrings, avoiding redundant calculations for frequently requested indices. |