在通用树中查找下一个更大的节点?

时间:2017-04-04 14:31:50

标签: java algorithm data-structures tree

我必须找到并返回通用树中的下一个更大的节点,几乎所有的测试用例都运行正常并给出正确的输出,只有一个测试用例出错了,它可能是任何东西。我已多次调试我的程序,无法弄清楚可能出现的错误是什么?实际上我在做什么我正在比较递归为我提取的所有下一个更大的节点并将它们相互比较并最终找到正确的节点?我会受到一点帮助,不胜感激。

代码

 /* TreeNode structure 
    class TreeNode<T> {
    T data;
    ArrayList<TreeNode<T>> children;

    TreeNode(T data){
        this.data = data;
        children = new ArrayList<TreeNode<T>>();
    }
}*/




public static TreeNode<Integer> findNextLargerNode(TreeNode<Integer> root, int n){

    if(root==null)
    return root;

    if(root.children.size()==0)
    {
        if(root.data>n)
        {
            return root;
        }

        else
        return null;

    }

    TreeNode<Integer> count[] = new TreeNode[root.children.size()];

    for(int i=0;i<root.children.size();i++)
    {
        count[i] = findNextLargerNode(root.children.get(i),n);
    }

    int nextLarger=Integer.MAX_VALUE;
    TreeNode<Integer> next = null;


    for(int i=0;i<count.length;i++)
    {
        if(count[i]!=null)
        {
            if(count[i].data>n && count[i].data<nextLarger)
            {
                nextLarger = count[i].data;
                next = count[i];
            }
        }
    }

    if(next!=null)
    {


        if(root.data>n && root.data<next.data)
        return root;
        else
        return next;

    }
    else 
    return null;

}

4 个答案:

答案 0 :(得分:1)

我看到一个极端测试可能会失败:如果正确答案是一个包含数据Integer.MAX_VALUE的节点,那么您的代码将返回null而不是该节点。

对代码进行最少更改的解决方案是替换:

count[i].data<nextLarger

使用:

count[i].data<=nextLarger

这样,即使nextcount[i].data,您仍然可以为Integer.MAX_VALUE提供非空值。

注意:如果要将两个for循环合并为一个循环,则不需要使用count数组,而只需要使用单个节点变量。

答案 1 :(得分:1)

最后,我在代码中发现了这个错误。它位于以下部分。

if(next!=null)
{
    if(root.data>n && root.data<next.data)
    return root;
    else
    return next;

}
else 
return null;

假设next == null然后else将被执行,这将返回null。这是错误的,因为root也可能是下一个更大的节点,因此我还必须检查该条件

正确的版本是:

if(next!=null)
    {
        if(root.data>n && root.data<next.data)
        return root;
        else
        return next;

    }
    else 
    {
        if(root.data>n)
        return root;
        else 
        return null;
    }

答案 2 :(得分:1)

尝试

public class Test {

    class TreeNode<T> {
        T data;
        List<TreeNode<T>> children;

        TreeNode(T data) {
            this.data = data;
            children = new ArrayList<TreeNode<T>>();
        }
        public  TreeNode<T> findNextNode(T n,Comparator<T> comp) {
            if (comp.compare(data , n) < 0) {
                return this;
            }
            if (children.size() == 0) {
                return null;
            }
            for (int i = 0; i < children.size(); i++) {
                TreeNode<T> node= children.get(i).findNextNode(n,comp);
                if(node!=null)return node;
            }
            return null;
        }
    }

说明:

测试

要在代码中显示一些错误,我在testForYourCode中提供test(见下文)。测试返回意外结果。值为4的第二个孩子胜出错误

TreeNode<T>.findNextNode中,我提供了“重构”版本。不确定它是否符合您的要求。两个测试testForModifiedCodetestForModifiedCodeComplex显示了refactored版本的行为方式。

通用

我没有编写只能处理TreeNode<Integer>的函数,而是决定编写一个适用于所有类型的泛型函数。

比较

将实际比较委托给Comparator对象。必须将Comparator的实例传递给findNextNode方法。这可以使用Java 8 lambda语法即时完成,例如(a,b)->{return b-a;}。这为实现增加了一些灵活性。通过更改比较器,您还可以使用(a,b)->{return a-b;}搜索“下一个较小节点”。

它做什么

如果入口节点满足Comparator.compare实现定义的条件,则算法将停止。否则,从第一个子节点开始执行深度搜索(等等)。一旦节点与比较标准匹配,算法就会停止。如果没有节点匹配,则返回null。

package stack43210199;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

import org.junit.Assert;

public class Test {

