Binary Tree Maximum Path Sum Algorithm - java

I am new to recursion and binary trees. I am trying to solve this problem on leetcode.
To find maximum sum path is like finding maximum path between any two nodes, that path may or may not pass through the root; except that with max sum path we want to track sum instead of path length.
My algorithm is passing 91/93 test cases and I just can't figure out what I am missing. Can anyone please provide some direction?
class Solution {
private int sum = Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
maxPathSumHelper(root);
if(root.left != null){
maxPathSumHelper(root.left);
}
if(root.right != null){
maxPathSumHelper(root.right);
}
return sum;
}
public int maxPathSumHelper(TreeNode root){
if(root == null){
return 0;
}
//check left sum
int leftValue = root.val + maxPathSumHelper(root.left);
if(leftValue > sum){
sum = leftValue;
}
//check right sum
int rightValue = root.val + maxPathSumHelper(root.right);
if(rightValue > sum){
sum = rightValue;
}
//check if root value is greater
if(root.val > sum){
sum = root.val;
}
//check if right and left value is the greatest
if((leftValue + rightValue - (2 * root.val) )+ root.val > sum){
sum = (leftValue + rightValue - (2 * root.val)) + root.val;
}
return Math.max(leftValue, rightValue);
}
}

Try
class Solution {
private int sum = Integer.MIN_VALUE;
public int maxPathSum(TreeNode root) {
maxPathSumHelper(root);
if (root.left != null) {
maxPathSumHelper(root.left);
} else if (root.right != null) {
maxPathSumHelper(root.right);
}
return sum;
}
public int maxPathSumHelper(TreeNode root) {
if (root == null) {
return 0;
}
//check left sum
int leftValue = root.val + maxPathSumHelper(root.left);
if (leftValue > sum) {
sum = leftValue;
}
//check right sum
int rightValue = root.val + maxPathSumHelper(root.right);
if (rightValue > sum) {
sum = rightValue;
}
//check if root value is greater
if (root.val > sum) {
sum = root.val;
}
//check if right and left value is the greatest
if ((leftValue + rightValue - (2 * root.val) ) + root.val > sum) {
sum = (leftValue + rightValue - (2 * root.val)) + root.val;
}
return Math.max(Math.max(leftValue, rightValue), root.val);
}
}

I guess we can a bit simplify our statements here.
This'll simply get accepted:
public final class Solution {
int max;
public final int maxPathSum(final TreeNode root) {
max = Integer.MIN_VALUE;
traverse(root);
return max;
}
private final int traverse(final TreeNode node) {
if (node == null)
return 0;
final int l = Math.max(0, traverse(node.left));
final int r = Math.max(0, traverse(node.right));
max = Math.max(max, l + r + node.val);
return Math.max(l, r) + node.val;
}
}
References
For additional details, please see the Discussion Board which you can find plenty of well-explained accepted solutions in there, with a variety of languages including efficient algorithms and asymptotic time/space complexity analysis1, 2.

Related

Find sum of smaller node from given element in AVL Tree

Can anyone help me.
If i have tree, the inorder traversal AVL Tree is
-1 0 1 2 5 6 9 10 11 12
then i want to have method sumGreater(n)
if
sumGreater(6) = 9 + 10 + 11 + 12 = 42
I tried to modified this.
https://www.geeksforgeeks.org/count-greater-nodes-in-avl-tree/
but it wont work.
Node rightRotate(Node y, int key) {
Node x = y.left;
Node T2 = x.right;
x.right = y;
y.left = T2;
y.height = max(height(y.left), height(y.right)) + 1;
x.height = max(height(x.left), height(x.right)) + 1;
int val = (T2 != null) ? T2.desc : -1;
y.desc = y.desc - (x.desc + key) + (val + key); // modified
x.desc = x.desc - (val + key) + (y.desc + key); // modified
return x;
}
int SumGreater(Node root, int x) {
int res = 0;
while (root != null) {
int desc = (root.right != null) ? root.right.desc : -1;
if (root.key > x) {
res = res + desc + 1 + 1;
root = root.left;
} else if (root.key < x) {
root = root.right;
} else {
res = res + desc + 1;
break;
}
}
return res;
}
this still count node not sum of node.
Can anyone help me with O(logN) time complexity
Please help me
corrected code and help
Does desc also represent the number of descendant nodes for a node? Then it is unnecessary to take it into account when you want to count the sum of value of nodes greater than n. You should sum their keys. Besides, since your function doesn't modify the tree, there is no need to consider rotation.
Here is my advice code in recursion.
int SumGreater(Node root, int x) {
int res = 0;
while (root != null) {
if (root.key > x) {
res += root.key;
res += SumGreater(root.right, x);
root = root.left;
} else {
root = root.right;
}
}
return res;
}

Find nearest double in ordered ArrayList<Double>

