Skip to content
Related Articles

Related Articles

Find elements changing groups or never moving with other group element

View Discussion
Improve Article
Save Article
  • Last Updated : 05 Aug, 2022

Given two snapshots S1 and S2 of N elements, the task is to find the elements which are changing their groups and the ones that never formed groups with other group elements (Though they can break and form a separate subgroup).

Note: The position of a group and the elements inside a group can change. Groups can break into subgroups.

Examples:

Input: S1: {{1, 2, 3, 4}, {5, 6}, {7, 8}}, S2: {{1, 2},  {3},  {4, 5}, {7, 8}, {6}}
Output: {1  2  3  6  7  8}, {1  2  3  4  5  6}
Explanation: Elements in groups [1, 2], [3], [6], [7, 8] have never been 
with an element from another group so the answer is [1, 2, 3, 6, 7, 8].
Elements in the group [7, 8] have not changed their group. 
Otherwise, all other elements have broken or interchanged the group.

Input: S1: {{1, 3, 8}, {2, 5}, {4}, {9, 6}, {7, 10, 11, 12}}, S2: {{1, 3}, {9}, {8}, {12, 11}, {7, 6}, {2, 5}, {4, 10}}
Output:{1  3  9  8  11  12  2  5}, {1  3  9  8  12  11  7  6  4  10}
Explanation: Elements in groups [1, 3], [9], [8], [11, 12], [2, 5] have not been 
with an element from another group so answer is [1, 3, 9, 8, 11, 12, 2, 5]. 
Only [2, 5] have not changed their group. 
All other elements have broken or interchanged the group.

 

Naive Approach: The basic approach to solve the problem as mentioned below:

  • Loop through each group in snapshot-1 (group-1).
  • Loop through each element in group-1.
  • Find the element’s group in snapshot-2 (group-2).
  • Check if group2 is a subset of group1 or if both have the same elements.

Time Complexity: O(N * (N + k) * k2) where N is the total number of elements and K is the maximum element in a group
Auxiliary Space: O(1)

Efficient approach: To solve the problem efficiently follow the below idea carefully:

  • To find the people who changed their groups: It is easy to find those who didn’t changed their groups: if the group of element is the same in both the snapshots. All other elements have changed the group.
  • To find the people who have never interacted outside of their groups: If the final group is a subset or equal to the initial group then its elements have never interacted outside their group.
  • Since both of these problems compare the groups in snapshots so we can follow the same approach only difference is between how we compare the groups.

Follow the steps to solve the problem:

  • Loop through each group in snapshot-2 (group-2).
  • For any one person in group-2.
  • Find the person’s group in snapshot-1 (group-1).
  • Check if group2 is a subset of group1 or both, having the same people.

Below is the implementation for the above approach:

C++




// C++ code for the above approach:
 
#include <bits/stdc++.h>
using namespace std;
 
// Function to print vector elements
void printVector(vector<int> vec)
{
    for (auto value : vec) {
        cout << value << " ";
    }
    cout << "\n";
}
 
// Function to check if one is subset of other
// or they are equal
bool isSubsetOrEqual(vector<int> parent,
                     vector<int> child,
                     bool strictEqual)
{
    // Check for size equality
    if (strictEqual ? child.size() != parent.size()
                    : child.size() > parent.size()) {
        return false;
    }
 
    // Initializing a hash set
    set<int> hashset;
    for (auto item : parent) {
        hashset.insert(item);
    }
 
    for (auto item : child) {
        if (hashset.find(item)
            == hashset.end())
            return false;
    }
    return true;
}
 
// Function to append vector
void appendVector(vector<int>& result,
                  vector<int> values)
{
    for (auto value : values) {
        result.push_back(value);
    }
}
 
// Function to assign the groups of elements
unordered_map<int, int>
getPersonToGroupIdxMap(vector<vector<int> > groups)
{
    unordered_map<int, int> personToGroupIdxMap;
    for (int groupIdx = 0; groupIdx < groups.size();
         groupIdx++) {
        for (auto person : groups[groupIdx]) {
            personToGroupIdxMap[person] = groupIdx;
        }
    }
    return personToGroupIdxMap;
}
 
