Open In App

Check if all strings of an array can be made same by interchanging characters

Improve
Improve
Like Article
Like
Save
Share
Report

Given an array arr[] of size N consisting of equal length strings, the task is to check if it is possible to make all strings of the array can be equal or not by swapping any character of one string with any character of the same string or another string. 
Note: Perform the operation 0 or more times.

Examples:

Input : arr[] = {“fdd”, “fhh”}
Output: Yes
Explanation:
Swap(arr[0][1], arr[1][1]) then arr[]={“fhd”, “fdh”}
Swap(arr[1][1], arr[1][2]) then arr[]={“fhd”, “fhd”}. Therefore, it is possible to make all strings equal.

Input: arr[] = {“fde”, “fhg”}
Output: No

Approach: The problem can be solved by counting the frequency of each character of the given array and check if it is divisible by N or not. Follow the steps below to solve the problem:

  1. Initialize an array, hash[256]={0} to store the frequency of characters.
  2. Traverse hash[] array and check if the frequency of all characters is divisible by N or not.
  3. If the frequency of all characters is divisible by N, then print Yes.
  4. Otherwise, print No.

Below is the implementation of the above approach:

C++




// C++ Program to implement
// the above approach
#include <bits/stdc++.h>
using namespace std;
 
// Function to check if all strings
// are equal after swap operations
bool checkEqual(string arr[], int N)
{
    // Stores the frequency
    // of characters
    int hash[256] = { 0 };
 
    // Stores the length of string
    int M = arr[0].length();
 
    // Traverse the array
    for (int i = 0; i < N; i++) {
        // Traverse each string
        for (int j = 0; j < M; j++) {
            hash[arr[i][j]]++;
        }
    }
 
    // Check if frequency of character
    // is divisible by N
    for (int i = 0; i < 256; i++) {
        if (hash[i] % N != 0) {
            return false;
        }
    }
 
    return true;
}
 
// Driver Code
int main()
{
 
    string arr[] = { "fdd", "fhh" };
    int N = sizeof(arr) / sizeof(arr[0]);
 
    if (checkEqual(arr, N)) {
        cout << "Yes";
    }
    else {
        cout << "No";
    }
 
    return 0;
}


Java




// Java Program to implement
// the above approach
class GFG{
 
// Function to check if all Strings
// are equal after swap operations
static boolean checkEqual(String arr[],
                          int N)
{
  // Stores the frequency
  // of characters
  int hash[] = new int[256];
 
  // Stores the length of String
  int M = arr[0].length();
 
  // Traverse the array
  for (int i = 0; i < N; i++)
  {
    // Traverse each String
    for (int j = 0; j < M; j++)
    {
      hash[arr[i].charAt(j)]++;
    }
  }
 
  // Check if frequency of character
  // is divisible by N
  for (int i = 0; i < 256; i++)
  {
    if (hash[i] % N != 0)
    {
      return false;
    }
  }
 
  return true;
}
 
// Driver Code
public static void main(String[] args)
{
  String arr[] = {"fdd", "fhh"};
  int N = arr.length;
 
  if (checkEqual(arr, N))
  {
    System.out.print("Yes");
  }
  else
  {
    System.out.print("No");
  }
}
}
 
// This code is contributed by 29AjayKumar


Python3




# Python3 program to implement
# the above approach
 
# Function to check if all strings
# are equal after swap operations
def checkEqual(arr, N):
 
    # Stores the frequency
    # of characters
    hash = [0] * 256
 
    # Stores the length of string
    M = len(arr[0])
 
    # Traverse the array
    for i in range(N):
         
        # Traverse each string
        for j in range(M):
            hash[ord(arr[i][j])] += 1
 
    # Check if frequency of character
    # is divisible by N
    for i in range(256):
        if(hash[i] % N != 0):
            return False
 
    return True
 
# Driver Code
arr = [ "fdd", "fhh" ]
N = len(arr)
 
# Function call
if(checkEqual(arr, N)):
    print("Yes")