I have an sorted ArrayList and I would like to find nearest element to double x in it.
double x = 50.2;
ArrayList<Double> arrayList = new ArrayList<>();
arrayList.add(12.34);
arrayList.add(86.00);
arrayList.add(87.26);
arrayList.add(241.63);
...
double findNearestDoubleInList(list, x)
{
...
}
How do I accomplish that?
Use java.lang.Math.abs to get the difference between values in the list and desired value and find the nearest one.
double answer = arrayList.get(0);
double current = Double.MAX_VALUE;
for (Double value : arrayList) {
if (Math.abs(value - x) < current) {
answer = value;
current = Math.abs(value - x);
}
}
Walk through the list and compute the absolute difference with x and the current element in the list.
Return the smallest absolute difference.
static double findNearestDoubleInList(ArrayList<Double> list, double d){
if(list.size() == 0){
return -1;
}
if(list.size() == 1){
return list.get(0);
}
double current = list.get(0);
double currentMin = Math.abs(list.get(0) - d);
for(int i = 1; i < list.size(); i ++){
double difference = Math.abs(list.get(i) - d);
if(currentMin > difference){
currentMin = difference;
current = list.get(i);
}
}
return current;
}
For algorithms like this, always assume the first element is your solution.
// Java program to find element closet to given target by binary search on the sorted array
class FindClosestNumber {
// Returns element closest to target in arr[]
public static double findClosest(double[] arr, double target)
{
int n = arr.length;
// Corner cases
if (target <= arr[0])
return arr[0];
if (target >= arr[n - 1])
return arr[n - 1];
// Doing binary search
int i = 0, j = n, mid = 0;
while (i < j) {
mid = (i + j) / 2;
// if arr[mid] and target are very close
if (Math.abs(arr[mid]-target) < 0.0001)
return arr[mid];
/* If target is less than array element,
then search in left */
if (target < arr[mid]) {
// If target is greater than previous
// to mid, return closest of two
if (mid > 0 && target > arr[mid - 1])
return getClosest(arr[mid - 1],
arr[mid], target);
/* Repeat for left half */
j = mid;
}
// If target is greater than mid
else {
if (mid < n-1 && target < arr[mid + 1])
return getClosest(arr[mid],
arr[mid + 1], target);
i = mid + 1; // update i
}
}
// Only single element left after search
return arr[mid];
}
// Method to compare which one is the more close
// We find the closest by taking the difference
// between the target and both values. It assumes
// that val2 is greater than val1 and target lies
// between these two.
public static double getClosest(double val1, double val2,
double target)
{
if (target - val1 >= val2 - target)
return val2;
else
return val1;
}
// Driver code
public static void main(String[] args)
{
double arr[] = {12.34, 86.00, 87.26, 241.63};
double target = 50.2;
System.out.println(findClosest(arr, target));
}
}

What is the size above depth of BST

This is what I have so far. I need to computes the size of the tree above at depth k.
public static int above(Node t, int k) {
if (t == null) { return 0; }
if (t.key > k)
return (above(t.left, k - 1) + above(t.right, k - 1) + 1);
else {
return above(t.left, k - 1) + above(t.right, k - 1);
}
}
EDIT: This code works and computes the size of the tree at depth k.
public static int at(Node t, int k) {
if(t == null) return 0;
if(k == 0) return 1;
return at(t.left, k - 1) + at(t.right, k - 1);
}
I would of thought something more like this would do it... but maybe I don't understand the problem correctly.
public static int above(Node t, int k) {
if (t == null) { return 0; }
if (k > 0) {
return (above(t.left, k - 1) + above(t.right, k - 1) + 1);
} else {
return 1;
}
}
This code computes the tree size till depth k where root is at depth 1.
static int depth=0;
static int tree_size=0,k=3;
private static void inorder(Node head) {
if(head!=null){
depth++;
inorder(head.left);
if(depth<=k)
tree_size++;
inorder(head.right);
depth--;
}
}

Unable to determine if my IDA* implementation has a bug or is just inefficient