// Function to find if interaction outside group
vector<int>
peoplesInteractionCheck(vector<vector<int> > initialGroups,
                        vector<vector<int> > finalGroups,
                        bool strictEqual)
{
    vector<int> result;
    unordered_map<int, int> initialPersonToGroupIdxMap
        = getPersonToGroupIdxMap(initialGroups);
 
    for (auto groupInFinal : finalGroups) {
        int person = groupInFinal[0];
 
        int initialGroupIdx
            = initialPersonToGroupIdxMap[person];
        vector<int> groupInInitial
            = initialGroups[initialGroupIdx];
 
        bool isSubsetOrEqualResult = isSubsetOrEqual(
            groupInInitial, groupInFinal, strictEqual);
 
        // For equal case, add in result
        // if groups are not equal.
        if (strictEqual && !isSubsetOrEqualResult) {
            appendVector(result, groupInFinal);
        }
 
        // For subset case, add in result
        // if groups are subset or equal.
        if (!strictEqual && isSubsetOrEqualResult) {
            appendVector(result, groupInFinal);
        }
    }
 
    return result;
}
 
// Driver code
int main()
{
    vector<vector<int> > initialGroups{ { 1, 3, 8 },
                                        { 2, 5 },
                                        { 4 },
                                        { 9, 6 },
                                        { 7, 10, 11, 12 } };
    vector<vector<int> > finalGroups{ { 1, 3 }, { 9 }, { 8 }, { 12, 11 }, { 7, 6 }, { 2, 5 }, { 4, 10 } };
 
    vector<int> peopleWithNoOutsideInteractions
        = peoplesInteractionCheck(initialGroups,
                                  finalGroups, false);
    cout << "Elements with no outside interactions\n";
    printVector(peopleWithNoOutsideInteractions);
 
    vector<int> peopleWhoSwitchedGroups
        = peoplesInteractionCheck(initialGroups,
                                  finalGroups, true);
    cout << "Elements that changed their groups\n";
    printVector(peopleWhoSwitchedGroups);
    return 0;
}


Java




// Java code for the above approach:
import java.util.*;
 
class Main
{
 
  // Driver code
  public static void main(String[] args)
  {
    List<List<Integer> > initialGroups
      = new ArrayList<>();
    initialGroups.add(Arrays.asList(1, 3, 8));
    initialGroups.add(Arrays.asList(2, 5));
    initialGroups.add(Arrays.asList(4));
    initialGroups.add(Arrays.asList(9, 6));
    initialGroups.add(Arrays.asList(7, 10, 11, 12));
 
    List<List<Integer> > finalGroups
      = new ArrayList<>();
    finalGroups.add(Arrays.asList(1, 3));
    finalGroups.add(Arrays.asList(9));
    finalGroups.add(Arrays.asList(8));
    finalGroups.add(Arrays.asList(12, 11));
    finalGroups.add(Arrays.asList(7, 6));
    finalGroups.add(Arrays.asList(2, 5));
    finalGroups.add(Arrays.asList(4, 10));
 
    List<Integer> peopleWithNoOutsideInteractions
      = peoplesInteractionCheck(initialGroups,
                                finalGroups, false);
    System.out.println(
      "Elements with no outside interactions");
    printVector(peopleWithNoOutsideInteractions);
    List<Integer> peopleWhoSwitchedGroups
      = peoplesInteractionCheck(initialGroups,
                                finalGroups, true);
    System.out.println(
      "Elements that changed their groups");
    printVector(peopleWhoSwitchedGroups);
  }
 
  // Function to print vector elements
  private static void printVector(List<Integer> vec)
  {
    for (int value : vec) {
      System.out.print(value + " ");
    }
    System.out.println();
  }
 
