0
点赞
收藏
分享

微信扫一扫

算法训练——回溯算法(LeetCodeHOT100)


摘要

主要是的分析介绍leetcode中的算法题目。

一、回溯算法总结:

总结:子集、组合类问题,关键是用一个 start 参数来控制选择列表!!最后回溯六步走:

1、画出递归树,找到状态变量(回溯函数的参数),这一步非常重要※

2、根据题意,确立结束条件

3、找准选择列表(与函数参数相关),与第一步紧密关联※

4、判断是否需要剪枝

5、作出选择,递归调用,进入下一层

6、撤销选择

二、算法练习

剑指 Offer II 087. 复原 IP 

算法训练——回溯算法(LeetCodeHOT100)_回溯算法

 

package 回溯算法;

import java.util.ArrayList;
import java.util.List;

public class restoreIpAddressesV2 {

    public List<String> restoreIpAddressesV2(String s) {
        int count = 4;
        int[] segment = new int[count];
        List<String> list = new ArrayList<>();
        int segid = 0;
        int index = 0;
        dfsv2(s, segid, index, segment, list, count);
        return list;
    }

    private void dfsv2(String s, int segid, int index, int[] segment, List<String> list, int count) {
        //如果是segid=4 && index=s.lenegth
        if (segid == count) {
            if (index == s.length()) {
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < count; i++) {
                    sb.append(segment[i]);
                    if (i != count - 1) {
                        sb.append('.');
                    }
                }
                list.add(sb.toString());
            }
            return;
        }
        // 当遍历完成了就返回
        if (index == s.length()) {
            return;
        }
        // 当该数字为0的时候
        if (s.charAt(index) == '0') {
            segment[segid] = 0;
            dfsv2(s, segid + 1, index + 1, segment, list, count);
        }
        int num = 0;
        for (int i = index; i < s.length(); i++) {
            num = num * 10 + (s.charAt(i) - '0');
            // 不能等于0
            if (num > 0 && num <= 255) {
                segment[segid] = num;
                dfsv2(s, segid + 1, i + 1, segment, list, count);
            }else {
                break;
            }
        }
    }
}

78. 子集

算法训练——回溯算法(LeetCodeHOT100)_回溯算法_02

public List<List<Integer>> subsets(int[] nums) {
        List<List<Integer>> lists=new ArrayList<>();
        //先添加一个空的集合
        lists.add(new ArrayList<>());
        for (int num:nums) {
            //每遍历一个元素就在之前子集中的每个集合追加这个元素,让他变成新的子集
            for (int i=0,j=lists.size();i<j;i++){
                List<Integer> list=new ArrayList<>(lists.get(i));
                list.add(num);
                lists.add(list);
            }
        }
        return lists;
    }
}

第二中就判断子集的长度来判断

class Solution {
    public List<List<Integer>> subsets(int[] nums) {
         List<List<Integer>> lists = new ArrayList<>();
        List<Integer> list = new ArrayList<>();
        boolean[] vis = new boolean[nums.length];
        for (int i = 0; i <= nums.length; i++) {
            dfs(nums, 0, i, vis, list, lists);
        }
        return lists;
    }
    private void dfs(int[] nums, int index, int length, boolean[] vis, List<Integer> list, List<List<Integer>> lists) {
        if (list.size() == length) {
            ArrayList<Integer> tmp=new ArrayList<>();
            for (int i:list){
                tmp.add(i);
            }
            Collections.sort(tmp);
            // 排序导致有错误
            if (!lists.contains(tmp)){
                // 这里需要排查在(0,1)(1,0)的两个元素
                lists.add(new ArrayList<>(tmp));
                return;
            }else {
                tmp.clear();
            }
        }
        for (int i = index; i < nums.length; i++) {
            if (!vis[i]) {
                vis[i] = true;
                list.add(nums[i]);
                dfs(nums, index + 1, length, vis, list, lists);
                list.remove(list.size() - 1);
                vis[i] = false;
            }
        }
    }
}

算法训练——回溯算法(LeetCodeHOT100)_算法_03

package 回溯算法;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;

public class subsets78V2 {
    

    public List<List<Integer>> subsets(int[] nums) {
        int len = nums.length;
        List<List<Integer>> res=new ArrayList<>();
        if (len==0){
            return  res;
        }
        Deque<Integer> path=new ArrayDeque<>();

        dfs(nums,len,0,path,res);
        return res;
    }

