📣 独立日限时特惠: VIP通行证立减$68
查看: 2232| 回复: 15
跳转到指定楼层
上一主题 下一主题
收起左侧

请问dfs的一个题型写法问题

全局:

注册一亩三分地论坛,查看更多干货!

您需要 登录 才可以下载或查看附件。没有帐号?注册账号

x
一般的dfs(比如permutation,subsets)是以下的格式:

  1. public void main(){
  2.     dfs();
  3. }

  4. public void dfs(){
  5.     for(){
  6.        dfs();
  7.    }
  8. }
复制代码

但是那几道word search, word squares是以下形式:
  1. public void main(){
  2.     for(){
  3.         for(){
  4.             dfs();
  5.         }
  6.     }
  7. }

  8. public void dfs(){
  9.     for(){
  10.        dfs();
  11.    }
  12. }
复制代码


在主程序里面,对二维矩阵里面的每一个格子做dfs,是不是矩阵的dfs都需这么写?可以像permutation那样的格式写吗?permutation可以看成一维的,但是主程序里面没有for循环啊。有些费解。


上一篇:请问dfs 的一个概念性问题
下一篇:打卡贴
推荐
pxu 2018-5-31 15:00:39 | 只看该作者
全局:
208.Implement Trie (Prefix Tree)也差不多。供你参考吧。
  1. class Solution {
  2.     int dirs[][] = {{0,-1},{-1,0},{0,1},{1,0}};
  3.     int longestLen = 0;
  4.     public List<String> findWords(char[][] board, String[] words) {
  5.         Set<String> res = new HashSet<>();
  6.         if(board == null || board.length == 0){
  7.             return new ArrayList<String>(res);
  8.         }
  9.         
  10.         TrieNode root = new TrieNode();
  11.         for(String word: words){
  12.             addWordToTrieNode(root, word);
  13.         }
  14.         
  15.         int rows = board.length;
  16.         int cols = board[0].length;
  17.         boolean status[][] = new boolean[rows][cols];
  18.         
  19.         for(int row = 0; row < rows; row++){
  20.             for(int col = 0; col < cols; col++){
  21.                 dfs(row, col,rows,cols,board, root, res, status);
  22.             }
  23.         }
  24.         
  25.         return new ArrayList<String>(res);
  26.     }
  27.    
  28.     private void dfs(int row, int col, int rows, int cols, char[][] board, TrieNode node, Set<String> res, boolean status[][]){
  29.                
  30.         if(row < 0 || row >= rows || col <0 || col >= cols || status[row][col]){
  31.             return;
  32.         }
  33.         
  34.         int k = board[row][col] - 'a';
  35.         if(node.children[k] == null){
  36.             return;
  37.         }  
  38.         
  39.         if(node.children[k].word != null){
  40.             res.add(node.children[k].word);
  41.             node.children[k].word = null;
  42.         }
  43.         
  44.         status[row][col] = true;   
  45.         for(int dir[]: dirs){
  46.             int newRow = row + dir[0];
  47.             int newCol = col + dir[1];
  48.             
  49.             dfs(newRow, newCol, rows, cols, board, node.children[k], res, status);
  50.         }

  51.         status[row][col] = false;   
  52.     }
  53.    
  54.     private void addWordToTrieNode(TrieNode root, String word){
  55.         TrieNode p = root;
  56.         for(char c: word.toCharArray()){
  57.             if(p.children[c-'a'] == null){
  58.                 p.children[c-'a'] = new TrieNode();
  59.             }
  60.             p = p.children[c-'a'];
  61.         }
  62.         p.word = word;
  63.         
  64.     }
  65.    
  66.     private class TrieNode{
  67.         TrieNode children[] = new TrieNode[26];
  68.         String word;
  69.     }
  70. }
复制代码


回复

使用道具 举报

推荐
pxu 2018-5-31 11:04:20 | 只看该作者
全局:
对于 79. Word Search,给出的是二维数组,需要对每个board[row][col]开始去探索是否有满足的需求,所以需要下面两组循环。  for(row=0;..){
        for(col=0;...){
            dfs();
        }
    }

在dfs里面,因为要上下左右的去探索,所以也会有一个4个方向的循-具体见我下面代码。感觉不能光去背模板,要具体情况,具体分析。 呵呵,解释起来太费劲,希望对你的理解有帮组。
class Solution {
    int dirs[][] = {{0, -1},{-1,0},{0, 1},{1, 0}};
   
