LeetCode:DFS,BFS

1.Minimum Depth of Binary Tree

Given a binary tree, find its minimum depth.

The minimum depth is the number of nodes along the shortest path from the root node down to the nearest leaf node.

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

public class Solution {
    public int minDepth(TreeNode root) {
        if(root==null){
            return 0;
        }
        return recursive(root);
    }

    int recursive(TreeNode root){
        if(root.left==null&&root.right==null){
            return 1;
        }else if(root.left!=null&&root.right!=null){
            return Math.min(recursive(root.left)+1,recursive(root.right)+1);
        }else if(root.left!=null){
            return recursive(root.left)+1;
        }else if(root.right!=null){
            return recursive(root.right)+1;
        }
        return Integer.MIN_VALUE;//error
    }
}

2.Number of Islands

题意

//success 1
//添加外围的一层0,使得边界条件更好表示,DFS思想很明显
public class Solution {
    public int numIslands(char[][] grid) {
        if(grid==null){
            return 0;
        }
        int m = grid.length;
        if(m==0){
            return 0;
        }
        int n = grid[0].length;
        if(n==0){
            return 0;
        }
        char[][] newGrid = new char[m+2][n+2];
        for (int i = 0; i < m+2; i++) {
            Arrays.fill(newGrid[i],'0');
        }
        for (int i = 0; i < m; i++) {
            for (int j = 0; j < n; j++) {
                newGrid[i+1][j+1] = grid[i][j];
            }
        }
        //store visited
        Set<String> visited = new HashSet<>();
        int count=0;
        for (int i = 1; i < m+1; i++) {
            for (int j = 1; j < n+1; j++) {
                if(newGrid[i][j]=='1'&&!visited.contains(String.valueOf(i)+","+String.valueOf(j))){
                    DFS(newGrid,visited,i,j);
                    count++;
                }
            }
        }
        return count;
    }

    void DFS(char[][] grid,Set visited,int i,int j){
        //up
        if(grid[i-1][j]=='1'&&!visited.contains(String.valueOf(i-1)+","+String.valueOf(j))){
            visited.add(String.valueOf(i-1)+","+String.valueOf(j));
            DFS(grid,visited,i-1,j);
        }
        //down
        if(grid[i+1][j]=='1'&&!visited.contains(String.valueOf(i+1)+","+String.valueOf(j))){
            visited.add(String.valueOf(i+1)+","+String.valueOf(j));
            DFS(grid,visited,i+1,j);
        }
        //left
        if(grid[i][j-1]=='1'&&!visited.contains(String.valueOf(i)+","+String.valueOf(j-1))){
            visited.add(String.valueOf(i)+","+String.valueOf(j-1));
            DFS(grid,visited,i,j-1);
        }
        //right
        if(grid[i][j+1]=='1'&&!visited.contains(String.valueOf(i)+","+String.valueOf(j+1))){
            visited.add(String.valueOf(i)+","+String.valueOf(j+1));
            DFS(grid,visited,i,j+1);
        }
    }
}

3.Sum Root to Leaf Numbers

Given a binary tree containing digits from 0-9 only, each root-to-leaf path could represent a number.

An example is the root-to-leaf path 1->2->3 which represents the number 123.

Find the total sum of all root-to-leaf numbers.

For example,

1
/ \
2 3
The root-to-leaf path 1->2 represents the number 12.
The root-to-leaf path 1->3 represents the number 13.

Return the sum = 12 + 13 = 25.

很简单,直接写:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

public class Solution{
    public int sumNumbers(TreeNode root) {
        List<Integer> nums = new ArrayList<>();
        String path = "";
        if(root==null){
            return 0;
        }
        DFS(root,nums,path);
        int total=0;
        for (Integer num:
             nums) {
            total+=num;
        }
        return total;
    }

    void DFS(TreeNode root,List list,String path){
        if(root.left==null&&root.right==null){
            list.add(Integer.valueOf(path+String.valueOf(root.val)));
            return;
        }
        if(root.left!=null){
            DFS(root.left,list,path+String.valueOf(root.val));
        }
        if(root.right!=null){
            DFS(root.right,list,path+String.valueOf(root.val));
        }
    }
}

4.Convert Sorted Array to Binary Search Tree

