zoukankan      html  css  js  c++  java
  • 算法之回溯和随机

    算法之回溯

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

    技巧就是只有一个临时变量,只有当临时变量是目标 值的时候才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;
        }
    }
  • 相关阅读:
    博客园
    未释放的已删除文件
    ssh连接缓慢
    剑指 Offer 38. 字符串的排列
    剑指 Offer 37. 序列化二叉树
    剑指 Offer 50. 第一个只出现一次的字符
    剑指 Offer 36. 二叉搜索树与双向链表
    剑指 Offer 35. 复杂链表的复制
    剑指 Offer 34. 二叉树中和为某一值的路径
    剑指 Offer 33. 二叉搜索树的后序遍历序列
  • 原文地址:https://www.cnblogs.com/lsfv/p/10514875.html
Copyright © 2011-2022 走看看