代码随想录刷题随记26-回溯last

代码随想录刷题随记26-回溯last

3个hard。。。

332. 重新安排行程

leetcode链接
一个行程中,如果航班处理不好容易变成一个圈,成为死循环
解决方法就是一张票只能用一次。
在这里插入图片描述
在这里插入图片描述
如何按字典排序返回最小的行程组合。首先这说明返回一组就可以,所以需要及时的终止循环里面的递归。因此会使用判断是否要跳出for循环


                if (backTracking(tickets, used)) {
                    return true;
                }

字母序:
Collections.sort(tickets, (a, b) -> a.get(1).compareTo(b.get(1)));
其中每个列表代表一张票。Lambda表达式(a, b) -> a.get(1).compareTo(b.get(1))用作排序的比较器。
注意不能用==而是要用equals比较对象

class Solution {
        List<String>  path=new ArrayList<>();
        //List<String> ret;
    boolean backtrace(List<List<String>> tickets,boolean[]used){

         if(path.size()==tickets.size()+1){
           
            return true;
         }
         for(int i=0;i<tickets.size();i++){
            if(used[i]||!tickets.get(i).get(0).equals(path.getLast()))
              continue;
            used[i]=true;
            path.add(tickets.get(i).get(1));
            if(backtrace(tickets, used)){
                return true;
            }
            used[i]=false;
            path.removeLast();
         }
         return false;
    }
    public List<String> findItinerary(List<List<String>> tickets) {

        Collections.sort(tickets,(a,b)->a.get(1).compareTo(b.get(1)));
        boolean [ ] used=new boolean[tickets.size()];
        path.add("JFK");
        backtrace(tickets, used);
        return path;

    }
}

这个解法会超时有一个测试案例无法通过
不超时解法:
感觉只是优化了map的查找?为啥就不超时了

class Solution {
    private Deque<String> res;
    private Map<String, Map<String, Integer>> map;

    private boolean backTracking(int ticketNum){
        if(res.size() == ticketNum + 1){
            return true;
        }
        String last = res.getLast();
        if(map.containsKey(last)){//防止出现null
            for(Map.Entry<String, Integer> target : map.get(last).entrySet()){
                int count = target.getValue();
                if(count > 0){
                    res.add(target.getKey());
                    target.setValue(count - 1);
                    if(backTracking(ticketNum)) return true;
                    res.removeLast();
                    target.setValue(count);
                }
            }
        }
        return false;
    }

    public List<String> findItinerary(List<List<String>> tickets) {
        map = new HashMap<String, Map<String, Integer>>();
        res = new LinkedList<>();
        for(List<String> t : tickets){
            Map<String, Integer> temp;
            if(map.containsKey(t.get(0))){
                temp = map.get(t.get(0));
                temp.put(t.get(1), temp.getOrDefault(t.get(1), 0) + 1);
            }else{
                temp = new TreeMap<>();//升序Map
                temp.put(t.get(1), 1);
            }
            map.put(t.get(0), temp);

        }
        res.add("JFK");
        backTracking(tickets.size());
        return new ArrayList<>(res);
    }
}

51. N皇后

leetcode链接
在这里插入图片描述
由于回溯到每一层的时候只需要上面一层的record数据,所以record数组是可以不回溯的
用一维的record来记载的思路十分巧妙。,因为一位数组的索引天然就包含了第几行的信息,所以只需要记载列。

class Solution {
    List<List<String>> ret=new ArrayList<>();
    List<String> path=new LinkedList<>();
    boolean isvalid(int [] record,int i,int row){
        for(int j=0;j<row;j++){
           if(record[j]==i||(Math.abs(record[j]-i)==(Math.abs(j-row))))
             
            return false;
        }
        return true;
    }
    void backtrace(int row,int[]record,int n){
         if(row==n){
            ret.add(new ArrayList <>(path));
            return;
         }
         
         for(int i=0;i<n;i++){  
                
            if(isvalid(record,i,row)){
               String s="";     
               for(int k=0;k<i;k++)
                 s+='.';
               s+="Q";
               for(int k=i+1;k<n;k++)
                 s+='.';
               path.add(s);
               record[row]=i;
               backtrace(row+1, record, n);
               path.removeLast();
            }
         }

    }
    public List<List<String>> solveNQueens(int n) {
    int []record=new int[n];
     backtrace(0, record, n);
     return ret;

    }
}

37. 解数独

leetcode链接
在这里插入图片描述
整体思路和N皇后很像
判断棋盘是否合法有如下三个维度:

  • 同行是否重复
  • 同列是否重复
  • 9宫格里是否重复

解题代码:

class Solution {
    boolean isvalid(char[][] board,int row,int col,char val){
       //检查行
       
       for(int i=0;i<9;i++){
           if(i==row)
             continue;
           if(board[i][col]==val)
             return false;

       }
       //检查列
       for(int i=0;i<9;i++){
           if(i==col)
             continue;
           if(board[row][i]==val)
             return false;

       }
       //检查九宫格
       //确定边界
       int tmp=row/3;
       int start=tmp*3;
       tmp=col/3;
       int startcol=tmp*3;
       
       
       for(int i=start;i<start+3;i++){
        for(int j=startcol;j<startcol+3;j++){
             if(board[i][j]==val)
               return false;            
        }     
       }
        return true;
    }
    boolean backtrace(char [][] board){
       for(int i=0;i<9;i++){
          for(int j=0;j<9;j++){
              if(board[i][j]!='.')
                continue;
              for(char k='1';k<='9';k++){              
                 if(isvalid(board, i, j,k)){
                    board[i][j]=k;
                    if(backtrace(board))
                       return true;
                    board[i][j]='.';
                 }
              }
              return false;

          }
       }
       return true;
    }
    public void solveSudoku(char[][] board) {
         backtrace(board);
    }
}
  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值