Given an array where elements are sorted in ascending order, convert it to a height balanced BST.

很简单,直接写:

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

public class Solution {
    private static final int LEFT=1;
    private static final int RIGHT=2;
    public TreeNode sortedArrayToBST(int[] nums) {
        TreeNode root = null;
        if(nums.length==0||nums==null){
            return root;
        }
        if(nums.length==1){
            root = new TreeNode(nums[0]);
            return root;
        }
        if(nums.length==2){
            root = new TreeNode(nums[0]);
            TreeNode node = new TreeNode(nums[1]);
            root.right=node;
            return root;
        }
        int mid = (nums.length-1)/2;
        root = new TreeNode(nums[mid]);
        recursive(root,LEFT,nums,0,mid-1);
        recursive(root,RIGHT,nums,mid+1,nums.length-1);
        return root;
    }
    void recursive(TreeNode node,int direction,int[] nums,int low,int high){
        if(high-low>=2){
            int mid = low+(high-low)/2;
            TreeNode midNode= new TreeNode(nums[mid]);
            if(direction==LEFT){
                node.left = midNode;
            }else{
                node.right = midNode;
            }
            recursive(midNode,LEFT,nums,low,mid-1);
            recursive(midNode,RIGHT,nums,mid+1,high);
        }else if(low==high){
            TreeNode midNode= new TreeNode(nums[low]);
            if(direction==LEFT){
                node.left = midNode;
            }else{
                node.right = midNode;
            }
        }else if(high-low==1){
            TreeNode lowNode= new TreeNode(nums[low]);
            if(direction==LEFT){
                node.left = lowNode;
            }else{
                node.right = lowNode;
            }
            TreeNode highNode= new TreeNode(nums[high]);
            lowNode.right = highNode;
        }
    }
}

5.Longest Increasing Path in a Matrix

题意

解题思路:遍历每一个节点,存储每个节点到自身能够到达的顶点的最远距离,这样当再track到这个点时,能够直接返回,不用重复计算(DP思想)。cache存储的是在一个点能够到达的所有的点的最远距离值。比如[1,2,3,4],那么在遍历1节点时,就已经将这条路上所有点的最远距离值都存储在cache中了,这样,遍历到2,3,4节点时直接返回的值,没有计算。代码如下:

//success 1
//参考https://discuss.leetcode.com/topic/34835/15ms-concise-java-solution
public class Solution {
    public static final int[][] dirs = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};

public int longestIncreasingPath(int[][] matrix) {
    if(matrix.length == 0) return 0;
    int m = matrix.length, n = matrix[0].length;
    //cache存储每个点到它所能达到的最顶点的长度
    int[][] cache = new int[m][n];
    int max = 1;
    for(int i = 0; i < m; i++) {
        for(int j = 0; j < n; j++) {
            int len = dfs(matrix, i, j, m, n, cache);
            max = Math.max(max, len);
        }
    }   
    return max;
}

public int dfs(int[][] matrix, int i, int j, int m, int n, int[][] cache) {
    if(cache[i][j] != 0) return cache[i][j];
    int max = 1;
    //注意for循环中这四个方向的简洁写法
    for(int[] dir: dirs) {
        int x = i + dir[0], y = j + dir[1];
        if(x < 0 || x >= m || y < 0 || y >= n || matrix[x][y] <= matrix[i][j]) continue;
        int len = 1 + dfs(matrix, x, y, m, n, cache);
        max = Math.max(max, len);
    }
    cache[i][j] = max;
    return max;
}
}

参考:

1.15ms Concise Java Solution
2.Java 14ms relative short & easy to code solution with explanation. O(mn) time O(mn) space. DFS + DP

6.Binary Tree Maximum Path Sum

Given a binary tree, find the maximum path sum.

For this problem, a path is defined as any sequence of nodes from some starting node to any node in the tree along the parent-child connections. The path must contain at least one node and does not need to go through the root.

For example:
Given the below binary tree,

   1
  / \
 2   3

Return 6.

参考:Accepted short solution in Java,代码如下:

public class Solution {
    int maxValue;

    public int maxPathSum(TreeNode root) {
        maxValue = Integer.MIN_VALUE;
        maxPathDown(root);
        return maxValue;
    }