    public boolean exist(char[][] board, String word) {
        if(board == null || board.length == 0 || word == null || word.length() == 0){
            return false;
        }
        int rows = board.length;
        int cols = board[0].length;
        int status[][] = new int[rows][cols];
        
        for(int row = 0; row < rows; row++){
            for(int col = 0; col < cols; col++){


                if(dfs(row, col, rows,cols,board, word,0, status) == true){
                   return true;
               }
               
            }
        }
        
        return false;
    }
   
    private boolean dfs(int row, int col, int rows, int cols, char[][] board, String word, int curr, int status[][]){
        if(curr == word.length()){
            return true;
        }else{
             if(row < 0 || row >= rows || col < 0 || col >= cols){
                return false;
             }
            
             if(status[row][col] == 0 && board[row][col] == word.charAt(curr)){   
                 status[row][col] = 1;
                 for(int dir[]: dirs){
                     int newRow = row + dir[0];
                     int newCol = col + dir[1];
                    
                    if(dfs(newRow, newCol,rows, cols, board, word, curr+1, status)){
                        return true;
                    }
            
                 }
                 status[row][col] = 0;
            }
         
            return false;
        }
    }
}





回复

使用道具 举报

推荐
 楼主| shuatizhe 2018-5-20 08:06:18 | 只看该作者
全局:
我的permutation是这么写的,在主程序里面没有for loop。不知道是不是可以把word search,word squares也写成这样。
[i][i][i]

  1.     public List<List<Integer>> permute(int[] nums) {
  2.         if(nums==null)
  3.             return null;
  4.         
  5.         List<List<Integer>> res = new ArrayList<List<Integer>>();
  6.         List<Integer> temp = new ArrayList<Integer>();
  7.         HashSet<Integer> set = new HashSet<Integer>();
  8.         helper(nums,set,temp,res);
  9.         return res;
  10.     }
  11.    
  12.     private void helper(int[] nums, HashSet<Integer> set, List<Integer> temp, List<List<Integer>> res){
  13.             if(temp.size()==nums.length){
  14.             res.add(new ArrayList<Integer>(temp));
  15.             return;
  16.             }
  17.         
  18.         for(int i=0;i<nums.length;i++){
  19.             if(set.contains(nums))
  20.                 continue;
  21.             temp.add(nums);
  22.             set.add(nums);
  23.             helper(nums,set,temp,res);
  24.             set.remove(nums);
  25.             temp.remove(temp.size()-1);
  26.         }
  27.     }
复制代码


补充内容 (2018-5-20 11:46):
@肥宅快乐水,你上面那个code有没有非bit的写法?
[/i][/i][/i]
回复

使用道具 举报

🔗
pxu 2018-5-20 00:53:32 | 只看该作者
全局:
收到你的消息 我晚点看看你的这个问题回复在这里 - 一条消息系统要扣三分哟
回复

使用道具 举报

全局:
一回事,dfs就是走图的每一个节点。

先回答你第二个问题好了,每一个[i][j] 相当于图中每一个节点,不过在这个题中没有别的方法走到这个[i][j]节点上。

对于permutation, 或者 subset ,是一样的。只不过你的起始点是可以走到每一个节点上的。

就以permutation为例好了,你当然也完全可以先选一个起始点, 然后再做perm。
  1. class Solution {
  2.     public List<List<Integer>> permute(int[] nums) {
  3.         int n = nums.length;
  4.         for(int i = 0; i < n; i++)
  5.         {
  6.             List<Integer> list = new ArrayList<>();
  7.             list.add(nums[i]);
  8.             dfs(nums, 1 << i, list);
  9.         }
  10.         return re;
  11.     }


  12.     List<List<Integer>> re = new ArrayList<>();

  13.     void dfs(int[] n, int k, List<Integer> list)
  14.     {
  15.         if((1 << n.length) - 1 == k)
  16.         {
  17.             re.add(new ArrayList<>(list));
  18.             return;
  19.         }
  20.         for(int i = 0; i < n.length; i++)
  21.         {
  22.             if(((1 << i) & k) != 0) continue;
  23.             k |= 1 << i;
  24.             list.add(n[i]);
  25.             dfs(n, k, list);
  26.             list.remove(list.size() - 1);
  27.             k &= ~(1 << i);
  28.         }
  29.     }
  30. }