I implemented the iterative deepening a-star search(for the 8-Puzzle problem, but can accept other problems) and ran it on an input. It ran unsuccessfully for 2 hrs. For simpler inputs that are close to goal node it works fine. Others have got it to work for this input. I am not sure whether my implementation is just inefficient or goes into an infinite loop
PuzzleSolver.java$ida
/** Accepts start node root and string identifying whihc heuristic to use
* h1 is number of misplaced tiles and h2 is Manhattan distance
*/
private Node ida(Node root, final String h) {
PriorityQueue<DNode> frontier = new PriorityQueue<DNode>(10, new Comparator<DNode>(){
#Override
public int compare(DNode n1, DNode n2) {
if(h == "h1") {
if(n1.depth + h1(n1.node) > n2.depth + h1(n2.node)) return 1;
if(n1.depth + h1(n1.node) < n2.depth + h1(n2.node)) return -1;
return 0;
}
if(h == "h2") {
if(n1.depth + h2(n1.node) > n2.depth + h2(n2.node)) return 1;
if(n1.depth + h2(n1.node) < n2.depth + h2(n2.node)) return -1;
return 0;
}
return 0;
}});
ArrayList<Node> explored = new ArrayList<Node>();
Node soln = null;
DNode start = new DNode(root, 1);
frontier.add(start);
int d = 0;
int flimit = (h == "h1" ? h1(start.node) : h2(start.node));
int min = flimit;
while(true) {
DNode dn = frontier.poll();
if(dn == null) {
frontier.add(start);
d = 0;
flimit = min;
continue;
}
d = dn.depth;
Node n = dn.node;
//n.print();
if(goalCheck(n)){
return n;
}
for(int i = 0;i < ops.length;i++) {
String op = ops[i];
if(n.applicable(op)) {
soln = n.applyOp(op);
int h_cost;
if(h == "h1") h_cost = h1(soln);
else h_cost = h2(soln);
if(!checkDup(explored,soln) && d + 1 + h_cost < flimit) {
frontier.add(new DNode(soln, d + 1));
DNode least = frontier.peek();
min = least.depth + (h == "h1" ? h1(least.node) : h2(least.node));
}
}
}
explored.add(n);
max_list_size = Math.max(max_list_size, frontier.size() + explored.size());
}
}
PuzzleSolver.java$CheckDup
private boolean checkDup(ArrayList<Node> explored, Node soln) {
boolean isDuplicate = false;
for(Node n:explored) {
boolean equal = true;
for(int i = 0;i < soln.size; i++) {
for(int j =0 ;j<soln.size;j++) {
if(soln.state.get(i).get(j) != n.state.get(i).get(j)) {
equal = false;
}
}
}
isDuplicate |= equal;
}
return isDuplicate;
}
Start state(failed):
1 2 3
8 - 4
7 6 5
Goal state:
1 3 4
8 6 2
7 - 5
(worked for 1 3 4 8 6 0 7 5 2)
I have not included Node.java because I am pretty sure it works after running other search algorithms like best-first, dfs. It is difficult to provide an SCCE, so I am just asking for help spotting any obvious bugs in the ida implementation.
EDIT: Solved issue, but still trying to figure out a termination condition when the goal is not reachable. IDA* does not keep a list of explored nodes, so how can I know if I have covered the whole solution space?
Your checkDup function is very inefficient. I recommend using a HashSet:
http://docs.oracle.com/javase/7/docs/api/java/util/HashSet.html
Your function has a cost linear in the size of the set, while the contains method of HashSet has a constant cost.
Strings in java are compared with equals:
Java String.equals versus ==
There may be other problems, but these are the two most obvious ones I spotted after a quick check of your code.
There was a mistake in the way I calculated the new flimit. It did not cause a problem in the other cases because the flimit of the successor was such that it did not cause it to loop infinitely. Also the condition should f(current node) <= cutoff. and not '<' as I took.
Updated version:
private Node ida(Node root, final String h) {
PriorityQueue<DNode> frontier = new PriorityQueue<DNode>(10, new Comparator<DNode>(){
#Override
public int compare(DNode n1, DNode n2) {
if(h == "h1") {
if(n1.depth + h1(n1.node) > n2.depth + h1(n2.node)) return 1;
if(n1.depth + h1(n1.node) < n2.depth + h1(n2.node)) return -1;
return 0;
}
if(h == "h2") {
if(n1.depth + h2(n1.node) > n2.depth + h2(n2.node)) return 1;
if(n1.depth + h2(n1.node) < n2.depth + h2(n2.node)) return -1;
return 0;
}
return 0;
}});
ArrayList<Node> explored = new ArrayList<Node>();
Node soln = null;
DNode start = new DNode(root, 1);
frontier.add(start);
int d = 0;
int flimit = (h == "h1" ? h1(start.node) : h2(start.node));
int min = flimit;
while(true) {
DNode dn = frontier.poll();
if(dn == null) {
explored.clear();
frontier.add(start);
d = 0;
flimit = min;
continue;
}
d = dn.depth;
Node n = dn.node;
//n.print();
if(goalCheck(n)){
return n;
}
min = Integer.MAX_VALUE;
for(int i = 0;i < ops.length;i++) {
String op = ops[i];
if(n.applicable(op)) {
soln = n.applyOp(op);
int h_cost;
if(h == "h1") h_cost = h1(soln);
else h_cost = h2(soln);
if(!checkDup(explored,soln)) {
if(d + 1 + h_cost <= flimit) {
frontier.add(new DNode(soln, d + 1));
}
else {
if(d + 1 + h_cost < min)min = d + 1 + h_cost;
}
}
}
}
explored.add(n);
max_list_size = Math.max(max_list_size, frontier.size() + explored.size());
}
}

Add node values in binary tree

How do I print the sum of values under a node in a binary tree? Here's what I have so far:
public int sumT(Node nodo, int sum) {
if (nodo == null) {
return 0;
} else {
int sum = suma + nodo.getLeft().getValor();
int sum1 = sumT(nodo.getLeft(), sum);
int sum2 = sumT(nodo.getRight(), sum1);
return sum2;
}
}
public int sumT(Node nodo) {
if (nodo == null)
return 0;
return sumT(nodo.getLeft()) + sum(nodo.getRight()) + nodo.getValor();
}
This should be right. So you donĀ“t have to set the sum as an argument in sumT.

Categories