- categories: Code, Interview Question, leetcode, Medium
- source: https://leetcode.com/problems/make-lexicographically-smallest-array-by-swapping-elements
- topics: Array, Queue
Description
Idea
The problem revolves around transforming the input array into its lexicographically smallest form, adhering to the swap constraints defined by limit.
The main insight is to group the numbers into levels based on their closeness (difference ≤ limit). Each level can be independently sorted to achieve the smallest order while respecting the swap constraints.
Code
Bruteforce - very slow
class Solution:
def lexicographicallySmallestArray(self, nums: List[int], limit: int) -> List[int]:
swaped = True
while swaped:
swaped = False
for i in range(len(nums)):
for j in range(i+1, len(nums), 1):
diff = nums[i] - nums[j]
if 0 < diff <= limit:
nums[i], nums[j] = nums[j], nums[i]
swaped = True
break
if swaped:
break
return nums Sort + Grouping by level + queues
class Solution:
def lexicographicallySmallestArray(self, nums: List[int], limit: int) -> List[int]:
# Create a sorted copy of nums to determine levels
sorted_nums = sorted(nums)
levels = defaultdict(deque) # Map of levels to their elements (sorted in deque)
level_map = {} # Element to level mapping
current_level = 0
levels[current_level].append(sorted_nums[0])
level_map[sorted_nums[0]] = current_level
for i in range(1, len(sorted_nums)):
# If the difference is within the limit, assign to the same level
if sorted_nums[i] - levels[current_level][-1] <= limit:
levels[current_level].append(sorted_nums[i])
else:
# Otherwise, start a new level
current_level += 1
levels[current_level].append(sorted_nums[i])
level_map[sorted_nums[i]] = current_level # Map element to its level
# Rebuild the original array
for i in range(len(nums)):
element_level = level_map[nums[i]] # Get the level of the current element
nums[i] = levels[element_level].popleft() # Replace with the smallest number in its level
return nums