算法之回溯和随机

算法之回溯

精髓就是想象一个蜗牛的角,碰到危险回退回去,再换个方向试探,一般深度尽量用递归做,别怕,递归思想才是王道。

技巧就是只有一个临时变量,只有当临时变量是目标 值的时候才new出来,插到总结果当中去。否则看正规代码时,会卡壳。

 

 

自己总结的书写规则,基本上套用是没有问题的。
//参数:下一深度,深度选择和总深度,临时数据,结果
//1.1 符合结果的断枝:把临时数据新创建一份,加入到结果中。
//1.2 看看是否还有任何其他不符合断枝情况。
//2.1 不断枝情况:是否需要处理下0深度。 
//2.2 列出所有分支,并每次进行回退。
//非重复的组合,一个深度只出现一个元素,那么可以保证组合中不重复元素,至于怎么分支看情况。

 

 

//按键组合。

class Solution 
{
    //考察深度优先
    private Map<Character,List<Character>> mapchar;

    public List<String> letterCombinations(String digits) 
    {
        initlist();
        List<String> res=new  ArrayList<String>();
        
        if(digits.length()==0)
        {
            return res;
        }
        else
        {
            StringBuilder explorer=new StringBuilder();
            DFS(0,digits,explorer,res);
            return res;
        }
    }
    
    //参数:下一深度,深度选择和总深度,临时数据,结果
    //1 断枝:超过最大深度或无效情况,把临时数据新创建一份,加入到结果中。
    //2.1 是否需要处理下0深度。 
    //2.2 列出所有分支,并每次进行回退。
    private void DFS(int depth,String digits,StringBuilder explorer,List<String> res)
    {
        if(depth>digits.length())//1 断枝:超过最大深度或无效情况
        {
            res.add(explorer.toString());
        }
        else if(depth<=digits.length())
        {
            if(depth==0)//2.1 是否需要处理下0深度
            {
                DFS(1,digits,explorer,res);
            }
            else
            {
                List<Character> allChar=getList(digits.charAt(depth-1));
                for(int i=0;i<allChar.size();i++)//2.2 列出所有分支,并每次进行回退。
                {
                    explorer.append(allChar.get(i));
                    DFS(depth+1,digits,explorer,res);
                    explorer.delete(explorer.length()-1,explorer.length());
                }
            }
        }
    }
    
    private List<Character> getList(char a)
    {
        return mapchar.get(a);
    }
    
    private void initlist()
    {
        mapchar=new HashMap();
        
        List<Character> list2= new ArrayList<Character>();
        list2.add('a');
        list2.add('b');
        list2.add('c');
        mapchar.put('2',list2);
        
        List<Character> list3= new ArrayList<Character>();
            list3.add('d');
            list3.add('e');
            list3.add('f');
        mapchar.put('3',list3);
        

        List<Character> list4= new ArrayList<Character>();
        list4.add('g');
        list4.add('h');
        list4.add('i');
        mapchar.put('4',list4);
        
    List<Character> list5= new ArrayList<Character>();
            list5.add('j');
            list5.add('k');
            list5.add('l');
        mapchar.put('5',list5);
        
        List<Character> list6= new ArrayList<Character>();
list6.add('m');
            list6.add('n');
            list6.add('o');
        mapchar.put('6',list6);
        
        List<Character> list7= new ArrayList<Character>();
            list7.add('p');
            list7.add('q');
            list7.add('r');
            list7.add('s');
        mapchar.put('7',list7);
        
        List<Character> list8= new ArrayList<Character>();
            list8.add('t');
            list8.add('u');
            list8.add('v');
        mapchar.put('8',list8);
        
        
        List<Character> list9= new ArrayList<Character>();
            list9.add('w');
            list9.add('x');
            list9.add('y');
            list9.add('z');
        mapchar.put('9',list9);
        

    }
}

 

 

 

class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) 
    {
        Arrays.sort(candidates);
        List<Integer> explorer=new LinkedList<Integer>();
        
        List<List<Integer>> res=new ArrayList<List<Integer>>();
        
        dfs(0,candidates,explorer,0,target,res);
        
        return res;
    }
    
    
    //参数:下一深度,深度选择和总深度,临时数据,结果
    //1.1 断枝:下次深度刚刚比最大大一,且符合结果,把临时数据新创建一份,加入到结果中。
    //1.2 看看是否还有任何其他断枝情况。
    //2.1 不断枝情况:是否需要处理下0深度。 
    //2.2 列出所有分支,并每次进行回退。
    private void dfs(int depth,int[] candidates,List<Integer> explorer,int explorerSum,int target,List<List<Integer>> res)
    {
        if(depth<=candidates.length+1 && explorerSum==target)//1 断枝:超过最大深度或无效情况,把临时数据新创建一份,加入到结果中.这里断枝加数据还需要检测
        {
            if(!Check(explorer,res))
            {
                res.add(new ArrayList<Integer>(explorer));
            }
        }
        else if(depth>candidates.length+1 || explorerSum>target)//1 断枝:超过最大深度或无效情况,把临时数据新创建一份,加入到结果中.这里断枝加数据还需要检测
        {
            
        }
        else if(depth<candidates.length+1)//2.2 列出所有分支,并每次进行回退。这里任何分支都有可能断指。
        {
            if(depth==0)
            {
                dfs(1,candidates,explorer,0,target,res);
            }
            else
            {
                explorer.add(candidates[depth-1]);
                dfs(depth+1,candidates,explorer,explorerSum+candidates[depth-1],target,res);
                explorer.remove(explorer.size()-1);
                dfs(depth+1,candidates,explorer,explorerSum,target,res);
            }
        }
    }
    
    private boolean Check(List<Integer> explorer,List<List<Integer>> res)
    {
        boolean check=false;
        
        List<Integer> explorer2=new ArrayList<Integer>(explorer);
        Collections.sort(explorer2);
        
        
        for(int i=0;i<res.size();i++)
        {
            List<Integer> cc2=new ArrayList<Integer>(res.get(i));
            Collections.sort(cc2);
            
            if(cc2.size()==explorer2.size())
            {
                int k=0;
                for(k=0;k<cc2.size();k++)
                {
                    if(cc2.get(k)!=explorer2.get(k))
                    {
                        break;
                    }
                }
                if(k==res.get(i).size())
                {
                    check=true;
                    break;
                }
            }
        }
        return check;
    }
}

 

posted @ 2019-03-12 10:10  琴鸟  阅读(220)  评论(0编辑  收藏  举报