回溯+贪心 代码注释(Java)322.重新安排行程


332.重新安排行程

给定一个机票的字符串二维数组 [from, to],子数组中的两个成员分别表示飞机出发和降落的机场地点,对该行程进行重新规划排序。所有这些机票都属于一个从 JFK(肯尼迪国际机场)出发的先生,所以该行程必须从 JFK 开始。

说明:

  1. 如果存在多种有效的行程,你可以按字符自然排序返回最小的行程组合。例如,行程 [“JFK”, “LGA”] 与 [“JFK”, “LGB”] 相比就更小,排序更靠前
  2. 所有的机场都用三个大写字母表示(机场代码)。
  3. 假定所有机票至少存在一种合理的行程。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/reconstruct-itinerary

    /**
     * 算法:回溯+贪心
     * 思想:① 以起点城市建立终点城市的邻接表
     *      ② 对相同起点城市的机票按字典序排序(贪心),这样我们每次取邻接点,取到的肯定是行程最短的
     *      ③ 因为我们找到的一条行程(欧拉路径)就是行程最短的路径,所以就可以直接回溯,不需要再继续找了,因此可以标记一个isFind,当ifFind=true 直接return
     *      ④ dfs中cnt来计数使用的机票数,n表示总机票数,beg表示起点城市,adjMap就是我们先前创建的邻接表
     *      ⑤ 遍历邻接表 -> 删除机票 -> dfs -> 恢复机票
     */
    List<String> tmp;
    List<String> ans;
    boolean isFind = false;
    public List<String> findItinerary(List<List<String>> tickets) {
        //check
        if (tickets == null || tickets.size() == 0) return new ArrayList<>();
        tmp = new ArrayList<>();
        //adj
        Map<String, List<String>> adjMap = new HashMap<>();
        for (int i = 0;i < tickets.size();i++){
            //邻接表
            List<String> adj = adjMap.getOrDefault(tickets.get(i).get(0),new LinkedList<>());
            adj.add(tickets.get(i).get(1));
            adjMap.put(tickets.get(i).get(0),adj);
        }
        //sort (贪心算法,按照字典序排序,使得每次选择的都是字典序最小的行程)
        Set<String> keys = adjMap.keySet();
        Iterator<String> iterator = keys.iterator();
        while (iterator.hasNext()){
            Collections.sort(adjMap.get(iterator.next()),((o1, o2) -> o1.compareTo(o2)));//lambda
        }
        //dfs
        tmp.add("JFK");
        dfs(adjMap,"JFK",0,tickets.size());
        //ans
        return ans;
    }

    private void dfs(Map<String, List<String>> adjMap,String beg,int cnt,int n){
        if(cnt >= n){
            ans = new ArrayList<>(tmp);
            isFind = true;//标记,找到最小行程就可以直接回溯了
            return;
        }

        List<String> list = adjMap.get(beg);
        if (list == null || list.size() == 0) return;//这里很重要,防止空指针异常

        for (int i = 0;i < list.size();i++){
            String des = list.get(0);
                tmp.add(des);
                list.remove(des);
                //dfs
                dfs(adjMap, des, cnt + 1, n);
                if (isFind) return;//剪枝
                //回溯
                tmp.remove(tmp.size()-1);//这里是关键,要删除后面的元素,我之前运行错误就是因为我删了前面的des
                list.add(des);
        }
    }
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值