    private int maxPathDown(TreeNode node) {
        if (node == null) return 0;
        int left = Math.max(0, maxPathDown(node.left));
        int right = Math.max(0, maxPathDown(node.right));
        maxValue = Math.max(maxValue, left + right + node.val);
        return Math.max(left, right) + node.val;
    }
}

7.Recover Binary Search Tree

Two elements of a binary search tree (BST) are swapped by mistake.

Recover the tree without changing its structure.

Note:
A solution using O(n) space is pretty straight forward. Could you devise a constant space solution?

参考Simple and Powerful In-Order Traversal

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

//success 1
//运用该方法的原理是:一个BST的中序遍历应该是升序的,我们可以找到不是升序的两项,然后交换之。
public class Solution {

    TreeNode firstElement = null;
    TreeNode secondElement = null;
    // The reason for this initialization is to avoid null pointer exception in the first comparison when prevElement has not been initialized
    TreeNode prevElement = new TreeNode(Integer.MIN_VALUE);

    public void recoverTree(TreeNode root) {

        // In order traversal to find the two elements
        traverse(root);

        // Swap the values of the two nodes
        //只交换值,很机智啊
        int temp = firstElement.val;
        firstElement.val = secondElement.val;
        secondElement.val = temp;
    }

    private void traverse(TreeNode root) {

        if (root == null)
            return;

        traverse(root.left);

        // Start of "do some business", 
        // If first element has not been found, assign it to prevElement (refer to 6 in the example above)
        if (firstElement == null && prevElement.val >= root.val) {
            firstElement = prevElement;
        }

        // If first element is found, assign the second element to the root (refer to 2 in the example above)
        if (firstElement != null && prevElement.val >= root.val) {
            secondElement = root;
        }        
        prevElement = root;

        // End of "do some business"

        traverse(root.right);
}
}

1.Perfect Squares

Given a positive integer n, find the least number of perfect square numbers (for example, 1, 4, 9, 16, …) which sum to n.

For example, given n = 12, return 3 because 12 = 4 + 4 + 4; given n = 13, return 2 because 13 = 4 + 9.

跟硬币问题很相似,同样是利用DP思想,直接写:

    public int numSquares(int n) {
        List<Integer> perfertSqu = new ArrayList<>();
        for (int i = 1; i < n; i++) {
            if(i*i<=n){
                perfertSqu.add(i*i);
            }else{
                break;
            }
        }
        int[] dp = new int[n+1];
        dp[0]=0;
        dp[1]=1;
        for (int i = 2; i < n+1; i++) {
            int min=Integer.MAX_VALUE;
            for (int j = 0; j < perfertSqu.size(); j++) {
                int num = perfertSqu.get(j);
                if(num<=i){
                    min = Math.min(min,dp[i-num]+1);
                }else{
                    break;
                }
            }
            dp[i] = min;
        }
        return dp[n];
    }
}

2.Minimum Height Trees

题意

参考:Share some thoughts

The actual implementation is similar to the BFS topological sort. Remove the leaves, update the degrees of inner vertexes. Then remove the new leaves. Doing so level by level until there are 2 or 1 nodes left. What’s left is our answer!

//success 1
//跟BFS拓扑排序的思想类似
public class Solution {
    public List<Integer> findMinHeightTrees(int n, int[][] edges) {
        if (n == 1) return Collections.singletonList(0);
        //将用edges表示的图关系转换为邻接链表
        List<Set<Integer>> graph = new ArrayList<>(n);
        for(int i=0;i<n;i++){
            graph.add(new HashSet<>());
        }
        for(int[] edge:edges){
            int i = edge[0];
            int j = edge[1];
            graph.get(i).add(j);
            graph.get(j).add(i);
        }
        //定义leaves,即degree为1的vertices
        List<Integer> leaves = new ArrayList<>();
        for(int i=0;i<n;i++){
            if(graph.get(i).size()==1){
                leaves.add(i);
            }
        }
        //最后只剩1个或2个leaf
        while(n>2){
            n-=leaves.size();
            List<Integer> newLeaves = new ArrayList<>();
            System.out.println(leaves.size());
            for(int i=0;i<leaves.size();i++){
                int start = leaves.get(i);
                //取得set中的数
                int end = graph.get(start).iterator().next();//遍历set
                graph.get(end).remove(start);
                if(graph.get(end).size()==1){
                    newLeaves.add(end);
                }
            }
            leaves = newLeaves;
        }
        return leaves;
    }
}

