简体   繁体   English

使用DFS查找一组字符串

[英]Find a set of strings with DFS

We have a self-defined data structure have the following attributes: id, a list of id it has access to(can be empty), string(can be empty) 我们有一个具有以下属性的自定义数据结构:id,它可以访问的id列表(可以为空),字符串(可以为空)

eg 例如

“Thomas” [“Donald”, “Barbara”] “a”
“Donald” [“Sarah”, “Lisa”] “”
“Lisa” [] “c”
“Sarah” [“Lisa”, “Thomas”, “Barbara”] “d”
“Barbara” [“Sarah”] “e”

Given a start id “Donald” , and target string set we are trying to collect is [“a”, “c”, “d”] , list all possible ways to visit all strings in target set. 给定一个起始ID “Donald” ,我们尝试收集的目标字符串集为[“a”, “c”, “d”] ,列出访问目标集中所有字符串的所有可能方式。 Every time we try to access an item through id, we need to make sure this id is valid. 每次我们尝试通过ID访问商品时,都需要确保此ID有效。 For the example given above, one possible path is [[“Donald”], [“Sarah”, “d”], [“Thomas”, “a”], [“Donald”], [“Lisa”, “c”]] . 对于上面给出的示例,一个可能的路径是[[“Donald”], [“Sarah”, “d”], [“Thomas”, “a”], [“Donald”], [“Lisa”, “c”]]

Another example, Given a start id "Sarah" , and target string set we are trying to collect is [“a”, “d”], one possible path is [["Sarah", "d"], ["Thomas", "a"]] . 另一个例子,给定一个起始id "Sarah" ,并且我们要收集的目标字符串集是[“ a”,“ d”],一个可能的路径是[["Sarah", "d"], ["Thomas", "a"]]

Here is how I try to address this problem. 这是我尝试解决此问题的方法。 Since the database could be very large, I store all the variable as in HashMap as a class variable. 由于数据库可能非常大,因此像HashMap一样,我将所有变量都存储为类变量。 Then use DFS to search for the list of target strings. 然后使用DFS搜索目标字符串列表。

Every time it searches the current item and also all the items in idList, if a match is found add this item to path, until it finds all string in targets. 每次搜索当前项目以及idList中的所有项目时,如果找到匹配项,则将该项目添加到路径中,直到在目标中找到所有字符串为止。 The process is done recursively. 该过程是递归完成的。

However, this isn't a typical DFS, cause the list it's trying to traverse is different every time, also, the first item should always be added to path no matter what. 但是,这不是典型的DFS,因为每次尝试遍历的列表都是不同的,而且无论如何都应始终将第一项添加到路径中。 That's why I get stuck. 这就是为什么我被卡住。

I made a careless mistake in the code, thanks @Mil4n for pointing it out. 我在代码中犯了一个粗心的错误,感谢@ Mil4n指出来。 Here is modified code: 这是修改后的代码:

import java.util.*;


public class TestFinder {
    Map<String, Item> map = new HashMap<String, Item>();


    public void finder(List<String> targets, String startid){
        List<List<String>> path = new ArrayList<List<String>>();
        List<List<List<String>>> result = new ArrayList<List<List<String>>>();

        dfs(startid, targets, path, result);

        // print out result
        System.out.println(result.size());
        for(int i=0; i<result.size(); i++){
            for(int j=0; j<result.get(i).size(); j++){
                for(int k=0; k<result.get(i).get(j).size(); k++){
                    System.out.println(result.get(i).get(j).get(k) + " ");
                }

            }
            System.out.println();
        }
    }