复制代码
回复

使用道具 举报

全局:
shuatizhe 发表于 2018-5-20 08:06
我的permutation是这么写的,在主程序里面没有for loop。不知道是不是可以把word search,word squares也写 ...

不该装b的,我错了。
你的perm写的完全没有问题,我也会这么写。

这样说吧, word search一样可以这么写, 只不过这样就不符合题意了,需要满足上下左右走的这四个方向。

如果perm这个题加一个条件, 比如给出【5,6,7】开头的所有perm,一共有【0-9】的数字。那么你的perm就不会这么写了。一定是进dfs之前有一个for loop的。

回复

使用道具 举报

🔗
 楼主| shuatizhe 2018-5-25 23:14:21 | 只看该作者
全局:
pxu 发表于 2018-5-20 00:53
收到你的消息 我晚点看看你的这个问题回复在这里 - 一条消息系统要扣三分哟

谢谢了啊:)如果不忙的话,期待看到你的答案
回复

使用道具 举报

🔗
pxu 2018-5-26 14:17:02 | 只看该作者
全局:
shuatizhe 发表于 2018-5-25 23:14
谢谢了啊:)如果不忙的话,期待看到你的答案

My computer was broken and I have to fix it early nex week and look at this topic afterwards. Sorry for that.
回复

使用道具 举报

🔗
 楼主| shuatizhe 2018-5-26 21:56:46 | 只看该作者
全局:
谢谢,没关系的,fix computer重要 :)
回复

使用道具 举报

🔗
pxu 2018-5-29 14:27:08 | 只看该作者
全局:
关于Subsets, Permutations, Combination Sum, Palindrome Partioning, 有人整理出通用的模板。
https://leetcode.com/problems/permutations/discuss/18239/A-general-approach-to-backtracking-questions-in-Java-(Subsets-Permutations-Combination-Sum-Palindrome-Partioning)

我没做过word search, word squares,这部分等我做完再恢复。不好意思
回复

使用道具 举报

🔗
pxu 2018-5-31 10:57:43 | 只看该作者
全局:

专门做了你问的这几个题目,我觉得应该按照给的数组类型(一维数组还是二维)去分析,
比如Permuation, 比如给的是一维数组[1,2,3]. 第一次循环,从item 0 开始到最后一个元素,依次加入后面的元素。通过if(tempList.contains(nums[i])) continue; 来跳过重复的。得出[1,2,3]
backtack后,从最后一个元素3被pop out,因为元素3就是最后一个元素,所有这个循环结束;
再次backtack, 把2 Pop out, 把3加进去 变成 [1,3],然后进入下一个backtrack 把2 加进来,得出 [1,3,2]。
解释起来比较费劲, 不好意思。@shuatizhe
public class Solution {
    public List<List<Integer>> permute(int[] nums) {
         List<List<Integer>> list = new ArrayList<>();
        backtrack(list, new ArrayList<>(), nums);
        return list;
    }


private void backtrack(List<List<Integer>> list, List<Integer> tempList, int [] nums){
    if( tempList.size()== nums.length){
        list.add(new ArrayList<>(tempList));
    }
    else{
        for(int i = 0; i < nums.length; i++){
            if(tempList.contains(nums[i])) continue;
            tempList.add(nums[i]);
            backtrack(list, tempList, nums);
            tempList.remove(tempList.size() - 1);
        }
    }
}
}

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册账号
隐私提醒:
  • ☑ 禁止发布广告,拉群,贴个人联系方式:找人请去🔗同学同事飞友,拉群请去🔗拉群结伴,广告请去🔗跳蚤市场,和 🔗租房广告|找室友
  • ☑ 论坛内容在发帖 30 分钟内可以编辑,过后则不能删帖。为防止被骚扰甚至人肉,不要公开留微信等联系方式,如有需求请以论坛私信方式发送。
  • ☑ 干货版块可免费使用 🔗超级匿名:面经(美国面经、中国面经、数科面经、PM面经),抖包袱(美国、中国)和录取汇报、定位选校版
  • ☑ 查阅全站 🔗各种匿名方法

本版积分规则

>
快速回复 返回顶部 返回列表