else:
    print("No")
 
# This code is contributed by Shivam Singh


C#




// C# program to implement
// the above approach
using System;
 
class GFG{
 
// Function to check if all Strings
// are equal after swap operations
static bool checkEqual(String []arr,
                       int N)
{
     
    // Stores the frequency
    // of characters
    int []hash = new int[256];
     
    // Stores the length of String
    int M = arr[0].Length;
     
    // Traverse the array
    for(int i = 0; i < N; i++)
    {
         
        // Traverse each String
        for(int j = 0; j < M; j++)
        {
            hash[arr[i][j]]++;
        }
    }
     
    // Check if frequency of character
    // is divisible by N
    for(int i = 0; i < 256; i++)
    {
        if (hash[i] % N != 0)
        {
            return false;
        }
    }
    return true;
}
 
// Driver Code
public static void Main(String[] args)
{
    String []arr = { "fdd", "fhh" };
    int N = arr.Length;
     
    if (checkEqual(arr, N))
    {
        Console.Write("Yes");
    }
    else
    {
        Console.Write("No");
    }
}
}
 
// This code is contributed by Amit Katiyar


Javascript




<script>
 
// Javascript program to implement
// the above approach
 
// Function to check if all strings
// are equal after swap operations
function checkEqual(arr, N)
{
     
    // Stores the frequency
    // of characters
    var hash = Array(256).fill(0);
 
    // Stores the length of string
    var M = arr[0].length;
 
    // Traverse the array
    for(var i = 0; i < N; i++)
    {
         
        // Traverse each string
        for(var j = 0; j < M; j++)
        {
            hash[arr[i][j]]++;
        }
    }
 
    // Check if frequency of character
    // is divisible by N
    for(var i = 0; i < 256; i++)
    {
        if (hash[i] % N != 0)
        {
            return false;
        }
    }
    return true;
}
 
// Driver Code
var arr = ["fdd", "fhh"];
var N = arr.length;
if (checkEqual(arr, N))
{
    document.write("Yes");
}
else
{
    document.write("No");
}
 
// This code is contributed by importantly
 
</script>


Output

Yes





Time Complexity: O(N)
Auxiliary Space: O(1), since no extra space has been taken.

Approach 2: Dynamic Programming:

Here’s a dynamic programming approach to check if all strings are equal after swap operations. We can model this problem as a graph problem, where each string is a node in the graph, and there is an edge between two nodes if and only if we can transform one string into the other by swapping two characters.

Here is the steps to above procedure:

  • We can use a dynamic programming approach to compute the connected components of the graph. We can represent each connected component as a set of integers, where each integer corresponds to a node in the graph. We can compute the connected components of the graph using depth-first search or breadth-first search.
  • Once we have computed the connected components of the graph, we can check if each connected component satisfies the condition that all strings are equal after swap operations. To do this, we can count the frequency of each character in the first string of the connected component, and then check if the frequency of each character is the same in all strings in the connected component.

Here’s the code implementation of this approach:

C++




#include <bits/stdc++.h>
using namespace std;
 
// Function to check if all strings
// are equal after swap operations
bool checkEqual(string arr[], int N)
{
    // Stores the length of string
    int M = arr[0].length();
     
    // Construct the graph
    vector<int> adj[N];
    for (int i = 0; i < N; i++) {
        for (int j = i+1; j < N; j++) {
            int cnt = 0;
            for (int k = 0; k < M; k++) {
                if (arr[i][k] != arr[j][k]) {
                    cnt++;
                }
                if (cnt > 2) {
                    break;
                }
            }
            if (cnt == 2) {
                adj[i].push_back(j);
                adj[j].push_back(i);
            }
        }
    }
     
    // Compute the connected components
    vector<set<int>> components;
    vector<bool> visited(N, false);
    for (int i = 0; i < N; i++) {
        if (!visited[i]) {
            set<int> component;
            queue<int> q;
            q.push(i);
            visited[i] = true;
            while (!q.empty()) {
                int u = q.front();
                q.pop();
                component.insert(u);
                for (int v : adj[u]) {
                    if (!visited[v]) {
                        q.push(v);
                        visited[v] = true;
                    }
                }
            }
            components.push_back(component);
        }
    }
     
    // Check if each connected component satisfies the condition
    for (set<int> component : components) {
        int freq[256] = {0};
        for (int u : component) {
            for (int k = 0; k < M; k++) {
                freq[arr[u][k]]++;
            }
        }
        for (int i = 0; i < 256; i++) {
            if (freq[i] % component.size() != 0) {
                return false;
            }
        }
    }
     
    return true;
}
 