    public void dfs(String id, List<String> targets, List<List<String>> path, List<List<List<String>>> pathList){
        if(targets.size() == 0){
            pathList.add(new ArrayList<List<String>>(path));
            return;
        }

        if(!map.containsKey(id)){
            System.out.println("This is doesn't exist!");
            return;
        }

        List<String> list = new ArrayList<String>();
        list.add(id); // add current item id to the head of list
        list.addAll(map.get(id).idList);

        int size = list.size();
        for(int i=0; i<size; i++){

            if(i==0){
                Item cur = map.get(list.get(i));
                List<String> l = new ArrayList<String>();
                l.add(cur.id);
                if(targets.contains(cur.str)){
                    l.add(cur.str);
                    targets.remove(cur.str);
                }
                path.add(l);
            }
            // else if i is greater than 0, set this id in idList as visited by removing it from idList
            else if(map.containsKey(list.get(i))){
                System.out.println("i is greater than 0");
                Item curTemp = map.get(list.get(i));
                List<String> idListTemp = curTemp.idList;
                idListTemp.remove(list.get(i));
                map.remove(id);
                map.put(curTemp.id, new Item(curTemp.id, idListTemp, curTemp.str));

                List<String> l = new ArrayList<String>();
                l.add(map.get(curTemp.id).id);
                if(targets.contains(map.get(curTemp.id).str)){
                    l.add(map.get(curTemp.id).str);
                    targets.remove(map.get(curTemp.id).str);
                }
                path.add(l);
                if(i<size-1){
                    dfs(list.get(i+1), targets, path, pathList);
                    path.remove(path.size()-1);
                }

            }

        } // end for







    }

    public void buildInput(){
        List<String> temp1 = new ArrayList<String>();
        temp1.add("Donald");
        temp1.add("Barbara");
        Item it1 = new Item("Thomas", temp1, "a");
        map.put("Thomas", it1);

        List<String> temp2 = new ArrayList<String>();
        temp2.add("Sarah");
        temp2.add("Lisa");
        Item it2 = new Item("Donald", temp2, "");
        map.put("Donald", it2);


        List<String> temp3 = new ArrayList<String>();
        Item it3 = new Item("Lisa", temp3, "c");
        map.put("Lisa", it3);


        List<String> temp4 = new ArrayList<String>();
        temp4.add("Lisa");
        temp4.add("Thomas");
        temp4.add("Barbara");
        Item it4 = new Item("Sarah", temp4, "d");
        map.put("Sarah", it4);

        List<String> temp5 = new ArrayList<String>();
        temp5.add("Sarah");
        Item it5 = new Item("Barbara", temp5, "e");
        map.put("Barbara", it5);
    }

    public static void main(String[] args) {
        TestFinder tf = new TestFinder();
        tf.buildInput();

        List<String> targets = new ArrayList<String>();
        targets.add("a");
        targets.add("c");
        targets.add("d");
        tf.finder(targets, "Donald");

    }    
}

class Item{
    String id;
    List<String> idList;
    String str;


    Item(String i, List<String> il, String s){
        id = i;
        idList = il;
        str = s;
    }

}

However, now the result is empty, it couldn't list any sequence of items that can get target strings, which is obviously untrue for current situation. 但是,现在的结果为空,它无法列出可以获取目标字符串的任何项目序列,这对于当前情况显然是不正确的。

I kinda got stuck here, I know there might something with my depth first search logic. 我有点卡在这里,我知道深度优先搜索逻辑可能会有所帮助。 Any inputs would be highly appreciated! 任何输入将不胜感激! Thank you. 谢谢。

(1) you else if block is incorrect (assuming that you don't have cyclical references) (1)如果块不正确,则返回其他(假设您没有循环引用)

before your first pass through for loop your list look like this: [Donald, Sarah, Lisa] once you iterator reaches i = 1 (Sarah) in the else if condition condition you check if Sarah has access to Sarah which will return false! 在第一次通过for循环之前for您的列表如下所示:[Donald,Sarah,Lisa]一旦迭代器在else条件条件下达到i = 1(Sarah),您就会检查Sarah是否可以访问Sarah,并返回false!

(2) this will not put current item on the head of the list: (2)这不会将当前项目放在列表的开头:

    List<String> list = new ArrayList<String>();
    list.add(id); // add current item id to the head of list

This will: 这将:

    List<String> list = new ArrayList<String>();
    list.add(id); // add current item id to the head of list
    list.addAll(map.get(id).idList);

(3) if you want to iterate through all items it should be i < size (or i <= size-1) (3)如果要遍历所有项目,则应为i <size(或i <= size-1)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM