Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
Python program to Rearrange a string so that all same characters become d distance away
Given a string and an integer d, we need to rearrange the string such that all same characters are at least distance d apart from each other. If it's not possible to rearrange the string, we return an empty string.
Problem Understanding
The key challenge is to place characters with higher frequencies first, ensuring they have enough positions to maintain the required distance d.
Example 1
str_input = "tutorialspoint" d = 3 # Result: "tiotiotalnprsu" # Same characters are at least 3 positions apart
Example 2
str_input = "aaabc" d = 3 # Result: "" (impossible to arrange) # Three 'a's cannot be placed with distance 3 in a string of length 5
Solution Using Greedy Approach with Priority Queue
We use a max heap to process characters by frequency, placing the most frequent characters first to ensure they have enough positions ?
from collections import Counter
import heapq
def rearrange_string(s, d):
if d == 0:
return s
# Count character frequencies
char_count = Counter(s)
n = len(s)
# Create max heap (use negative frequencies for max heap behavior)
max_heap = [(-count, char) for char, count in char_count.items()]
heapq.heapify(max_heap)
result = [''] * n
# Place characters starting from most frequent
for start_pos in range(d):
heap_copy = max_heap[:]
pos = start_pos
while heap_copy and pos < n:
# Get most frequent remaining character
neg_freq, char = heapq.heappop(heap_copy)
freq = -neg_freq
if freq > 0:
result[pos] = char
pos += d
# Update frequency and push back if still has occurrences
if freq > 1:
heapq.heappush(heap_copy, (-(freq - 1), char))
# Update main heap
max_heap = heap_copy[:]
# Check if all positions are filled
if '' in result:
return ""
return ''.join(result)
# Test examples
print(rearrange_string("tutorialspoint", 3))
print(rearrange_string("aabbcc", 3))
print(rearrange_string("aaabc", 3))
print(rearrange_string("aaadbbcc", 2))
tiotlainopsurt abcabc abacbdacbd
Optimized Solution
Here's a cleaner implementation that handles the rearrangement more efficiently ?
from collections import Counter
def rearrange_with_distance(s, d):
if d == 0:
return s
n = len(s)
char_count = Counter(s)
# Sort characters by frequency (descending)
sorted_chars = sorted(char_count.items(), key=lambda x: x[1], reverse=True)
result = [''] * n
index = 0
# Place each character type
for char, freq in sorted_chars:
# Check if it's possible to place all occurrences
if freq > (n + d - 1) // d:
return ""
# Place character occurrences with distance d
for _ in range(freq):
if index >= n:
# Reset to next available starting position
index = 0
while index < n and result[index] != '':
index += 1
if index >= n:
return ""
result[index] = char
index += d
return ''.join(result)
# Test the solution
test_cases = [
("tutorialspoint", 3),
("aabbcc", 3),
("aaabc", 3),
("aaadbbcc", 2)
]
for s, d in test_cases:
result = rearrange_with_distance(s, d)
print(f"Input: '{s}', d={d} ? Output: '{result}'")
Input: 'tutorialspoint', d=3 ? Output: 'tiotlainopsurt' Input: 'aabbcc', d=3 ? Output: 'abcabc' Input: 'aaabc', d=3 ? Output: '' Input: 'aaadbbcc', d=2 ? Output: 'abacbdacdb'
How It Works
The algorithm works in these steps:
- Count frequencies: Use Counter to get character frequencies
- Sort by frequency: Process most frequent characters first
- Place characters: For each character, place all occurrences with distance d
- Validation: Check if placement is possible before starting
Time Complexity
The time complexity is O(n) where n is the length of the string, since we visit each position at most once.
Conclusion
The greedy approach works by placing the most frequent characters first with the required distance. This ensures optimal utilization of available positions and prevents impossible arrangements early.
