package DFS;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Stack; public class RealDFS {
public static void main(String[] args) {
// TODO Auto-generated method stub
}
/*
* 在进入DFS这个话题前面,首先得讲一下DFS的基本公式和基本概念,那么下面是从网上摘抄的一段关于dfs的比较传统的代码
* Depth-First-Search( MazeCell c )
* If c is the goal
* Exit
* Else Mark c
* "Visit In Progress"
* Foreach neighbor n of c If n "Unvisited"
* Depth-First-Search( n )
* Mark c "Visited"
* End procedure
* 也就是说dfs是找到任何相邻的子节点,然后对于每个子节点分别的进入继续dfs
*/
/*
* 257.Binary Tree Paths
* 11.21 By mingyang
*/
public List<String> binaryTreePaths(TreeNode root) {
List<String> res = new ArrayList<String>();
if (root != null)
dfs(root, "", res);
return res;
}
private void dfs(TreeNode root, String path, List<String> res) {
if (root.left == null && root.right == null) res.add(path + root.val);
if (root.left != null) dfs(root.left, path + root.val + "->", res);
if (root.right != null) dfs(root.right, path + root.val + "->", res);
}
/*
* 199. Binary Tree Right Side View
* 11.21 By Mingyang
* 在recursive的算法,就是贴着树的右边界往下面走,如果不行往左边偏一个,然后继续往右边偏,利用末尾的个数与层数相等的技巧
* 其实是一种根右左的算法,很巧妙
*/
public List<Integer> rightSideView(TreeNode root) {
List<Integer> result = new ArrayList<Integer>();
rightSideView(root, result, 0);
return result;
}
public void rightSideView(TreeNode curr, List<Integer> result, int currDepth){
if(curr == null){
return;
}
if(currDepth == result.size()){
result.add(curr.val);
}
rightSideView(curr.right, result, currDepth + 1);
rightSideView(curr.left, result, currDepth + 1);
}
/*
* 133. Clone Graph
* 3.20 by Mingyang
* 这道题目就是典型的dfs了
*/
private HashMap<Integer, UndirectedGraphNode> map = new HashMap<Integer, UndirectedGraphNode>();
public UndirectedGraphNode cloneGraph(UndirectedGraphNode node) {
return dfs(node);
}
private UndirectedGraphNode dfs(UndirectedGraphNode node) {
if (node == null) return null;
if (map.containsKey(node.label)) {
return map.get(node.label);
}
UndirectedGraphNode clone = new UndirectedGraphNode(node.label);
map.put(clone.label, clone);
for (UndirectedGraphNode neighbor : node.neighbors) {
clone.neighbors.add(dfs(neighbor));
}
return clone;
}
//用stack来实现dfs
public UndirectedGraphNode cloneGraph1(UndirectedGraphNode node) {
if(node == null)
return null;
HashMap<UndirectedGraphNode, UndirectedGraphNode> hm = new HashMap<UndirectedGraphNode, UndirectedGraphNode>();
LinkedList<UndirectedGraphNode> stack = new LinkedList<UndirectedGraphNode>();
UndirectedGraphNode head = new UndirectedGraphNode(node.label);
hm.put(node, head);
stack.push(node);
while(!stack.isEmpty()){
UndirectedGraphNode curnode = stack.pop();
for(UndirectedGraphNode aneighbor: curnode.neighbors){//check each neighbor
if(!hm.containsKey(aneighbor)){//if not visited,then push to stack
stack.push(aneighbor);
UndirectedGraphNode newneighbor = new UndirectedGraphNode(aneighbor.label);
hm.put(aneighbor, newneighbor);
}
hm.get(curnode).neighbors.add(hm.get(aneighbor));
}
}
return head;
}
/*
* 129. Sum Root to Leaf Numbers
* 11.23 By Mingyang
* dfs包含三种,这里是dfs的preorder方法,先解决根再是左右
*/
public int sumNumbers(TreeNode root) {
return dfs(root, 0);
}
public int dfs(TreeNode root, int levelBase) {
if (root == null)
return 0;
if (root.left == null && root.right == null) {
return levelBase + root.val;
}
int nextLevelBase = (levelBase + root.val) * 10;
int leftSubTreeSum = dfs(root.left, nextLevelBase);
int rightSubTreeSum = dfs(root.right, nextLevelBase);
return leftSubTreeSum + rightSubTreeSum;
}
/*
* 337. House Robber III
* 2016-3-14 by Mingyang
* 刚开始看这道题目有一点误区,以为是奇数排和偶数排之和比较大写,然后选出更大的,所以自己就写了BFS的代码,但发现如下的case不过:
* 4
* 1
* 2
*3
*因为这里面的最大的其实是4和3,中间隔了两行不偷,所以我觉得这道题目是dp加上dfs,两个线路的dfs的最大加起来。
*dfs all the nodes of the tree, each node return two number, int[] num,
*num[0] is the max value while rob this node,
*num[1] is max value while not rob this value.
*Current node return value only depend on its children's value
*/
public int rob(TreeNode root) {
int[] num = dfs(root);
return Math.max(num[0], num[1]);
}
private int[] dfs(TreeNode x) {
if (x == null) return new int[2];
int[] left = dfs(x.left);
int[] right = dfs(x.right);
int[] res = new int[2];
res[0] = left[1] + right[1] + x.val;
res[1] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]);
return res;
}
/*
* 332. Reconstruct Itinerary
* 2016-3-14 by Mingyang
* 这道题给我们一堆飞机票,让我们建立一个行程单,如果有多种方法,取其中字母顺序小的那种方法。
* 这道题的本质是有向图的遍历问题,那么LeetCode关于有向图的题只有两道Course Schedule和Course Schedule II,
* 而那两道是关于有向图的顶点的遍历的,而本题是关于有向图的边的遍历。
* 每张机票都是有向图的一条边,我们需要找出一条经过所有边的路径,那么DFS不是我们的不二选择。
* 代码前半段都在准备工作。把所有的tickets全部装进一个map,string对应了一个priority queue
* 后半段dfs中,找出第一个顺序的结果。最终输出是从最后一个开始,一个一个往前退的情况下addFirst加起来的
*/
Map<String, PriorityQueue<String>> flights;
LinkedList<String> path;
public List<String> findItinerary(String[][] tickets) {
flights = new HashMap<String, PriorityQueue<String>>();
path = new LinkedList<String>();
for (String[] ticket : tickets) {
if(!flights.containsKey(ticket[0])){
flights.put(ticket[0], new PriorityQueue<String>());
}
flights.get(ticket[0]).add(ticket[1]);
}
dfs("JFK");
return path;
}
public void dfs(String departure) {
PriorityQueue<String> arrivals = flights.get(departure);
while (arrivals != null && !arrivals.isEmpty())
dfs(arrivals.poll());
path.addFirst(departure);
}
/*
* 329. Longest Increasing Path in a Matrix
* 2016-3-14 by Mingyang
*/
int []dx = { 1 , -1, 0 , 0 };
int []dy = { 0 , 0 , 1 , -1 };
public int longestIncreasingPath(int[][] matrix) {
if (matrix.length == 0) return 0;
int m = matrix.length, n = matrix[0].length;
int[][] dis = new int [m][n];
int ans = 0;
for (int i = 0; i < m; i++) {
for (int j = 0; j < n; j++) {
ans = Math.max(ans, dfs( i, j, m, n, matrix, dis));
}
}
return ans;
}
public int dfs(int x, int y, int m,int n,int[][] matrix, int[][] dis) {
if (dis[x][y] != 0) return dis[x][y];
for (int i = 0; i < 4; i++) {
int nx = x + dx[i];
int ny = y + dy[i];
if (nx >= 0 && ny >= 0 && nx < m && ny < n && matrix[nx][ny] > matrix[x][y]) {
dis[x][y] = Math.max(dis[x][y], dfs(nx, ny, m, n, matrix, dis));
}
}
return ++dis[x][y];
}
/*
* 323 Number of Connected Components in an Undirected Graph
* 2016-3-14 by Mingyang
* Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes),
* write a function to find the number of connected components in an undirected graph.
* Note:You can assume that no duplicate edges will appear in edges.
* Since all edges are undirected, [0, 1] is the same as [1, 0] and thus will not appear together in edges.
*/
public int countComponents(int n, int[][] edges) {
if (n <= 0 || edges == null) {
return 0;}
if (n == 1 && edges.length == 0) {
return 1;}
int result = 0;
boolean[] visited = new boolean[n];
// step 1: create the adj list from edge list
List[] adjList = new List[n];
for (int i = 0; i < n; i++) {
adjList[i] = new ArrayList<Integer>();
}
for (int[] edge : edges) {
int from = edge[0];
int to = edge[1];
adjList[from].add(to);
adjList[to].add(from);}
// step 2: calculate the number of cc
for (int i = 0; i < n; i++) {
if (!visited[i]) {
result++;
countCCHelper(i, adjList, visited);}}
return result;}
private void countCCHelper(int node, List[] adjList, boolean[] visited) {
if (visited[node]) {return;}
visited[node] = true;
List<Integer> neighbors = adjList[node];
for (int neighbor : neighbors) {
countCCHelper(neighbor, adjList, visited);}}
/*
* 301. Remove Invalid Parentheses
* 2016-3-14 by Mingyang
* https://leetcode.com/discuss/72208/easiest-9ms-java-solution
* 括号总是成对出现的,因此我们只需要记录尚未匹配的(。
* 每次循环时有如下三种情况:
* (, 保留或者不保留。
* ), 如果我们有未匹配的(,则有两种选择;否则,只能不保留。
* 保留其他字符。
* 因为我们要移除数量最少的括号,我们应该得到最大的匹配()数量,注意下面两行的顺序。
* dfs(str.substring(1), subRes + '(', countLeft + 1, maxLeft + 1);
* dfs(str.substring(1), subRes, countLeft, maxLeft);
* 它可以保证最长的结果出现在比它较短的结果前面。
*/
private List<String> res = new ArrayList<String>();
private int max = 0;
public List<String> removeInvalidParentheses(String s) {
dfs(s, "", 0, 0);
if (res.size() == 0) {
res.add("");
}
return res;
}
private void dfs(String str, String subRes, int countLeft, int maxLeft) {
if (str.length() == 0) {
if (countLeft == 0 && subRes.length() != 0) {
if (maxLeft > max) {
max = maxLeft;
}
if (max == maxLeft && !res.contains(subRes)) {
res.add(subRes.toString());
}
}
return;
}
if (str.charAt(0) == '(') {
dfs(str.substring(1), subRes.concat("("), countLeft + 1,maxLeft + 1);
dfs(str.substring(1), subRes, countLeft, maxLeft);
} else if (str.charAt(0) == ')') {
if (countLeft > 0) {
dfs(str.substring(1), subRes.concat(")"), countLeft - 1,maxLeft);
}
dfs(str.substring(1), subRes, countLeft, maxLeft);
} else {
dfs(str.substring(1), subRes.concat(String.valueOf(str.charAt(0))),countLeft, maxLeft);
}
}
/*
* 98. Validate Binary Search Tree
* 11.23 By Mingyang
* 这个题目开始用dfs的循环做时,我第一次把root的null的判断写在主函数里面,殊不知这么仅仅判断了root,对于
* 子分支并没有做判断。另外需要注意的是用long不用int,否则会溢出。
* 另外一种方法就是Tree里面的中序遍历。dfs用stack实现
*/
public boolean isValidBST(TreeNode root) {
return isValidBST(root, Long.MIN_VALUE, Long.MAX_VALUE);
}
public boolean isValidBST(TreeNode root, long minVal, long maxVal) {
if (root == null) return true;
if (root.val >= maxVal || root.val <= minVal) return false;
return isValidBST(root.left, minVal, root.val) && isValidBST(root.right, root.val, maxVal);
}
public boolean isValidBST1(TreeNode root) {
Stack<TreeNode> stack = new Stack<TreeNode>();
TreeNode cur = root;
TreeNode pre = null;
while (!stack.isEmpty() || cur != null) {
if (cur != null) {
stack.push(cur);
cur = cur.left;
} else {
TreeNode p = stack.pop();
if (pre != null && p.val <= pre.val) {
return false;
}
pre = p;
cur = p.right;
}
}
return true;
}
/*
* 99. Recover Binary Search Tree
* 11.23 By Mingyang
* inorder
*/
TreeNode pre;
TreeNode first;
TreeNode second;
public void inorder(TreeNode root) {
if (root == null)
return;
inorder(root.left);
if (pre == null) {// 只有一种情况,就是最初的情况,最开始的最左边的值-----convert BST to double
// linked list
pre = root; // pre指针初始
} else {
if (pre.val > root.val) {
if (first == null) {
first = pre;// 第一个逆序点
}
second = root; // 不断寻找最后一个逆序点
}
pre = root; // pre指针每次后移一位
}
inorder(root.right);
} public void recoverTree(TreeNode root) {
pre = null;
first = null;
second = null;
inorder(root);
if (first != null && second != null) {
int tmp = first.val;
first.val = second.val;
second.val = tmp;
}
} public void recoverTree1(TreeNode root) {
// use inorder traversal to detect incorrect node inOrder(root); int temp = first.val;
first.val = second.val;
second.val = temp;
} TreeNode prev = null;
TreeNode first1 = null;
TreeNode second1 = null; public void inOrder(TreeNode root) {
if (root == null)
return;
// search left tree
inOrder(root.left); // in inorder traversal of BST, prev should always have smaller value
// than current value
if (prev != null && prev.val >= root.val) {
// incorrect smaller node is always found as prev node
if (first1 == null)
first = prev;
// incorrect larger node is always found as curr(root) node
second1 = root;
}
// update prev node
prev = root;
// search right tree
inOrder(root.right);
}
/*
* 100 Same Tree
* 2016-3-14 by Mingyang
*/
public boolean isSameTree(TreeNode p, TreeNode q) {
if(p == null && q == null) return true;
if(p == null || q == null) return false;
if(p.val == q.val)
return isSameTree(p.left, q.left) && isSameTree(p.right, q.right);
return false;
}
/*
* 101. Symmetric Tree
* 11.23 By Mingyang
*/
public boolean isSymmetric(TreeNode root) {
if (root == null)
return true;
return isSymmetricTree(root.left, root.right);
}
public boolean isSymmetricTree(TreeNode p, TreeNode q) {
if (p == null && q == null)
return true;
if (p == null || q == null)
return false;
return (p.val == q.val) && isSymmetricTree(p.left, q.right)&& isSymmetricTree(p.right, q.left);
}
/*
* 104. Maximum Depth of Binary Tree
* 11.19 By Mingyang
* 同样可以用queue,注意!queue不能用null来判决,queue应该用size()来判断的
*/
public int maxDepth(TreeNode root) {
if (root == null)
return 0;
return Math.max(maxDepth(root.left), maxDepth(root.right)) + 1;
}
/*
* 105. Construct Binary Tree from Preorder and Inorder Traversal
* 11.21 By Mingyang
* Becuase k is not the length, it it need to -(inStart+1) to get the length
*/
public TreeNode buildTree2(int[] inorder, int[] postorder) {
int inStart = 0;
int inEnd = inorder.length - 1;
int postStart = 0;
int postEnd = postorder.length - 1;
return buildTree2(inorder, inStart, inEnd, postorder, postStart,postEnd);
}
public TreeNode buildTree2(int[] inorder, int inStart, int inEnd,int[] postorder, int postStart, int postEnd) {
if (inStart > inEnd || postStart > postEnd)
return null;
int rootValue = postorder[postEnd];
TreeNode root = new TreeNode(rootValue);
int k = 0;
for (int i = 0; i < inorder.length; i++) {
if (inorder[i] == rootValue) {
k = i;
break;
}
}
root.left = buildTree2(inorder, inStart, k - 1, postorder, postStart,
postStart + k - (inStart + 1));
// Becuase k is not the length, it it need to -(inStart+1) to get the length
root.right = buildTree2(inorder, k + 1, inEnd, postorder, postStart + k - inStart, postEnd - 1);
// postStart+k-inStart = postStart+k-(inStart+1) +1
return root;
}
/*
* 106. Construct Binary Tree from Inorder and preorder Traversal
* 11.20 By Mingyang
* 千万不要以为root一定在中间那个点,还是要找一下中间点的位置
*/
public TreeNode buildTree(int[] preorder, int[] inorder) {
int preEnd = preorder.length - 1;
int inEnd = inorder.length - 1;
return construct(preorder, 0, preEnd, inorder, 0, inEnd);
}
public TreeNode construct(int[] preorder, int preStart, int preEnd,int[] inorder, int inStart, int inEnd) {
if (preStart > preEnd || inStart > inEnd) {
return null;
}
int val = preorder[preStart];
TreeNode p = new TreeNode(val);
// find parent element index from inorder
int k = 0;
for (int i = 0; i < inorder.length; i++) {
if (val == inorder[i]) {
k = i;
break;
}
}
p.left = construct(preorder, preStart + 1, preStart + (k - inStart),inorder, inStart, k - 1);
p.right = construct(preorder, preStart + (k - inStart) + 1, preEnd,inorder, k + 1, inEnd);
return p;
}
/*
* 108. Convert Sorted Array to Binary Search Tree
* 11.20 By Mingyang
*/
public TreeNode sortedArrayToBST(int[] num) {
if (num.length == 0)
return null;
return sortedArrayToBST(num, 0, num.length - 1);
}
public TreeNode sortedArrayToBST(int[] num, int start, int end) {
if (start > end)
return null;
int mid = (start + end) / 2;
TreeNode root = new TreeNode(num[mid]);
root.left = sortedArrayToBST(num, start, mid - 1);
root.right = sortedArrayToBST(num, mid + 1, end);
return root;
}
/*
* 109.Convert sorted list to BST
* 2016.12.24 by Mingyang
* 这里的问题是对于一个链表我们是不能常量时间访问它的中间元素的。
* 这时候就要利用到树的中序遍历了,按照递归中序遍历的顺序对链表结点一个个进行访问,而我们要构造的二分查找树正是按照链表的顺序来的。
* 思路就是先对左子树进行递归
* 然后将当前结点作为根,迭代到下一个链表结点,最后在递归求出右子树即可。整体过程就是一次中序遍历,时间复杂度是O(n),空间复杂度是栈空间O(logn)
* 但是我没用上面的二分查找,用的是快慢节点recursive来做,所以这么做就有缺陷:
*/
public TreeNode sortedListToBST(ListNode head) {
if(head == null)
return null;
ListNode fast = head;
ListNode slow = head;
ListNode prev =null;
while(fast != null && fast.next != null)
{
fast = fast.next.next;
prev =slow;
slow=slow.next;
}
TreeNode root = new TreeNode(slow.val);
if(prev != null)
prev.next = null;
else
head = null;
root.left = sortedListToBST(head);
root.right = sortedListToBST(slow.next);
return root;
}
/*
* 上面做法的缺陷在哪呢,就在于这个函数的复杂度是n的logn次方,因为,T(n)=n+2T(n/2),这里多就多了这个n
* 也就是我们fast从头到尾的遍历的这个时间复杂度。那么每个Subproblem里面就会有n个至少,那么一共有logn个问题
* 因为树的遍历一般的分层就是nlogn。那么下面的问题复杂度就是n,因为只有主函数用了n,每个子函数也只是n,why?
* T(n)=2T(n/2)这里每个子函数都是原来复杂度的一半。所以一共就是n的复杂度
* 这个就跟merge sort不一样了,因为merge sort合起来的那个部分需要logn,所以总的就是nlogn
* 那么这里为什么是dfs呢?这里的start到end,他的临边就是一个是从start到mid-1,一个是mid这个点,一个是mid+1到end
*/
private ListNode node;
public TreeNode sortedListToBST2(ListNode head) {
if(head == null){
return null;
}
int size = 0;
ListNode runner = head;
node = head;
while(runner != null){
runner = runner.next;
size ++;
}
return inorderHelper(0, size - 1);
}
public TreeNode inorderHelper(int start, int end){
if(start > end){
return null;
}
int mid = start + (end - start) / 2;
TreeNode left = inorderHelper(start, mid - 1);
TreeNode treenode = new TreeNode(node.val);
treenode.left = left;
node = node.next;//第一次访问到这就是左边已经到头了,才会访问到node节点
TreeNode right = inorderHelper(mid + 1, end);
treenode.right = right;
return treenode;
} /*
* 110. Balanced Binary Tree
* 1.18 by Mingyang
* This improved algorithm works by checking the height of each subtree as we recurse
* down from the root. On each node, we recursively get the heights of the left and right
* subtrees through the checkHeight method. If the subtree is balanced, then check-
* Height will return the actual height of the subtree. If the subtree is not balanced, then
* checkHeight will return -1. We will immediately break and return -1 from the current call.
*/
public boolean isBalanced(TreeNode root) {
if (root == null)
return true;
if (Math.abs(depth(root.left) - depth(root.right)) > 1)
return false;
return isBalanced(root.left) && isBalanced(root.right);
}
private int depth(TreeNode root) {
if (root == null)
return 0;
return Math.max(depth(root.left), depth(root.right)) + 1;
}
/*
* 111. Minimum Depth of Binary Tree
* 11.18 by Mingyang 还是用queue来做
*/
public int minDepth(TreeNode root) {
if (root == null)
return 0;
int left = minDepth(root.left);
int right = minDepth(root.right);
return (left == 0 || right == 0) ? left + right + 1 : Math.min(left,right) + 1;
}
/*
* 112. Path Sum
* 11.18 by Mingyang
*/
public boolean hasPathSumRec(TreeNode root, int sum) {
if (root == null)
return false;
if (root.left == null && root.right == null && sum - root.val == 0)
return true;
return hasPathSumRec(root.left, sum - root.val)|| hasPathSumRec(root.right, sum - root.val);
}
/*
* 114. Flatten Binary Tree to Linked List
* 11.20 By Mingyang
* 注意stack不能用!=null来描述,应该用
* (!stack.isEmpty())来表述!这道题目你会发现好像是根左右的顺序,然后就用stack来写
* 就是一个preorder的变体,在recursive的方法中呢,我们必须用一个全局变量来保存上一个节点的位置,因为
* 我们退回来的时候才可以知道lastNode具体的地方。
*/
public void flatten(TreeNode root) {
if (root == null)
return;
Stack<TreeNode> stack = new Stack<TreeNode>();
stack.push(root);
TreeNode prev = null;
while (!stack.isEmpty()) {
TreeNode temp = stack.pop();
if (temp.right != null)
stack.push(temp.right);
if (temp.left != null)
stack.push(temp.left);
if (prev != null) {
prev.right = temp;
prev.left = null;
}
prev = temp;
}
}
private TreeNode lastNode = null;//lastNode就是连接左边和右边的纽带
public void flattenRec(TreeNode root) {
if (root == null) {
return;
}
if (lastNode != null) {
lastNode.left = null;//这里面就是真正的改变整个TreeNode的部分,相当于preorder的根操作。
lastNode.right = root;
}
lastNode = root;
TreeNode right = root.right;//这不不能省去,因为一旦省去了以后我们就不能记录当时的root.right了
flatten(root.left);
flatten(right);
}
/*
* 116. Populating Next Right Pointers in Each Node
* 1.20 By Mingyang
*在这里面,因为是满的二叉树,所以所有点都有值,那么root的左边和右边都有值
*我本来想用上面的思路,在外面建立一个father node,然后在子层考虑father和next的关系,但是那么做太复杂了
*/
public void connect(TreeLinkNode root) {
if(root == null)
return;
if(root.left != null){//表明不是叶子节点那一行
root.left.next = root.right;
if(root.next != null)
root.right.next = root.next.left;
}
connect(root.left);
connect(root.right);
}
/*
* 117. Populating Next Right Pointers in Each Node II
* 1.20 by Mingyang
* 唯一的不同是每次要先找到一个第一个有效的next链接节点,并且递归的时候要先处理右子树,再处理左子树。
*/
public void connect1Rec(TreeLinkNode root) {
if (root == null)
return;
TreeLinkNode p = root.next;
while (p != null) {
if (p.left != null) {
p = p.left;
break;
}
if (p.right != null) {
p = p.right;
break;
}
p = p.next;
}
if (root.right != null) {
root.right.next = p;
}
if (root.left != null) {
root.left.next = root.right != null ? root.right : p;
}
connect1Rec(root.right);
connect1Rec(root.left);
}
/*
* 124. Binary Tree Maximum Path Sum
* 11.21 By Mingyang 刚开始想只用一个int
* max来传参,但是后面发现无论怎么改,return的max都要被附上初值
* 所以我们这里出了一个全局变量,这里的任何一个path都要经过一个最高的点,那么这个最高的点就在
* root里面的node,那么每次都是最大的值更新。所以node表示一定经过的。
* 那么返回的整数就是如果最大的path还要通往父节点能提供的最大值。也就是我能提供给父节点一个接口,
* 并且最大的值。
*/
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;
}
//那你说我不用全局变量,那就只能用数组:
public int maxPathSum1(TreeNode root) {
int[] max = new int[1];
max[0] = Integer.MIN_VALUE;
maxPathSum1(max, root);
return max[0];
}
private int maxPathSum1(int[] max, TreeNode root){
if(root == null)
return 0;
int leftMax = Math.max(0, maxPathSum1(max, root.left));
int rightMax = Math.max(0, maxPathSum1(max, root.right));
max[0] = Math.max(max[0], root.val+leftMax+rightMax);
return root.val+Math.max(leftMax,rightMax);
}
} class TreeNode {
public int val;
public TreeNode left;
public TreeNode right; public TreeNode(int x) {
val = x;
}
} class ListNode {
int val;
ListNode next; ListNode(int x) {
val = x;
}
} class TreeLinkNode {
int val;
TreeLinkNode left, right, next; TreeLinkNode(int x) {
val = x;
}
} class UndirectedGraphNode {
int label;
List<UndirectedGraphNode> neighbors;
UndirectedGraphNode(int x) { label = x; neighbors = new ArrayList<UndirectedGraphNode>(); }
}

Leetcode总结之DFS的更多相关文章

  1. LeetCode Subsets (DFS)

    题意: 给一个集合,有n个互不相同的元素,求出所有的子集(包括空集,但是不能重复). 思路: DFS方法:由于集合中的元素是不可能出现相同的,所以不用解决相同的元素而导致重复统计. class Sol ...

  2. [LeetCode] questions conclustion_BFS, DFS

    BFS, DFS 的题目总结. Directed graph: Directed Graph Loop detection and if not have, path to print all pat ...

  3. LeetCode刷题 DFS+回溯

    一.DFS介绍 二.LeetCode 实战 LC 17. 电话号码的字母组合 解法思路 解题步骤 代码 LC 79. 单词搜索 解题思路 解题步骤 代码 LC 46. 全排列 解题思路一 解题步骤 代 ...

  4. Clone Graph leetcode java(DFS and BFS 基础)

    题目: Clone an undirected graph. Each node in the graph contains a label and a list of its neighbors. ...

  5. LeetCode Combinations (DFS)

    题意: 产生从1-n的k个数的所有组合,按升序排列并返回. 思路: DFS一遍即可解决.注意升序. class Solution { public: vector<vector<int&g ...

  6. LeetCode Generate Parentheses (DFS)

    题意 Given n pairs of parentheses, write a function to generate all combinations of well-formed parent ...

  7. LeetCode 组合总和(dfs)

    题目 给定一个无重复元素的数组 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合. candidates 中的数字可以无限制重 ...

  8. LeetCode:BFS/DFS

    BFS/DFS 在树专题和回溯算法中其实已经涉及到了BFS和DFS算法,这里单独提出再进一步学习一下 BFS 广度优先遍历 Breadth-First-Search 这部分的内容也主要是学习了labu ...

  9. 待解决)leetcode 路径和 dfs 线序遍历

    Given a binary tree and a sum, find all root-to-leaf paths where each path's sum equals the given su ...