    class TreeNode<T> {
        T data;
        List<TreeNode<T>> children;

        TreeNode(T data) {
            this.data = data;
            children = new ArrayList<TreeNode<T>>();
        }
        public  TreeNode<T> findNextNode(T n,Comparator<T> comp) {
            if (comp.compare(data , n) < 0) {
                return this;
            }
            if (children.size() == 0) {
                return null;
            }
            for (int i = 0; i < children.size(); i++) {
                TreeNode<T> node= children.get(i).findNextNode(n,comp);
                if(node!=null)return node;
            }
            return null;
        }
    }

    @org.junit.Test
    public void testForYourCode() {
        TreeNode<Integer> root = buildNode(0);
        TreeNode<Integer> firstChild = buildNode(5);
        TreeNode<Integer> secondChild = buildNode(4);
        TreeNode<Integer> thirdChild = buildNode(5);
        root.children.add(firstChild);
        root.children.add(secondChild);
        root.children.add(thirdChild);
        //Arrg - not as expected
        Assert.assertEquals(secondChild, findNextLargerNode(root, 0));
    }

    @org.junit.Test
    public void testForModifiedCode() {
        TreeNode<Integer> root = buildNode(2);
        TreeNode<Integer> firstChild = buildNode(5);
        TreeNode<Integer> secondChild = buildNode(4);
        TreeNode<Integer> thirdChild = buildNode(5);
        TreeNode<Integer> fourthChild = buildNode(1);
        root.children.add(firstChild);
        root.children.add(secondChild);
        root.children.add(thirdChild);
        thirdChild.children.add(fourthChild);
        //find next greater
        Assert.assertEquals(firstChild, root.findNextNode(2,(a,b)->{return b-a;}));
        //find next lesser
        Assert.assertEquals(fourthChild, root.findNextNode(2,(a,b)->{return a-b;}));
        }

    @org.junit.Test
    public void testForModifiedCodeComplex() {
        TreeNode<Integer> root = buildNode(2);
        TreeNode<Integer> firstChild = buildNode(2);
        TreeNode<Integer> secondChild = buildNode(4);
        TreeNode<Integer> thirdChild = buildNode(5);
        TreeNode<Integer> fourthChild = buildNode(1);
        TreeNode<Integer> sixthChild = buildNode(8);
        firstChild.children.add(fourthChild);
        firstChild.children.add(sixthChild);
        root.children.add(firstChild);
        root.children.add(secondChild);
        root.children.add(thirdChild);
        //find next greater
        Assert.assertEquals(sixthChild, root.findNextNode(2,(a,b)->{return b-a;}));
        //find next lesser
        Assert.assertEquals(fourthChild, root.findNextNode(2,(a,b)->{return a-b;}));
    }

    private TreeNode<Integer> buildNode(int i) {
        return new TreeNode<Integer>(new Integer(i));
    }

    public static TreeNode<Integer> findNextLargerNode(TreeNode<Integer> root, int n) {

        if (root == null)
            return root;

        if (root.children.size() == 0) {

            if (root.data > n) {
                return root;
            }

            else
                return null;

        }

        TreeNode<Integer> count[] = new TreeNode[root.children.size()];

        for (int i = 0; i < root.children.size(); i++) {
            count[i] = findNextLargerNode(root.children.get(i), n);
        }

        int nextLarger = Integer.MAX_VALUE;
        TreeNode<Integer> next = null;

        for (int i = 0; i < count.length; i++) {
            if (count[i] != null) {
                if (count[i].data > n && count[i].data < nextLarger) {
                    nextLarger = count[i].data;
                    next = count[i];
                }
            }
        }

        if (next != null) {
            if (root.data > n && root.data < next.data)
                return root;
            else
                return next;

        } else {
            if (root.data > n)
                return root;
            else
                return null;
        }
    }


}

答案 3 :(得分:0)

TreeNode通常看起来像这样。

class TreeNode<T extends Comparable<T>> {
    T data;
    TreeNode<T> left, right;

    TreeNode(T data){
        this.data = data;
    }

    public TreeNode<T> findNextLargerNode(T t) {
        if (data.compareTo(t) <= 0)
            return right == null ? null : right.findNextLargerNode(t);
        T found = left == null ? null : left.findNextLargerNode(t);
        return found == null ? this : found;
    }
}