力扣记录:回溯算法6其他——491 递增子序列,332 重新安排行程

本次题目

  • 491 递增子序列
  • 332 重新安排行程

491 递增子序列

  • 回溯:对比子集问题,需要递增子序列,但是结果需要去重,不能使用子集问题的去重方法。
    1. 定义startIndex为for循环的起始位置;
    2. 当已经存放的元素超过两个时将子序列存入子集集合,当遍历完数组后终止;
    3. 每次回溯定义一个数组(也可以使用map)在同一层选择中跳过已经使用过的元素(不用回溯),当前元素不满足递增时也跳过。
class Solution {
    //定义全局数组存放排列子集,定义全局二维数组存放子集集合
    LinkedList<Integer> res = new LinkedList<>();
    List<List<Integer>> result = new LinkedList<>();
    public List<List<Integer>> findSubsequences(int[] nums) {
        //定义startIndex为for循环的起始位置
        int startIndex = 0;
        //开始回溯
        backtracking(nums, startIndex);
        //返回结果
        return result;
    }
    //回溯函数
    private void backtracking(int[] nums, int startIndex){
        //当已经存放的元素超过两个时将子序列存入子集集合
        if(res.size() >= 2) result.add(new LinkedList<>(res));
        //当遍历完数组后终止
        if(startIndex >= nums.length) return;
        //每次回溯定义一个数组(也可以使用map)去重
        //-100 <= nums[i] <= 100
        int[] used = new int[201];
        for(int i = startIndex; i < nums.length; i++){
            //在同一层选择中跳过已经使用过的元素
            if(used[nums[i] + 100] == 1) continue;
            //当前元素不满足递增时也跳过
            if(res.size() > 0 && nums[i] < res.get(res.size() - 1)) continue;
            res.add(nums[i]);
            used[nums[i] + 100] = 1;
            //回溯
            backtracking(nums, i + 1);
            res.removeLast();
            //used在同层中使用不用回溯
        }
    }
}

332 重新安排行程

  • 回溯:
    1. 定义全局数组存放行程,定义全局map映射出发机场和到达机场的关系(map<出发机场, map<到达机场, 航班次数>>),因为只需要找到一条合理的行程,所以不用遍历所有的行程,返回布尔值判断该行程是否合理;
    2. 当行程中的机场数等于给定航班数量加1时,找到合理行程,终止;
    3. 遍历map找到下一站。
  • 注意:当有多条行程时选择首字母靠前的,使用TreeMap排序。enteySet()遍历map修改值setValue()。
class Solution {
    //定义全局数组存放行程
    LinkedList<String> res = new LinkedList<>();
    //定义全局map映射出发机场和到达机场的关系(map<出发机场, map<到达机场, 航班次数>>)
    Map<String, Map<String, Integer>> map = new HashMap<>();
    public List<String> findItinerary(List<List<String>> tickets) {
        //初始化
        for(List<String> t : tickets){
            String src = t.get(0);
            String dst = t.get(1);
            //当有多条行程时选择首字母靠前的,使用TreeMap排序
            if(!map.containsKey(src)) map.put(src, new TreeMap<String, Integer>());
            Map<String, Integer> temp = map.get(src);
            if(!temp.containsKey(dst)){
                temp.put(dst, 0);
                map.put(src, temp);
            }
            temp = map.get(src);
            temp.put(dst, temp.get(dst) + 1);
            map.put(src, temp);
        }
        res.add("JFK");
        //开始回溯
        backtracking(tickets.size());
        //返回结果
        return res;
    }
    //回溯函数,因为只需要找到一条合理的形成,所以不用遍历所有的行程,返回布尔值判断该行程是否合理
    private boolean backtracking(int ticketsNum){
        //当行程中的机场数等于给定航班数量加1时,找到合理行程,终止
        if(res.size() == ticketsNum + 1) return true;
        //获取当前站
        String cur = res.peekLast();
        //遍历map找到下一站
        if(map.containsKey(cur)){
            for(Map.Entry<String, Integer> dstEntry : map.get(cur).entrySet()){
                String dst = dstEntry.getKey();
                int num = dstEntry.getValue();
                //如果航班数大于0,可以选择
                if(num > 0){
                    res.add(dst);
                    dstEntry.setValue(num - 1);
                    //回溯
                    if(backtracking(ticketsNum)) return true;
                    dstEntry.setValue(num);
                    res.removeLast();
                }
            }
        }
        //没有合理行程
        return false;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值