Design an algorithm to randomly shuffle an integer array such that all permutations are equally likely. You need to implement a Solution
class with the following methods:
Solution(int[] nums)
: Initializes the object with the input array nums
.int[] reset()
: Resets the array to its original configuration and returns it.int[] shuffle()
: Returns a randomly shuffled array.Constraints:
1 <= nums.length <= 50
-10^6 <= nums[i] <= 10^6
nums
are unique.10^4
calls will be made to reset
and shuffle
.Example:
Input:
["Solution", "shuffle", "reset", "shuffle"]
[[[1, 2, 3]], [], [], []]
Output:
[null, [3, 1, 2], [1, 2, 3], [1, 3, 2]]
Explanation:
Solution solution = new Solution([1, 2, 3]);
solution.shuffle(); // Returns a random shuffling, e.g., [3, 1, 2]
solution.reset(); // Returns the original array [1, 2, 3]
solution.shuffle(); // Returns another random shuffling, e.g., [1, 3, 2]
Explain the algorithm you would use, its time and space complexity, and provide code implementation.
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 most straightforward way to shuffle something is to consider every possible arrangement. The brute force method for shuffling an array involves generating all possible orderings and then randomly picking one. It's like trying out every single way to arrange the items until you find one you like.
Here's how the algorithm would work step-by-step:
import random
import itertools
def brute_force_shuffle(input_array):
# Generate all possible permutations of the array
all_permutations = list(itertools.permutations(input_array))
# Choose a random permutation from the list.
# This ensures each arrangement has equal probability.
random_index = random.randint(0, len(all_permutations) - 1)
return list(all_permutations[random_index])
We want to rearrange items in a collection randomly. The best way to do this is to go through the collection, and for each item, swap it with another randomly chosen item from the collection. This guarantees each arrangement has an equal chance of happening.
Here's how the algorithm would work step-by-step:
import random
def shuffle_array(input_array):
array_length = len(input_array)
for current_index in range(array_length):
# Generate a random index within the bounds of the array
random_index = random.randint(0, array_length - 1)
# Swap the current element with the element at the random index
# This ensures each element has a chance to move to any position
input_array[current_index], input_array[random_index] = input_array[random_index], input_array[current_index]
# Return the shuffled array
return input_array
Case | How to Handle |
---|---|
Null input array | Throw an IllegalArgumentException or return null/empty array (depending on problem requirements and language conventions). |
Empty array (nums.length == 0) | Return a new empty array or the original empty array; specify behavior in documentation. |
Array with a single element (nums.length == 1) | Return a copy of the original array as shuffling is trivial, or return the original array itself. |
Array with all identical values | The shuffling algorithm should still produce a permutation, although all permutations will be identical. |
Large array size (approaching memory limits) | In-place shuffling algorithms like Fisher-Yates are memory-efficient and suitable for large arrays. |
Array containing negative numbers, zeros, and positive numbers | The shuffling algorithm should work correctly regardless of the numerical values in the array. |
Calling shuffle multiple times in succession. | Each call to shuffle must produce a new and independent random permutation. |
Integer overflow when generating random indices | Use appropriate random number generation functions that avoid integer overflow issues, potentially using long or double. |