3644. Maximum K to Sort a Permutation
Problem Description
You have an integer array nums
of length n
that contains a permutation of all numbers from 0
to n-1
(each number appears exactly once).
You can perform swap operations on this array, but with a specific constraint: you can only swap elements at positions i
and j
if nums[i] AND nums[j] == k
, where AND
is the bitwise AND operation and k
is a non-negative integer that you choose.
Your goal is to find the maximum possible value of k
such that using this value, you can sort the array into non-decreasing order (ascending order) through any number of valid swaps.
If the array is already sorted, return 0
.
For example:
- If you choose
k = 2
, you can only swap elements where their bitwise AND equals2
- Elements like
6
(binary:110
) and3
(binary:011
) have6 AND 3 = 2
, so they could be swapped ifk = 2
- You need to find the largest
k
value that still allows you to completely sort the array
The solution works by checking which elements are not in their correct positions (where element x
should be at index x
). For all misplaced elements, it performs a bitwise AND operation on all of them. This gives the maximum k
that allows necessary swaps to sort the array, since any bit that's 1
in the result must be 1
in all misplaced elements, ensuring they can all participate in swaps with each other or with correctly placed elements sharing those bits.
Intuition
To understand why we need to find the bitwise AND of all misplaced elements, let's think about what swaps are necessary to sort the array.
Since nums
is a permutation of [0, 1, 2, ..., n-1]
, the sorted array should have each element i
at position i
. Any element that's not at its correct position needs to be moved through swaps.
The key insight is that for a given k
, elements can only be swapped if their bitwise AND equals k
. This creates "swap groups" - elements that can potentially exchange positions with each other. For the array to be sortable:
- All misplaced elements must be able to participate in swaps (either directly or indirectly through a chain of swaps)
- The value
k
must be present as a common pattern in the binary representation of all misplaced elements
Consider what happens at the bit level: if k
has a bit set to 1
at position p
, then for two numbers to have AND = k
, both numbers must have bit 1
at position p
. This means any bit that's 1
in k
must be 1
in all numbers we need to swap.
Therefore, the maximum k
is the bitwise AND of all misplaced elements. This ensures:
- Every misplaced element has all the bits of
k
set to1
, so they can potentially participate in swaps - We're using the largest possible
k
that satisfies this condition - Elements already in correct positions don't restrict our choice of
k
since they don't need to be moved
If all elements are already in place, no swaps are needed, so we return 0
. The solution elegantly handles this by initializing ans = -1
(all bits set to 1
), and the AND operation naturally gives 0
or positive when needed through max(ans, 0)
.
Solution Approach
The implementation follows a straightforward approach to find the maximum k
:
-
Initialize the answer: Start with
ans = -1
. In binary,-1
is represented as all bits set to1
(due to two's complement representation). This serves as our starting point for the bitwise AND operation. -
Iterate through the array: For each element at index
i
, check if it's in its correct position:for i, x in enumerate(nums): if i != x:
- If element
x
is at indexi
andi != x
, then this element is misplaced - In a sorted permutation of
[0, 1, ..., n-1]
, elementx
should be at indexx
- If element
-
Accumulate the bitwise AND: For each misplaced element, perform bitwise AND with the current answer:
ans &= x
- This operation keeps only the bits that are
1
in bothans
andx
- After processing all misplaced elements,
ans
will contain only the bits that are1
in ALL misplaced elements - This gives us the maximum
k
where all misplaced elements satisfy the condition that their AND with other elements can equalk
- This operation keeps only the bits that are
-
Handle the edge case: Return the maximum of
ans
and0
:return max(ans, 0)
- If the array is already sorted (no misplaced elements),
ans
remains-1
, so we return0
- Otherwise, we return the computed bitwise AND value
- If the array is already sorted (no misplaced elements),
The algorithm runs in O(n)
time with O(1)
extra space, making it highly efficient. The beauty of this solution lies in recognizing that the constraint on swaps translates directly to a bitwise AND operation on all elements that need to be moved.
Ready to land your dream job?
Unlock your dream job with a 3-minute evaluator for a personalized learning plan!
Start EvaluatorExample Walkthrough
Let's walk through a concrete example to understand how the solution works.
Example: nums = [3, 0, 1, 2, 5, 4]
Step 1: Identify misplaced elements
First, let's check which elements are not in their correct positions:
- Index 0: has value 3 (should be 0) → misplaced
- Index 1: has value 0 (should be 1) → misplaced
- Index 2: has value 1 (should be 2) → misplaced
- Index 3: has value 2 (should be 3) → misplaced
- Index 4: has value 5 (should be 4) → misplaced
- Index 5: has value 4 (should be 5) → misplaced
All elements are misplaced! The misplaced values are: 3, 0, 1, 2, 5, 4
Step 2: Calculate bitwise AND of misplaced elements
Let's convert to binary and perform the AND operation:
3 = 011 0 = 000 1 = 001 2 = 010 5 = 101 4 = 100
Starting with ans = -1
(all bits set to 1):
ans = -1 & 3 = 3
(binary: 011)ans = 3 & 0 = 0
(binary: 000)- Since we get 0, all subsequent AND operations will remain 0
Step 3: Return result
The maximum k value is 0.
Verification: With k = 0, we can swap any two elements whose AND equals 0. Let's check some pairs:
- 3 & 0 = 0 ✓ (can swap)
- 1 & 2 = 0 ✓ (can swap)
- 5 & 2 = 0 ✓ (can swap)
- 4 & 3 = 0 ✓ (can swap)
This allows enough flexibility to sort the array through a series of swaps.
Alternative Example: nums = [2, 0, 1, 3]
- Index 0: has value 2 (should be 0) → misplaced
- Index 1: has value 0 (should be 1) → misplaced
- Index 2: has value 1 (should be 2) → misplaced
- Index 3: has value 3 (should be 3) → correct!
Misplaced values: 2, 0, 1
Binary representation:
2 = 10 0 = 00 1 = 01
Bitwise AND: 2 & 0 & 1 = 0
So the maximum k is 0, which allows swaps between elements with AND = 0, enabling us to sort the array.
Solution Implementation
1from typing import List
2
3class Solution:
4 def sortPermutation(self, nums: List[int]) -> int:
5 # Initialize result with -1 (all bits set to 1 in two's complement)
6 ans = -1
7
8 # Iterate through the array with indices
9 for i, x in enumerate(nums):
10 # Check if element is not at its "sorted" position
11 # (assuming 0-indexed positions should match values)
12 if i != x:
13 # Perform bitwise AND with misplaced elements
14 # This keeps only common set bits across all misplaced values
15 ans &= x
16
17 # Return the result, ensuring non-negative output
18 # If no misplaced elements found, ans remains -1, so return 0
19 return max(ans, 0)
20
1class Solution {
2 /**
3 * Finds the bitwise AND of all elements that are not in their correct sorted position.
4 * Returns 0 if all elements are already in their correct positions or if the AND result is negative.
5 *
6 * @param nums The input array to check
7 * @return The bitwise AND of misplaced elements, or 0 if none exist or result is negative
8 */
9 public int sortPermutation(int[] nums) {
10 // Initialize result with -1 (all bits set to 1)
11 int result = -1;
12
13 // Iterate through each element in the array
14 for (int i = 0; i < nums.length; ++i) {
15 // Check if current element is not in its expected sorted position
16 // (assuming sorted position means nums[i] should equal i)
17 if (i != nums[i]) {
18 // Perform bitwise AND with the misplaced element
19 result &= nums[i];
20 }
21 }
22
23 // Return the maximum of result and 0
24 // This ensures non-negative output (returns 0 if result is negative)
25 return Math.max(result, 0);
26 }
27}
28
1class Solution {
2public:
3 int sortPermutation(vector<int>& nums) {
4 // Initialize result with -1 (all bits set to 1 in binary)
5 int result = -1;
6
7 // Iterate through each element in the array
8 for (int i = 0; i < nums.size(); ++i) {
9 // Check if current element is not at its sorted position
10 // (assuming 0-indexed array where nums[i] should equal i in sorted order)
11 if (i != nums[i]) {
12 // Perform bitwise AND operation with the misplaced element
13 result &= nums[i];
14 }
15 }
16
17 // Return the maximum between result and 0
18 // This ensures non-negative output (returns 0 if result is negative)
19 return max(result, 0);
20 }
21};
22
1/**
2 * Finds the bitwise AND of all elements that are not in their correct sorted position
3 * @param nums - Array of numbers to check
4 * @returns The bitwise AND result, or 0 if negative or no misplaced elements
5 */
6function sortPermutation(nums: number[]): number {
7 // Initialize result with -1 (all bits set to 1)
8 let bitwiseAndResult: number = -1;
9
10 // Iterate through each element in the array
11 for (let i = 0; i < nums.length; ++i) {
12 // Check if current element is not at its expected position
13 // (assuming the expected position is when nums[i] === i)
14 if (i !== nums[i]) {
15 // Perform bitwise AND with the misplaced element
16 bitwiseAndResult &= nums[i];
17 }
18 }
19
20 // Return the maximum between the result and 0
21 // This ensures non-negative output
22 return Math.max(bitwiseAndResult, 0);
23}
24
Time and Space Complexity
Time Complexity: O(n)
where n
is the length of the input list nums
. The algorithm iterates through the list exactly once using enumerate()
, performing constant-time operations (comparison and bitwise AND) for each element.
Space Complexity: O(1)
. The algorithm only uses a fixed amount of extra space for variables ans
, i
, and x
, regardless of the input size. The space used does not grow with the size of the input list.
Common Pitfalls
1. Misunderstanding the Initial Value of -1
Pitfall: Developers might incorrectly initialize ans
with 0
or float('inf')
instead of -1
, thinking they need to start with a neutral or maximum value.
Why it's wrong:
- Starting with
0
would immediately make any bitwise AND operation result in0
, losing all information - Starting with
float('inf')
doesn't work with bitwise operations -1
in binary is all1
s (e.g.,11111111...
), which is the identity element for bitwise AND when finding common bits
Correct approach:
ans = -1 # All bits set to 1, perfect for finding common bits via AND
2. Forgetting to Handle the Already-Sorted Case
Pitfall: Returning ans
directly without checking if it's still -1
:
# Wrong implementation
def sortPermutation(self, nums: List[int]) -> int:
ans = -1
for i, x in enumerate(nums):
if i != x:
ans &= x
return ans # Would return -1 for sorted arrays!
Why it's wrong: If the array is already sorted, no elements are misplaced, so ans
remains -1
. The problem states we should return 0
for already-sorted arrays.
Correct approach:
return max(ans, 0) # Ensures we return 0 instead of -1 for sorted arrays
3. Incorrectly Identifying Misplaced Elements
Pitfall: Using wrong comparison logic like nums[i] != i+1
(1-indexed thinking) or nums[i] != nums[x]
:
# Wrong: assuming 1-indexed positions if x != i + 1: ans &= x # Wrong: comparing with value at position x if nums[i] != nums[x]: ans &= x
Why it's wrong: The problem describes a permutation of [0, 1, ..., n-1]
, where element x
should be at index x
in the sorted array.
Correct approach:
if i != x: # Element x at position i is misplaced if i ≠ x ans &= x
4. Misunderstanding What Value to AND
Pitfall: Performing AND with the index instead of the value:
# Wrong implementation
for i, x in enumerate(nums):
if i != x:
ans &= i # Should be x, not i!
Why it's wrong: We need to find common bits among the VALUES that need to be swapped, not their current positions. The swap condition is based on nums[i] AND nums[j] == k
, involving the actual values.
Correct approach:
ans &= x # AND with the misplaced value, not its index
Problem: Given a list of tasks and a list of requirements, compute a sequence of tasks that can be performed, such that we complete every task once while satisfying all the requirements.
Which of the following method should we use to solve this problem?
Recommended Readings
Coding Interview Patterns Your Personal Dijkstra's Algorithm to Landing Your Dream Job The goal of AlgoMonster is to help you get a job in the shortest amount of time possible in a data driven way We compiled datasets of tech interview problems and broke them down by patterns This way
Recursion Recursion is one of the most important concepts in computer science Simply speaking recursion is the process of a function calling itself Using a real life analogy imagine a scenario where you invite your friends to lunch https assets algo monster recursion jpg You first call Ben and ask
Runtime Overview When learning about algorithms and data structures you'll frequently encounter the term time complexity This concept is fundamental in computer science and offers insights into how long an algorithm takes to complete given a certain input size What is Time Complexity Time complexity represents the amount of time
Want a Structured Path to Master System Design Too? Don’t Miss This!