I have a Map, that can have keys: A, B, C, D, E, F
or the subset of it
In which, A, B, C and D
are a group of strings that belong to a certain hierarchy in the same order: A -> B -> C -> D
I need to check in the HashMap
if the map contains a valid hierarchy. Doesn't matter in which order map stores data. I don't care about the order and I am not checking the order inside the map.
If the map contains either, it is considered a valid hierarchy:
A or
A, B or // A and B can be in any order
A, B, E or // as E is not in the group, so doesn't matter
A, B, C or // these can be in any order in map.
A, B, C, D or
If map
has A, B, and D
but not C
, it will be considered invalid.
I can add multiple if else
check, but this will make code messy. Is there any elegant way of doing this check?
Edit: I have implemented below logic:
// order contains strings in order: { A, B, C, D}
private boolean isHierarchyComplete(Map<String, Object> map, String[] order) {
// lastIndexFound, this will give the last index of string found in hierarchy that is continous and breaks out once the path is broken
int lastIndexFound = -1;
for (String str : order) {
if (map.containsKey(str)) {
lastIndexFound++;
} else {
break;
}
}
// if nothing found from path
if (lastIndexFound == -1) {
return false;
}
// if all found from path
if (lastIndexFound == order.length - 1) {
return true;
}
// now check after lastIndexFound if there are any values from hierarchy,
// if present return false
for (int index = lastIndexFound + 1; index < order.length; index++) {
if (map.containsKey(order[index])) {
return false;
}
}
return true;
}
I think the problem can be solved in the following way (a working demonstration),
import java.util.HashMap;
public class MyClass {
public static void main(String args[]) {
String[] hierarchy = {"A","B","C","D"};
//Test case 1: false
HashMap<String,String> map = new HashMap<String,String>();
map.put("A","#");
map.put("D","#");
isValidMap(map,hierarchy);
map = new HashMap<String,String>();
//Test case 2: true
map = new HashMap<String,String>();
map.put("A","#");
map.put("B","#");
isValidMap(map,hierarchy);
map = new HashMap<String,String>();
//Test case 3: true
map = new HashMap<String,String>();
map.put("E","#");
map.put("F","#");
isValidMap(map,hierarchy);
map = new HashMap<String,String>();
//Test case 4: true
map = new HashMap<String,String>();
map.put("A","#");
map.put("E","#");
isValidMap(map,hierarchy);
map = new HashMap<String,String>();
//Test case 5: true
map = new HashMap<String,String>();
map.put("A","#");
map.put("B","#");
map.put("C","#");
isValidMap(map,hierarchy);
map = new HashMap<String,String>();
//Test case 6: true
map = new HashMap<String,String>();
map.put("A","#");
map.put("B","#");
map.put("E","#");
isValidMap(map,hierarchy);
map = new HashMap<String,String>();
//Test case 7: false
map = new HashMap<String,String>();
map.put("A","#");
map.put("D","#");
map.put("E","#");
isValidMap(map,hierarchy);
map = new HashMap<String,String>();
}
public static void isValidMap(HashMap<String,String> map, String[] hierarchy){
boolean checkShouldBePresent = true;
boolean finalAns = true;
boolean changed = false;
boolean checked = false;
for(int i=0;i<hierarchy.length;i++){
String s = hierarchy[i];
boolean finalAnsPrev = finalAns;
finalAns = finalAns && !changed?map.keySet().contains(s):!map.keySet().contains(s);
if(finalAnsPrev!=finalAns && !checked){
changed = true;
finalAns = true;
checked = true;
}
}
System.out.println(finalAns);
}
}
the main logic above is in the isValidMap
method.
Explanation:
The logic for solving the problem is as follows,
We should traverse the hierarchy elements one by one starting from the top and check if it is present in the given map
keyset. The moment when we find one of the elements in the hierarchy is missing in the map, all the following elements should not be present as well.
For example,
String[] hierarchy = {"A","B","C","D"};
//keyset = set of {"A", "B", "E"}. The truth list of the hierarchy elements pertaining to whether they are present in the keyset or not is,
[A:TRUE,B:TRUE,C:FALSE,D:FALSE] ... (1)
//keyset = set of {"G", "F", "E"}. The truth list of the hierarchy elements pertaining to whether they are present in the keyset or not is,
[A:FALSE,B:FALSE,C:FALSE,D:FALSE]. ... (2)
//keyset = set of {"A", "B", "D"}. The truth list of the hierarchy elements pertaining to whether they are present in the keyset or not is,
[A:TRUE,B:TRUE,C:FALSE,D:TRUE]. ... (3)
In example (3) above, notice how there is a change in truth values from TRUE to FALSE and then again to TRUE. In all such cases, we would say that the map keyset does not obey our hierarchy.
The time complexity should also be O(n)
where n is the length of the hierarchy array.