// Driver Code
int main()
{
    string arr[] = { "fdd", "fhh" };
    int N = sizeof(arr) / sizeof(arr[0]);
 
    if (checkEqual(arr, N)) {
        cout << "Yes";
    }
    else {
        cout << "No";
    }
 
    return 0;
}


Java




import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
 
public class Main {
     
    // Function to check if all strings are equal after swap operations
    static boolean checkEqual(String[] arr, int N) {
        // Stores the length of string
        int M = arr[0].length();
 
        // Construct the graph
        ArrayList<Integer>[] adj = new ArrayList[N];
        for (int i = 0; i < N; i++) {
            adj[i] = new ArrayList<>();
        }
        for (int i = 0; i < N; i++) {
            for (int j = i + 1; j < N; j++) {
                int cnt = 0;
                for (int k = 0; k < M; k++) {
                    if (arr[i].charAt(k) != arr[j].charAt(k)) {
                        cnt++;
                    }
                    if (cnt > 2) {
                        break;
                    }
                }
                if (cnt == 2) {
                    adj[i].add(j);
                    adj[j].add(i);
                }
            }
        }
 
        // Compute the connected components
        ArrayList<Set<Integer>> components = new ArrayList<>();
        boolean[] visited = new boolean[N];
        for (int i = 0; i < N; i++) {
            if (!visited[i]) {
                Set<Integer> component = new HashSet<>();
                Queue<Integer> q = new LinkedList<>();
                q.add(i);
                visited[i] = true;
                while (!q.isEmpty()) {
                    int u = q.poll();
                    component.add(u);
                    for (int v : adj[u]) {
                        if (!visited[v]) {
                            q.add(v);
                            visited[v] = true;
                        }
                    }
                }
                components.add(component);
            }
        }
 
        // Check if each connected component satisfies the condition
        for (Set<Integer> component : components) {
            int[] freq = new int[256];
            for (int u : component) {
                for (int k = 0; k < M; k++) {
                    freq[arr[u].charAt(k)]++;
                }
            }
            for (int i = 0; i < 256; i++) {
                if (freq[i] % component.size() != 0) {
                    return false;
                }
            }
        }
 
        return true;
    }
 
    public static void main(String[] args) {
        String[] arr = {"fdd", "fhh"};
        int N = arr.length;
 
        if (checkEqual(arr, N)) {
            System.out.println("YES");
        } else {
            System.out.println("NO");
        }
    }
}


Python3




from collections import deque
 
# Function to check if all strings are equal after swap operations
def checkEqual(arr, N):
    # Stores the length of string
    M = len(arr[0])
 
    # Construct the graph
    adj = [[] for _ in range(N)]
    for i in range(N):
        for j in range(i+1, N):
            cnt = 0
            for k in range(M):
                if arr[i][k] != arr[j][k]:
                    cnt += 1
                if cnt > 2:
                    break
            if cnt == 2:
                adj[i].append(j)
                adj[j].append(i)
 
    # Compute the connected components
    components = []
    visited = [False]*N
    for i in range(N):
        if not visited[i]:
            component = set()
            q = deque()
            q.append(i)
            visited[i] = True
            while q:
                u = q.popleft()
                component.add(u)
                for v in adj[u]:
                    if not visited[v]:
                        q.append(v)
                        visited[v] = True
            components.append(component)
 
    # Check if each connected component satisfies the condition
    for component in components:
        freq = [0]*256
        for u in component:
            for k in range(M):
                freq[ord(arr[u][k])] += 1
        for i in range(256):
            if freq[i] % len(component) != 0:
                return False
 
    return True
 