随机推荐

  1. LeetCode(122) Best Time to Buy and Sell Stock II

    题目 Say you have an array for which the ith element is the price of a given stock on day i. Design an ...

  2. CodeForces 703A Mishka and trip

    Description Little Mishka is a great traveller and she visited many countries. After thinking about ...

  3. HDU 5236 Article 期望

    题意: 你现在要打\(n\)个字符,但是程序随时可能会崩溃. 你可以在恰当的时机按下 \(Ctrl-S\)键,崩溃后,会从最后一次保存的情况继续开始打字. 具体是这样的: 在每个第\(i-0.1s(i ...

  4. action属性和data属性组合事例

  5. 浅析win32 Win64 x86 x64 区别 及Eclipse启动报Java was started but returned exit code=13 错误

    win32.x86_64是64位 X86就是  32位系统 X64 就是64位系统 最好记得方法就是带有64的就是64位,其余都是32位 为什么要讲这个呢? 如果是绿色版本的eclipse,在打开ec ...

  6. SDOJ 3742 黑白图

    [描述] 一个 n 个点 m 条边构成的无向带权图.由一些黑点与白点构成 树现在每个白点都要与他距离最近的黑点通过最短路连接(如果有很多个,可以选 取其中任意一个),我们想要使得花费的代价最小.请问这 ...

  7. 精通CSS高级Web标准解决方案(1-3 规划、组织与维护样式表)

    对文档应用样式 对代码进行注释/*......*/ 结构性注释 自我提示 删除注释.优化样式表 样式指南:解释代码与站点的视觉设计是如何组织在一起的 站点结构.文件结构.命名规则 编码标准:(X)ht ...

  8. 关于windows系统DPI增大导致字体变大的原因分析

    最近再学习WPF开发,其中提到一个特性“分辨率无关性”,主要功能就是实现开发的桌面程序在不同分辨率的电脑上显示时,会根据系统的DPI自动进行UI的缩放,从而不会导致应用程序的失真. 这个里面就提到了个 ...

  9. 九度oj 题目1466:排列与二进制

    题目描述: 在组合数学中,我们学过排列数.从n个不同元素中取出m(m<=n)个元素的所有排列的个数,叫做从n中取m的排列数,记为p(n, m).具体计算方法为p(n, m)=n(n-1)(n-2 ...

  10. DS博客作业05——树

    1.本周学习总结 1.1思维导图 1.2学习体会 学习:相比于之前的数据结构,树多了很多性质,相应的也多了很多计算题,不得不说,专有名词也是颇多.觉得树最独特的地方就是它的兄弟.孩子结点,用以组成了它 ...