public ArrayList<ArrayList<String>> findLadders(String start, String end, HashSet<String> dic) {
        //result stores the final return value
        ArrayList<ArrayList<String>> result = new ArrayList<ArrayList<String>>();
        dic.remove(start);
        dic.add(end);
        //queue stores the stacks which hold the word ladders
        Queue<Stack<String>> queue = new LinkedList<Stack<String>>();
        Stack<String> stack = new Stack<String>();
        String compare = null;
        stack.push(start);
        queue.add(stack);

        ArrayList<String> removeCollection = new ArrayList<String>();
        ArrayList<String> usedCollection = new ArrayList<String>();
        int preLength = 1;
        while(!queue.isEmpty()){
            Stack<String>  stack1 = queue.poll();
            compare = stack1.peek();
            if(compare.equals(end)){
                if((result.isEmpty() || stack1.size() == result.get(0).size())){
                    ArrayList<String> arrayList = new ArrayList<String>(stack1);
                    result.add(arrayList);
                    continue;
                }
                else
                    break;
            }
/*
*
* Because the same word could be used multiple times in the same layer, but it shouldn't appear in later layers
* So the we create a collection collecting words from the same layer. And remove the collection from dictionary once
* the layer creation is over.
*
* */
            //when handle another layer
            int currentLength = stack1.size();
            if(currentLength > preLength){
                preLength = currentLength;
                for(String item: removeCollection){
                    dic.remove(item);
                }
                removeCollection.clear();
            }

            int stringLength = compare.length();

            String createString;
            for(int i = 0; i < stringLength; i++){
                char [] arr = compare.toCharArray();
                for(char c = 'a'; c < 'z'; c++){
                    arr[i] = c;
                    createString = new String(arr);
                    if(dic.contains(createString)){
                        Stack<String> tempStack = new Stack<String>();
                        tempStack.addAll(stack1);
                        tempStack.add(createString);
                        queue.add(tempStack);
                        removeCollection.add(createString);
                    }
                }
            }
        }
        return result;
    }