  // Function to check if one is subset of other
  // or they are equal
  private static boolean
    isSubsetOrEqual(List<Integer> parent,
                    List<Integer> child,
                    boolean strictEqual)
  {
    if (strictEqual ? child.size() != parent.size()
        : child.size() > parent.size()) {
      return false;
    }
    Set<Integer> hashset = new HashSet<>(parent);
    for (int item : child) {
      if (!hashset.contains(item))
        return false;
    }
    return true;
  }
 
  // Function to assign the groups of elements
  private static Map<Integer, Integer>
    getPersonToGroupIdxMap(List<List<Integer> > groups)
  {
    Map<Integer, Integer> personToGroupIdxMap
      = new HashMap<>();
    int groupIdx = 0;
    for (List<Integer> group : groups) {
      for (int person : group) {
        personToGroupIdxMap.put(person, groupIdx++);
      }
    }
    return personToGroupIdxMap;
  }
 
  // Function to find if interaction outside group
  private static List<Integer> peoplesInteractionCheck(
    List<List<Integer> > initialGroups,
    List<List<Integer> > finalGroups,
    boolean strictEqual)
  {
    List<Integer> result = new ArrayList<>();
    Map<Integer, Integer> initialPersonToGroupIdxMap
      = getPersonToGroupIdxMap(initialGroups);
    for (List<Integer> groupInFinal : finalGroups) {
      int person = groupInFinal.get(0);
      int initialGroupIdx
        = initialPersonToGroupIdxMap.get(person);
 
      List<Integer> groupInInitial
        = new ArrayList<>();
      for (List<Integer> g : initialGroups) {
        if ((g).contains((person)))
          groupInInitial = g;
      }
      boolean isSubsetOrEqualResult = isSubsetOrEqual(
        groupInInitial, groupInFinal, strictEqual);
 
      if (strictEqual && !isSubsetOrEqualResult) {
        result.addAll(groupInFinal);
      }
      if (!strictEqual && isSubsetOrEqualResult) {
        result.addAll(groupInFinal);
      }
    }
    return result;
  }
}
 
// This code is contribtued by Tapesh(tapeshdua420)


Python3




# python3 code for the above approach:
 
# Function to print vector elements
def printVector(vec):
 
    for value in vec:
        print(value, end=" ")
 
    print()
 
 
# Function to check if one is subset of other
# or they are equal
def isSubsetOrEqual(parent, child, strictEqual):
 
    # Check for size equality
    if (len(child) != len(parent) if strictEqual
            else len(child) > len(parent)):
        return False
 
    # Initializing a hash set
    hashset = set()
    for item in parent:
        hashset.add(item)
 
    for item in child:
        if (not(item in hashset)):
            return False
 
    return True
 
 
# Function to append vector
def appendVector(result, values):
 
    for value in values:
        result.append(value)
 
 
# Function to assign the groups of elements
def getPersonToGroupIdxMap(groups):
 
    personToGroupIdxMap = {}
    for groupIdx in range(0, len(groups)):
        for person in groups[groupIdx]:
            personToGroupIdxMap[person] = groupIdx
 
    return personToGroupIdxMap
 
 
# Function to find if interaction outside group
def peoplesInteractionCheck(initialGroups, finalGroups, strictEqual):
 
    result = []
    initialPersonToGroupIdxMap = getPersonToGroupIdxMap(initialGroups)
 
    for groupInFinal in finalGroups:
        person = groupInFinal[0]
 
        initialGroupIdx = initialPersonToGroupIdxMap[person]
        groupInInitial = initialGroups[initialGroupIdx]
 
        isSubsetOrEqualResult = isSubsetOrEqual(
            groupInInitial, groupInFinal, strictEqual)
 
        # For equal case, add in result
        # if groups are not equal.
        if (strictEqual and (not isSubsetOrEqualResult)):
            appendVector(result, groupInFinal)
 
        # For subset case, add in result
        # if groups are subset or equal.
        if ((not strictEqual) and isSubsetOrEqualResult):
            appendVector(result, groupInFinal)
 
    return result
 
 
# Driver code
if __name__ == "__main__":
 
    initialGroups = [[1, 3, 8],
                     [2, 5],
                     [4],
                     [9, 6],
                     [7, 10, 11, 12]]
 
    finalGroups = [[1, 3], [9], [8], [12, 11], [7, 6], [2, 5], [4, 10]]
 
    peopleWithNoOutsideInteractions = peoplesInteractionCheck(
        initialGroups, finalGroups, False)
 
    print("Elements with no outside interactions")
    printVector(peopleWithNoOutsideInteractions)
    peopleWhoSwitchedGroups = peoplesInteractionCheck(
        initialGroups, finalGroups, True)
    print("Elements that changed their groups")
    printVector(peopleWhoSwitchedGroups)
 
    # This code is contributed by rakeshsahni


Javascript




// JavaScript code for the above approach:
 
 
// Function to print vector elements
function printVector(vec)
{
    for (var value of vec) {
        process.stdout.write(value + " ");
    }
    process.stdout.write("\n");
}
 
// Function to check if one is subset of other
// or they are equal
function isSubsetOrEqual(parent, child, strictEqual)
{
    // Check for size equality
    if (strictEqual ? child.length != parent.length
                    : child.length > parent.length) {
        return false;
    }
 
    // Initializing a hash set
    let hashset = new Set();
    for (var item of parent) {
        hashset.add(item);
    }
 
    for (var item of child) {
        if (!hashset.has(item))
            return false;
    }
    return true;
}
 
// Function to append vector
function appendVector(result, values)
{
    result.push(...values)
}
 
// Function to assign the groups of elements
function getPersonToGroupIdxMap(groups)
{
    let personToGroupIdxMap = {};
    for (var groupIdx = 0; groupIdx < groups.length;
         groupIdx++) {
        for (var person of groups[groupIdx]) {
            personToGroupIdxMap[person] = groupIdx;
        }
    }
    return personToGroupIdxMap;
}
 
// Function to find if interaction outside group
function peoplesInteractionCheck(initialGroups, finalGroups,  strictEqual)
{
    let result = [];
    let initialPersonToGroupIdxMap
        = getPersonToGroupIdxMap(initialGroups);
 
    for (var groupInFinal of finalGroups) {
        let person = groupInFinal[0];
 
        let initialGroupIdx
            = initialPersonToGroupIdxMap[person];
        let groupInInitial
            = initialGroups[initialGroupIdx];
 
        let isSubsetOrEqualResult = isSubsetOrEqual(
            groupInInitial, groupInFinal, strictEqual);
 
        // For equal case, add in result
        // if groups are not equal.
        if (strictEqual && !isSubsetOrEqualResult) {
            appendVector(result, groupInFinal);
        }
 
        // For subset case, add in result
        // if groups are subset or equal.
        if (!strictEqual && isSubsetOrEqualResult) {
            appendVector(result, groupInFinal);
        }
    }
 
    return result;
}
 
// Driver code
let initialGroups = [ [ 1, 3, 8 ],
                                        [ 2, 5 ],
                                        [ 4 ],
                                        [ 9, 6 ],
                                        [ 7, 10, 11, 12 ] ];
let finalGroups = [[ 1, 3 ], [ 9 ], [ 8 ], [ 12, 11 ], [ 7, 6 ], [ 2, 5 ], [ 4, 10 ]];
 
let peopleWithNoOutsideInteractions
        = peoplesInteractionCheck(initialGroups,
                                  finalGroups, false);
console.log("Elements with no outside interactions");
    printVector(peopleWithNoOutsideInteractions);
 
let peopleWhoSwitchedGroups
        = peoplesInteractionCheck(initialGroups,
                                  finalGroups, true);
console.log("Elements that changed their groups");
printVector(peopleWhoSwitchedGroups);
 
 
// This code is contributed by phasing17


Output

Elements with no outside interactions
1 3 9 8 12 11 2 5 
Elements that changed their groups
1 3 9 8 12 11 7 6 4 10 

Time complexity: O(N * k)
Auxiliary Space: O(N * k)


My Personal Notes arrow_drop_up
Recommended Articles
Page :

Start Your Coding Journey Now!