# Driver Code
if __name__ == '__main__':
    arr = ["fdd", "fhh"]
    N = len(arr)
 
    if checkEqual(arr, N):
        print("Yes")
    else:
        print("No")


C#




using System;
using System.Collections.Generic;
 
class Program
{
    static bool AreEqualAfterSwaps(string[] arr)
    {
        int n = arr.Length;
        int m = arr[0].Length;
 
        // Create a disjoint-set data structure
        int[] parent = new int[n];
        for (int i = 0; i < n; i++)
            parent[i] = i;
 
        for (int i = 0; i < n; i++)
        {
            for (int j = i + 1; j < n; j++)
            {
                int diffCount = 0;
 
                // Count the differences between the two strings
                for (int k = 0; k < m; k++)
                {
                    if (arr[i][k] != arr[j][k])
                        diffCount++;
                }
 
                // If there are exactly 2 differences, merge the sets
                if (diffCount == 2)
                    Union(parent, i, j);
            }
        }
 
        // Check if all strings belong to the same set
        for (int i = 1; i < n; i++)
        {
            if (Find(parent, i) != Find(parent, 0))
                return false;
        }
 
        return true;
    }
 
    static int Find(int[] parent, int x)
    {
        if (parent[x] != x)
            parent[x] = Find(parent, parent[x]);
        return parent[x];
    }
 
    static void Union(int[] parent, int x, int y)
    {
        int rootX = Find(parent, x);
        int rootY = Find(parent, y);
        if (rootX != rootY)
            parent[rootX] = rootY;
    }
 
    static void Main()
    {
        string[] arr = { "fdd", "fhh" };
 
        if (AreEqualAfterSwaps(arr))
            Console.WriteLine("Yes");
        else
            Console.WriteLine("No");
    }
}


Javascript




// Function to check if all strings are equal after swap operations
function checkEqual(arr, N) {
    // Stores the length of string
    const M = arr[0].length;
 
    // Construct the graph
    const adj = Array.from({ length: N }, () => []);
    for (let i = 0; i < N; i++) {
        for (let j = i + 1; j < N; j++) {
            let cnt = 0;
            for (let k = 0; k < M; k++) {
                if (arr[i][k] !== arr[j][k]) {
                    cnt++;
                }
                if (cnt > 2) {
                    break;
                }
            }
            if (cnt === 2) {
                adj[i].push(j);
                adj[j].push(i);
            }
        }
    }
 
    // Compute the connected components
    const components = [];
    const visited = new Array(N).fill(false);
    for (let i = 0; i < N; i++) {
        if (!visited[i]) {
            const component = new Set();
            const q = [];
            q.push(i);
            visited[i] = true;
            while (q.length > 0) {
                const u = q.shift();
                component.add(u);
                for (const v of adj[u]) {
                    if (!visited[v]) {
                        q.push(v);
                        visited[v] = true;
                    }
                }
            }
            components.push(component);
        }
    }
 
    // Check if each connected component satisfies the condition
    for (const component of components) {
        const freq = new Array(256).fill(0);
        for (const u of component) {
            for (let k = 0; k < M; k++) {
                freq[arr[u][k].charCodeAt()]++;
            }
        }
        for (let i = 0; i < 256; i++) {
            if (freq[i] % component.size !== 0) {
                return false;
            }
        }
    }
 
    return true;
}
 
// Driver Code
const arr = ["fdd", "fhh"];
const N = arr.length;
 
if (checkEqual(arr, N)) {
    console.log("Yes");
} else {
    console.log("No");
}


Output: 

Yes

Time Complexity: O(N*M^2)
Auxiliary Space: O(1), since no extra space has been taken.



Last Updated : 16 Oct, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads