The thief has found himself a new place for his thievery again. There is only one entrance to this area, called the "root." Besides the root, each house has one and only one parent house. After a tour, the smart thief realized that "all houses in this place forms a binary tree". It will automatically contact the police if two directly-linked houses were broken into on the same night. Determine the maximum amount of money the thief can rob tonight without alerting the police. Example 1: 3 / \ 2 3 \ \ 3 1 Maximum amount of money the thief can rob = 3 + 3 + 1 = 7. Example 2: 3 / \ 4 5 / \ \ 1 3 1 Maximum amount of money the thief can rob = 4 + 5 = 9.
即如何從樹中選擇幾個節點,在確保這幾個節點不直接相連的狀況下使其值的和最大。面試
最開始的思路我是採用自頂向下遞歸遍歷樹的形式來計算可能得到的最大收益。當前節點的狀況有兩種:選中或是沒選中,若是選中的話,那麼兩個直接子節點將不能夠被選中,若是沒選中,那麼兩個直接子節點的狀態能夠是選中或是沒選中。代碼以下:微信
public int rob(TreeNode root) { if(root == null) return 0; int result1 = root.val + (root.left == null ? 0 : rob(root.left.left) + rob(root.left.right)) + (root.right == null ? 0 : rob(root.right.left) + rob(root.right.right)); int result2 = rob(root.left) + rob(root.right); return Math.max(result1, result2); }
這段代碼的缺陷在於,我須要遍歷這棵樹兩次,分別爲了獲取選中當前節點和不選中當前節點的狀況。而事實上咱們能夠在一次遍歷中就獲得這兩個狀況對於當前節點的影響,並經過遞歸將值傳遞迴上一層。很像是一種逆向思惟。ide
public int rob2(TreeNode root) { if (root == null) return 0; int[] value = robSum(root); return Math.max(value[0], value[1]); } private int[] robSum(TreeNode root) { int[] res = new int[2]; if (root == null) return res; int[] left = robSum(root.left); int[] right = robSum(root.right); res[0] = Math.max(left[0], left[1]) + Math.max(right[0], right[1]); res[1] = root.val + left[0] + right[0]; return res; }
想要了解更多開發技術,面試教程以及互聯網公司內推,歡迎關注個人微信公衆號!將會不按期的發放福利哦~this