[高频] 五. 如何高效实现搜索类题目

130. Sorrounded Regions:  点击打开链接

思路:从四个最外边向里面搜索,只要是遇到'O',就是可以从外面走通的,装入queue

         将搜过的为'O'的元素进行遍历,并标记为true,

         找它的四个邻居点,如果在边界点之内为'O'并且是没有标记为true的,要做标记等待被遍历

         最后将没有标记成true的'O'标记为'X',这些是内部围着的'X',返回地图

class Pair{
    int x;
    int y;
    Pair(int x, int y){
        this.x = x;
        this.y = y;
    }
}

public class Solution {
    /**
     * @param board a 2D board containing 'X' and 'O'
     * @return void
     */
    
    public void surroundedRegions(char[][] board) {
        if(board==null || board.length == 0) return;
        boolean[][] marked = new boolean[board.length][board[0].length];
        Queue<Pair> queue = new LinkedList<Pair>();
        int[] dx = {-1, 1, 0, 0};
        int[] dy = {0, 0, -1, 1};
       
        for(int i = 0; i < board[0].length; i++){                        //最上,最下两条边
            if(board[0][i] == 'O'){
                queue.offer(new Pair(0, i));
            }
            if(board[board.length - 1][i] == 'O'){
                queue.offer(new Pair(board.length - 1, i));
            }
        }
        
        for(int j = 0; j < board.length; j++){                           //最左,最右两条边
            if(board[j][0] == 'O'){
                queue.offer(new Pair(j, 0));
            }
            if(board[j][board[0].length - 1] == 'O'){
                queue.offer(new Pair(j, board[0].length - 1));
            }
        }
        
        while(!queue.isEmpty()){
            Pair current = queue.poll();
            marked[current.x][current.y] = true;                         //每次poll出来的标记为true
            for(int k = 0; k < 4; k++){
                int newX=current.x + dx[k];
                int newY=current.y + dy[k];
                Pair newP=new Pair(newX,newY);
                if(isValid(board, newP)){
                    if(board[newX][newY] == 'O' && !marked[newX][newY]){
                        queue.add(newP);                            
                    }
                }
            }
        }
        
        for(int i = 0; i < board.length; i++){                           //剩余没被标记为true的'O',都要标记为'X'
            for(int j = 0; j < board[0].length; j++){
                if(board[i][j] == 'O' && !marked[i][j]){
                    board[i][j] = 'X';
                }
            }
        }
    }
    
    private boolean isValid(char[][] board,Pair p){
        if(p.x<0 || p.x>=board.length){
            return false;
        }
        if(p.y<0 || p.y>=board[0].length){
            return false;
        }
        return true;
    }
}
663. Nearest Exit:  点击打开链接

思路:遍历整个matrix拿到所有gate,BFS所有gate点,如果四周有有效的INF点,INF的值更新为gate值+1

注意:已经更新的INF点,就不用再更新,即使以后的遍历恰好是别的gate的四周点,因为要求离门最近的距离,越先被更新说明离门越近

         obsatcle点不用管,一开始我也是对obstacle不知道怎么处理

class Point{
    int x;
    int y;
    Point(int x,int y){
        this.x=x;
        this.y=y;
    }
}
public class Solution {
    /**
     * @param rooms m x n 2D grid
     * @return nothing
     */
    public void wallsAndGates(int[][] rooms) {
        if(rooms==null || rooms.length==0){
            return;
        }
        final int INF = 2147483647;
        int[] dx={0,0,-1,1};
        int[] dy={1,-1,0,0};
        Queue<Point> queue=new LinkedList<>();
        for(int i=0;i<rooms.length;i++){
            for(int j=0;j<rooms[0].length;j++){
                if(rooms[i][j]==0){
                    queue.offer(new Point(i,j));
                }
            }
        }
        
        while(!queue.isEmpty()){
            Point p=queue.poll();
            for(int i=0;i<4;i++){
                int newX=p.x+dx[i];
                int newY=p.y+dy[i];
                Point newP=new Point(newX,newY);
                if(isValid(rooms,newP)){
                    if(rooms[newX][newY]==INF){
                        queue.offer(newP);
                        rooms[newX][newY]=rooms[p.x][p.y]+1;                //一层一层的值不断累加
                    }
                }
            }
        }
    }
    
