Given an array arr[] of integers, determine whether it is possible to rearrange the array using any number of swaps between adjacent elements - so that no two adjacent elements in the resulting array are equal.
Examples:
Input: arr[] = [1, 1, 2]
Output: true
Explanation: Swapping the last two elements gives [1, 2, 1], where no two adjacent elements are equal.Input: arr[] = [7, 7, 7, 7]
Output: false
Explanation: Every element is identical, so any arrangement will always have equal adjacent elements. Hence, no sequence of swaps can fix this.
Table of Content
[Naive Approach] Using Hash Map to Count Frequencies - O(n) Time and O(n) Space
The idea is to count the frequency of every element in a single pass using a hash map, then find the maximum frequency among all elements. The array can be rearranged with no two adjacent elements equal if and only if this maximum frequency does not exceed ⌈n/2⌉ - any more, and that element would be forced to repeat next to itself no matter how the array is arranged.
Step by Step Implementation:
- Count the frequency of every element using a hash map.
- Find the maximum frequency among all elements.
- Check if this maximum frequency is at most ⌈n/2⌉ (computed as (n + 1) / 2 using integer division).
- Return true if the condition holds, false otherwise.
#include <iostream>
#include <vector>
#include <unordered_map>
using namespace std;
bool distinctAdjacent(vector<int> &arr) {
int n = arr.size();
// Count the frequency of every element
unordered_map<int, int> freq;
for (int num : arr) {
freq[num]++;
}
// Find the maximum frequency among all elements
int maxFreq = 0;
for (auto &entry : freq) {
maxFreq = max(maxFreq, entry.second);
}
// Rearrangement is possible only if the maximum frequency
// does not exceed ceil(n / 2)
return maxFreq <= (n + 1) / 2;
}
int main() {
vector<int> arr = {1, 1, 2};
cout << (distinctAdjacent(arr) ? "true" : "false") << endl;
return 0;
}
import java.util.HashMap;
class GFG {
static boolean distinctAdjacent(int[] arr) {
int n = arr.length;
// Count the frequency of every element
HashMap<Integer, Integer> freq = new HashMap<>();
for (int num : arr) {
freq.put(num, freq.getOrDefault(num, 0) + 1);
}
// Find the maximum frequency among all elements
int maxFreq = 0;
for (int val : freq.values()) {
maxFreq = Math.max(maxFreq, val);
}
// Rearrangement is possible only if the maximum frequency
// does not exceed ceil(n / 2)
return maxFreq <= (n + 1) / 2;
}
public static void main(String[] args) {
int[] arr = {1, 1, 2};
System.out.println(distinctAdjacent(arr));
}
}
from collections import Counter
def distinctAdjacent(arr):
n = len(arr)
# Count the frequency of every element
freq = Counter(arr)
# Find the maximum frequency among all elements
maxFreq = max(freq.values())
# Rearrangement is possible only if the maximum frequency
# does not exceed ceil(n / 2)
return maxFreq <= (n + 1) // 2
arr = [1, 1, 2]
print("true" if distinctAdjacent(arr) else "false")
using System;
using System.Collections.Generic;
using System.Linq;
class GFG {
static bool distinctAdjacent(int[] arr) {
int n = arr.Length;
// Count the frequency of every element
Dictionary<int, int> freq = new Dictionary<int, int>();
foreach (int num in arr) {
if (freq.ContainsKey(num)) freq[num]++;
else freq[num] = 1;
}
// Find the maximum frequency among all elements
int maxFreq = freq.Values.Max();
// Rearrangement is possible only if the maximum frequency
// does not exceed ceil(n / 2)
return maxFreq <= (n + 1) / 2;
}
static void Main() {
int[] arr = { 1, 1, 2 };
Console.WriteLine(distinctAdjacent(arr) ? "true" : "false");
}
}
function distinctAdjacent(arr) {
const n = arr.length;
// Count the frequency of every element
const freq = new Map();
for (const num of arr) {
freq.set(num, (freq.get(num) || 0) + 1);
}
// Find the maximum frequency among all elements
let maxFreq = 0;
for (const val of freq.values()) {
maxFreq = Math.max(maxFreq, val);
}
// Rearrangement is possible only if the maximum frequency
// does not exceed ceil(n / 2)
return maxFreq <= Math.floor((n + 1) / 2);
}
// Driver Code
const arr = [1, 1, 2];
console.log(distinctAdjacent(arr) ? "true" : "false");
Output
true
[Expected Approach] Using Boyer-Moore Voting Algorithm - O(n) Time and O(1) Space
The idea is to first find a candidate for the most frequent element using Boyer-Moore's voting algorithm, which processes the array in a single pass without any extra space. We then verify this candidate's actual frequency in a second pass, and check if it exceeds ⌈n/2⌉. Since the true maximum-frequency element is guaranteed to survive the voting phase whenever it actually causes infeasibility, this approach avoids the extra space a hash map would need.
- Run Boyer-Moore's voting algorithm: maintain a candidate and a count, incrementing the count when the current element matches the candidate, decrementing otherwise, and switching candidates whenever the count drops to zero.
- After the voting phase, count how many times the resulting candidate actually appears in the array.
- Check if this count exceeds ⌈n/2⌉ (computed as (n + 1) / 2 using integer division).
- Return false if it does, true otherwise.
#include <iostream>
#include <vector>
using namespace std;
bool distinctAdjacent(vector<int> &arr) {
int n = arr.size();
// Voting phase: find a candidate using Boyer-Moore's algorithm
int candidate = -1;
int count = 0;
for (int num : arr) {
if (count == 0) {
candidate = num;
count = 1;
} else if (num == candidate) {
count++;
} else {
count--;
}
}
// Verification phase: count the candidate's actual occurrences
count = 0;
for (int num : arr) {
if (num == candidate) {
count++;
}
}
// Rearrangement is impossible only if some element's frequency
// exceeds ceil(n / 2)
return count <= (n + 1) / 2;
}
int main() {
vector<int> arr = {1, 1, 2};
cout << (distinctAdjacent(arr) ? "true" : "false") << endl;
return 0;
}
class GFG {
static boolean distinctAdjacent(int[] arr) {
int n = arr.length;
// Voting phase: find a candidate using Boyer-Moore's algorithm
int candidate = -1;
int count = 0;
for (int num : arr) {
if (count == 0) {
candidate = num;
count = 1;
} else if (num == candidate) {
count++;
} else {
count--;
}
}
// Verification phase: count the candidate's actual occurrences
count = 0;
for (int num : arr) {
if (num == candidate) {
count++;
}
}
// Rearrangement is impossible only if some element's frequency
// exceeds ceil(n / 2)
return count <= (n + 1) / 2;
}
public static void main(String[] args) {
int[] arr = {1, 1, 2};
System.out.println(distinctAdjacent(arr));
}
}
def distinctAdjacent(arr):
n = len(arr)
# Voting phase: find a candidate using Boyer-Moore's algorithm
candidate = -1
count = 0
for num in arr:
if count == 0:
candidate = num
count = 1
elif num == candidate:
count += 1
else:
count -= 1
# Verification phase: count the candidate's actual occurrences
count = 0
for num in arr:
if num == candidate:
count += 1
# Rearrangement is impossible only if some element's frequency
# exceeds ceil(n / 2)
return count <= (n + 1) // 2
arr = [1, 1, 2]
print("true" if distinctAdjacent(arr) else "false")
using System;
class GFG {
static bool distinctAdjacent(int[] arr) {
int n = arr.Length;
// Voting phase: find a candidate using Boyer-Moore's algorithm
int candidate = -1;
int count = 0;
foreach (int num in arr) {
if (count == 0) {
candidate = num;
count = 1;
} else if (num == candidate) {
count++;
} else {
count--;
}
}
// Verification phase: count the candidate's actual occurrences
count = 0;
foreach (int num in arr) {
if (num == candidate) {
count++;
}
}
// Rearrangement is impossible only if some element's frequency
// exceeds ceil(n / 2)
return count <= (n + 1) / 2;
}
static void Main() {
int[] arr = { 1, 1, 2 };
Console.WriteLine(distinctAdjacent(arr) ? "true" : "false");
}
}
function distinctAdjacent(arr) {
const n = arr.length;
// Voting phase: find a candidate using Boyer-Moore's algorithm
let candidate = -1;
let count = 0;
for (const num of arr) {
if (count === 0) {
candidate = num;
count = 1;
} else if (num === candidate) {
count++;
} else {
count--;
}
}
// Verification phase: count the candidate's actual occurrences
count = 0;
for (const num of arr) {
if (num === candidate) {
count++;
}
}
// Rearrangement is impossible only if some element's frequency
// exceeds ceil(n / 2)
return count <= Math.floor((n + 1) / 2);
}
// Driver Code
const arr = [1, 1, 2];
console.log(distinctAdjacent(arr) ? "true" : "false");
Output
true