代码随想录算法训练营之JAVA|第二十六天| 332. 重新安排行程

今天是第26天刷leetcode,立个flag,打卡60天。

算法挑战链接

332. 重新安排行程icon-default.png?t=N6B9https://leetcode.cn/problems/reconstruct-itinerary/

第一想法

题目理解:将多个行程的ticket 用第一个行程的结束地点作为下一个行程的开始地点,将行程串联起来。要求一次ticket只能使用一次,且必须将所有ticket使用完。

这种题目就是无脑套用回溯算法。我就会根据回溯算法的三步曲来走

第一步:确定返回值和入参。返回值是 void 入参是:tickets 、 tickets的标记 和 开始的位置

void backtracking5(String start, List> tickets, int[] index)

第二步:确定终止条件:当所有的tickets都被用完了,就可以结束了

        if (resultTmp5.size() + 1 == tickets.size()) {
                ......
                ......
        }

 第三步:当前递归需要完成的事情:当找到合适的ticket,在结果列表中添加,将改ticket的位置置为已使用,进入下一个递归。递归完后恢复,结果列表中移除该ticket,将改ticket的位置置为未使用

       for (int i = 0; i < index.length; i++) {
            if (index[i] == 1) {
                continue;
            }
            if (tickets.get(i).get(0).equals(start)) {
                resultTmp5.add(tickets.get(i).get(1));
                index[i] = 1;
                backtracking5(tickets.get(i).get(1), tickets, index);
                resultTmp5.removeLast();
                index[i] = 0;
            }
        }

于是代码就写出来了如下:

class Solution {
    LinkedList resultTmp5 = new LinkedList<>();
    List result5 = new ArrayList<>();
    public List findItinerary(List> tickets) {
        resultTmp5.add("JFK");
        backtracking5("JFK", tickets, new int[tickets.size()]);
        return result5;
    }

    void backtracking5(String start, List> tickets, int[] index) {
        if (resultTmp5.size() - 1 == tickets.size()) {
            result5 = getMinResult(resultTmp5, result5);
        }

        for (int i = 0; i < index.length; i++) {
            if (index[i] == 1) {
                continue;
            }
            if (tickets.get(i).get(0).equals(start)) {
                resultTmp5.add(tickets.get(i).get(1));
                index[i] = 1;
                backtracking5(tickets.get(i).get(1), tickets, index);
                resultTmp5.removeLast();
                index[i] = 0;
            }
        }
        
    }
    private List getMinResult(LinkedList resultTmp5, List result5) {
        if (result5.isEmpty()) {
            return new ArrayList<>(resultTmp5);
        }
        for (int i = 0; i < resultTmp5.size(); i++) {
            if (resultTmp5.get(i).compareTo(result5.get(i)) > 0) {
                return result5;
            }else if (resultTmp5.get(i).compareTo(result5.get(i)) < 0) {
                return new ArrayList<>(resultTmp5);
            }
        }
        return result5;
    }
}

 但是并没有出现理想中的AC的结果。给力一个超出时间限制的结果。

看完代码随想录之后的想法 

苦思冥想还是想不出来。好难呀。

对比了代码随想录的java代码之后,发现他的递归函数居然需要返回值?我和他的代码差就差在这里了。为啥需要返回值?

他给出的解释是:因为找到一条路径之后就需要在去遍历其他路径了。

对于这个解释我有点好奇,仔细对比之后发现,tickets在开始之前进行过一轮排序。所以如果找到了一条,那么这一条就是正确的答案了。

代码如下:

class Solution {
    LinkedList resultTmp5 = new LinkedList<>();
    List result5 = new ArrayList<>();
    public List findItinerary(List> tickets) {
        Collections.sort(tickets, (a, b) -> a.get(1).compareTo(b.get(1)));
        resultTmp5.add("JFK");
        backtracking5("JFK", tickets, new int[tickets.size()]);
        return result5;
    }

    boolean backtracking5(String start, List> tickets, int[] index) {
        if (resultTmp5.size() -1 == tickets.size()) {
            result5 = getMinResult(resultTmp5, result5);
            return true;
        }

        for (int i = 0; i < index.length; i++) {
            if (index[i] == 1) {
                continue;
            }
            if (tickets.get(i).get(0).equals(start)) {
                resultTmp5.add(tickets.get(i).get(1));
                index[i] = 1;
                if (backtracking5(tickets.get(i).get(1), tickets, index)) {
                    return true;
                }
                resultTmp5.removeLast();
                index[i] = 0;
            }
        }
        return false;
    }

    private List getMinResult(LinkedList resultTmp5, List result5) {
        if (result5.isEmpty()) {
            return new ArrayList<>(resultTmp5);
        }
        for (int i = 0; i < resultTmp5.size(); i++) {
            if (resultTmp5.get(i).compareTo(result5.get(i)) > 0) {
                return result5;
            }else if (resultTmp5.get(i).compareTo(result5.get(i)) < 0) {
                return new ArrayList<>(resultTmp5);
            }
        }
        return result5;
    }
}

今日收获

并不是所有的回溯算法都是不需要返回值的。那哪些需要返回值,这里抄了一下其他人写的:

  • 如果需要搜索整棵二叉树且不用处理递归返回值,递归函数就不要返回值。
  • 如果需要搜索整棵二叉树且需要处理递归返回值,递归函数就需要返回值。 
  • 如果要搜索其中一条符合条件的路径,那么递归一定需要返回值,因为遇到符合条件的路径了就要及时返回。(本题的情况)

你可能感兴趣的:(算法,java,开发语言)