    private boolean isValid(int[][] rooms,Point p){
        if(p.x<0 || p.x>=rooms.length){
            return false;
        }
        if(p.y<0 || p.y>=rooms[0].length){
            return false;
        }
        return true;
    }
}
425. Letter Combinations of a Phone Number: 点击打开链接

思路:枚举型dfs

时间:O(3^n),每一层有三种选择,一共有n层

public class Solution {
    /**
     * @param digits A digital string
     * @return all posible letter combinations
     */
    ArrayList<String> result=new ArrayList<>();
    public ArrayList<String> letterCombinations(String digits) {
        if(digits==null || digits.length()==0){
            return result;
        }
        
        String[] array=new String[]{"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};  
        dfs(0,digits.length(),"",digits,array);
        return result;
    }
    
    private void dfs(int n,int len,String str,String digits,String[] array){  //无脑地放入所有所需参数
        if(n==len){                                                           //再写退出情况
            result.add(str);  
            return;
        }
        
        int digit=digits.charAt(n)-'0';                                       //先写扩展情况
        for(char c:array[digit].toCharArray()){
            dfs(n+1,len,str+c,digits,array);                                  //String可以直接加char,int
        }
    }
}
652. Factorization: 点击打开链接
public class Solution {
    /**
     * @param n an integer
     * @return a list of combination
     */
    List<List<Integer>> result=new ArrayList<>();
    List<Integer> list=new ArrayList<>();
    public List<List<Integer>> getFactors(int n) {
        if(n<=1){
            return result;
        }
        dfs(2,n);
        return result;
    }
    
    private void dfs(int lastF,int remain){
        if(!list.isEmpty()){
            list.add(remain);                                        //判断的时候才装remain
            result.add(new ArrayList<Integer>(list));
            list.remove(list.size()-1);                              //装到result链之后还要remove
        }
        
        for(int i=lastF;i<=remain/i;i++){                            //能保证每个list顺序是non-descending order
            if(remain%i==0){                                         //也能保证后面的[6,2]不要,和[2,6]不重复
                list.add(i);
                dfs(i,remain/i);
                list.remove(list.size()-1);
            }
        }
    }
}
653. Add Operators: 点击打开链接

注意:String转化为int很容易溢出,因此要用long

public class Solution {
    /**
     * @param num a string contains only digits 0-9
     * @param target an integer
     * @return return all possibilities
     */
    public List<String> addOperators(String num, int target) {
        List<String> result=new ArrayList<>();
        if(num==null || num.length()==0){
            return result;
        }
        dfs(result,num,target,"",0,0,0);
        return result;
    }
    
    private void dfs(List<String> result,String num, int target,String path,int pos,long sum,long lastF){
        if(pos==num.length()){
            if(sum==target){
                result.add(path);
            }
        }
        
        for(int i=pos;i<num.length();i++){
            long cur=Long.valueOf(num.substring(pos,i+1));
            if(pos==0){                                                         //第一个数字前不能有符号
                dfs(result,num,target,path+cur,i+1,cur,cur);
            }else{
                dfs(result,num,target,path+"+"+cur,i+1,sum+cur,cur);
                dfs(result,num,target,path+"-"+cur,i+1,sum-cur,-cur);
                dfs(result,num,target,path+"*"+cur,i+1,sum-lastF+lastF*cur,lastF*cur);
            }
            if(num.charAt(pos)=='0'){                                           //数字不能有前导零
                break;
            }
        }
    }
}
634. Word Squares: 点击打开链接





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值