    private void dfs(int[] nums, int len, int index, Deque<Integer> path, List<List<Integer>> res) {
        if (len==index){
            res.add(new ArrayList<>(path));
            return;
        }
        // 不选择这个元素
        dfs(nums,len,index+1,path,res);
        //选择这个元素
        path.addLast(nums[index]);
        dfs(nums,len,index+1,path,res);
        //回溯算法
        path.removeLast();
    }

    private void dfs2(int[] nums, int len, int index, Deque<Integer> path, List<List<Integer>> res) {
        if (len==index){
            res.add(new ArrayList<>(path));
            return;
        }
        //选择这个元素
        path.addLast(nums[index]);
        dfs2(nums,len,index+1,path,res);
        //回溯算法
        path.removeLast();
        // 不选择这个元素
        dfs2(nums,len,index+1,path,res);
    }
}

17. 电话号码的字母组合

算法训练——回溯算法(LeetCodeHOT100)_List_04

List<String> list = new ArrayList<>();

    HashMap<Character, String> map1 = new HashMap<>();

    public List<String> letterCombinations3(String digits) {
        map1.put('2',"abc");
        map1.put('3', "def");
        map1.put('4', "ghi");
        map1.put('5', "jkl");
        map1.put('6', "mno");
        map1.put('7', "pqrs");
        map1.put('8', "tuv");
        map1.put('9', "wxyz");
        if (digits.length() == 0) {
            return list;
        }
        dfs(digits, 0, new StringBuilder());
        return list;
    }

    private void dfs(String digits, int index, StringBuilder path) {
        if (path.length() == digits.length()) {
            list.add(path.toString());
            return;
        }
        String s = map1.get(digits.charAt(index));
        for (int i = 0; i < s.length(); i++) {
            path.append(s.charAt(i));
            dfs(digits,index+1,path);
            path.deleteCharAt(path.length()-1);
        }
    }

 22. 括号生成

算法训练——回溯算法(LeetCodeHOT100)_List_05

算法训练——回溯算法(LeetCodeHOT100)_算法_06

package 回溯算法;

import java.util.ArrayList;
import java.util.List;

public class generateParenthesis22 {

    public List<String> generateParenthesis(int n) {
        List<String> ans = new ArrayList<String>();
        backtrack(ans, new StringBuilder(), 0, 0, n);
        return ans;
    }
    
    public void backtrack(List<String> ans, StringBuilder cur, int left, int right, int max) {
        // 判断终止条件
        if (cur.length() == max * 2) {
            ans.add(cur.toString());
            return;
        }
        if (left < max) {
            cur.append('(');
            backtrack(ans, cur, left + 1, right, max);
            cur.deleteCharAt(cur.length() - 1);
        }
        if (right < left) {
            cur.append(')');
            backtrack(ans, cur, left, right + 1, max);
            cur.deleteCharAt(cur.length() - 1);
        }
    }
}

39. 组合总和

 46. 全排列

package 回溯算法;

import org.junit.Test;

import java.util.ArrayList;
import java.util.List;

public class permute46 {
    /**
     * 全排列的 有可能需要去重 也不需要去重
     *
     * @param nums
     * @return
     */
    List<List<Integer>> lists;
    boolean[] vis;

    public List<List<Integer>> permute(int[] nums) {
        lists = new ArrayList<>();
        vis = new boolean[nums.length];

        if (nums.length == 0) {
            return lists;
        }
        dfs(nums, 0, new ArrayList<>(), vis, lists);
        return lists;
    }

    private void dfs(int[] nums, int index, ArrayList<Integer> list, boolean[] vis, List<List<Integer>> lists) {
        if (index == nums.length) {
            lists.add(new ArrayList<>(list));
            return;
        }
        for (int i = 0; i < nums.length; i++) {
            if (!vis[i]) {
                vis[i] = true;
                list.add(nums[i]);
                dfs(nums, index + 1, list, vis, lists);
                vis[i] = false;
                list.remove(list.size() - 1);
            }
        }
    }

    @Test
    public void test(){
        List<List<Integer>> permute = permute(new int[]{1});
        for (List<Integer> list:permute){
            for (int i:list){
                System.out.print(i+" ");
            }
            System.out.println();
        }

    }
}

 301. 删除无效的括号

 79. 单词搜索

494. 目标和

博文参考

举报

相关推荐

0 条评论