3.Remove Invalid Parentheses

Remove the minimum number of invalid parentheses in order to make the input string valid. Return all possible results.

Note: The input string may contain letters other than the parentheses ( and ).

参考:

1.Java DFS 3 ms solution
2.Share my Java BFS solution

//success 1
//很难理解
// public class Solution {
//     public List<String> removeInvalidParentheses(String s) {
//     List<String> ans = new ArrayList<>();
//     remove(s, ans, 0, 0, new char[]{'(', ')'});
//     return ans;
// }

// public void remove(String s, List<String> ans, int last_i, int last_j,  char[] par) {
//     for (int stack = 0, i = last_i; i < s.length(); ++i) {
//         if (s.charAt(i) == par[0]) stack++;
//         if (s.charAt(i) == par[1]) stack--;
//         if (stack >= 0) continue;
//         for (int j = last_j; j <= i; ++j)
//             if (s.charAt(j) == par[1] && (j == last_j || s.charAt(j - 1) != par[1]))
//                 remove(s.substring(0, j) + s.substring(j + 1, s.length()), ans, i, j, par);
//         return;
//     }
//     String reversed = new StringBuilder(s).reverse().toString();
//     if (par[0] == '(') // finished left to right
//         remove(reversed, ans, 0, 0, new char[]{')', '('});
//     else // finished right to left
//         ans.add(reversed);
// }
// }

//success 2
//空间效率很低,思想比较直观
public class Solution {
    public List<String> removeInvalidParentheses(String s) {
      List<String> res = new ArrayList<>();

      // sanity check
      if (s == null) return res;

      Set<String> visited = new HashSet<>();
      Queue<String> queue = new LinkedList<>();

      // initialize
      queue.add(s);
      visited.add(s);

      boolean found = false;

      while (!queue.isEmpty()) {
        s = queue.poll();
        System.out.println("queue poll: "+s);

        if (isValid(s)) {
            System.out.println("res: "+s);
          // found an answer, add to the result
          res.add(s);
          //这句话非常重要,在found到一个valid string时,那么这个值就被永久置为true了
          //它将不会执行generate all possible states后面的语句,一直在queue中取值,直到为空
          //因为题意是Remove the minimum number,一旦found为true,那么只需要在跟它长度相同的string
          //中查找,在queue中查找都有一部分冗余,可以从stdOut中看出来
          found = true;
        }

        System.out.println("found: "+found);
        if (found) continue;

        // generate all possible states
        for (int i = 0; i < s.length(); i++) {
          // we only try to remove left or right paren
          if (s.charAt(i) != '(' && s.charAt(i) != ')') continue;

          String t = s.substring(0, i) + s.substring(i + 1);
          System.out.println(t);
          if (!visited.contains(t)) {
            // for each state, if it's not visited, add it to the queue
            System.out.println("not visited: "+t);
            queue.add(t);
            visited.add(t);
          }
        }
      }

      return res;
    }

    // helper function checks if string s contains valid parantheses
    boolean isValid(String s) {
      int count = 0;

      for (int i = 0; i < s.length(); i++) {
        char c = s.charAt(i);
        if (c == '(') count++;
        if (c == ')' && count-- == 0) return false;
      }

      return count == 0;
    }
}

对于输入:

"()())()"

上述stdOut输出为:

queue poll: ()())()
found: false
)())()
not visited: )())()
(())()
not visited: (())()
()))()
not visited: ()))()
()()()
not visited: ()()()
()()()
()()))
not visited: ()()))
()())(
not visited: ()())(
queue poll: )())()
found: false
())()
not visited: ())()
)))()
not visited: )))()
)()()
not visited: )()()
)()()
)()))
not visited: )()))
)())(
not visited: )())(
queue poll: (())()
res: (())()
found: true
queue poll: ()))()
found: true
queue poll: ()()()
res: ()()()
found: true
queue poll: ()()))
found: true
queue poll: ()())(
found: true
queue poll: ())()
found: true
queue poll: )))()
found: true
queue poll: )()()
found: true
queue poll: )()))
found: true
queue poll: )())(
found: true

最终输出结果为:

["(())()","()()()"]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值