【问题标题】:Java pass by value and recursionJava传值和递归
【发布时间】:2014-10-09 08:04:47
【问题描述】:

我有简单的代码,可以打印树中特定节点的路径。我使用 java String 的实现如下

//using strings
public static void getPathS(Node node,String path,int key){
    if (node == null) {
        return;
    } else if(node.data == key) {
        System.out.println(path+" "+key);;
    }

    getPathS(node.left,path+" "+node.data,key);
    getPathS(node.right,path+" "+node.data,key);
}

假设有如下给出的树,

如果我在 3 上调用 getPathS,上面的实现会打印出来

1 34 3 //path from root to the element

如果我使用下面的 ArrayList 实现相同的方法

public static List getPath(Node node, List<Integer> path, int key) { 
    if (node == null) {
        //1 . path = new ArrayList<Integer>();
        path = new ArrayList<Integer>();
        // 2. or tried path.clear()  -- it should clear the path
        //return path;
        return null;
    } else if (node.data == key) {
        path.add(node.data);
        return path;
    }

    path.add(node.data);
    return nonNull(getPath(node.left, path, key), getPath(node.right, path, key));
}

private List nonNull(List path1, List path2) {
    if (path1 != null)
        return path1;
    if(path2 !=null )
        return path2;
    return null;
}

// class Node { Node left, Node right , int data; };
//Code to call getPath  
Node node = new Node(1);
node.left = new Node(2);
node.left.left = new Node(4);
node.right = new Node(34);
node.right.right = new Node(3);
System.out.println(getPath(node, new ArrayList(), 3));

在第二个实现中,我尝试了两种方法,当我们得到 NULL 节点时,在第一种方法中,如果我将新的 ArrayList 分配给路径,它会打印所有元素,即

[1, 2, 4, 34, 3]

如果我使用path.clear(),它只会打印最后一个元素,即要搜索的元素。

我们如何确保ArrayList 在递归中作为字符串工作?

【问题讨论】:

  • nonNull(arg1,arg2) 是什么?
  • 请检查更新的代码
  • 好的,谢谢。请第一时间贴出调用getPath()的代码。这里的问题是你正在向我猜的同一个列表中添加/删除元素。您需要使用某种回溯。几分钟后我会想出一些办法。
  • 仅供参考,您的新 nonNull() 方法的作用完全相同;-)

标签: java algorithm data-structures arraylist


【解决方案1】:

这里的问题是您在调用nonNull() 时不会考虑两个分支都失败。 这是一个考虑到这种可能性的更正,如果我们未能在其子节点中找到密钥,则删除当前节点的数据。

public static List<Integer> getPath(Node node, List<Integer> path, int key) {
    if (node == null) {
        return null;
    } else if (node.data == key) {
        path.add(node.data);
        return path;
    }
    path.add(node.data);

    // path is unchanged if nothing is found in left children
    if (getPath(node.left, path, key) != null || getPath(node.right, path, key) != null) {
        // found in one branch or the other
        return path;
    }

    // not found in either branch, remove our data
    path.remove(path.size() - 1);
    return null;
}

当然,看起来我们正在处理不同的列表,但只有一个:第一次作为参数提供的那个。这就是为什么应该从中删除数据的原因。你需要清楚你的论点。


一种更简洁的解决方案,强调只有一个列表这一事实。

/**
 * Appends to the specified list all keys from {@code node} to the {@link Node} containing the
 * specified {@code key}. If the key is not found in the specified node's children, the list is
 * guaranteed to be unchanged. If the key is found among the children, then the specified list
 * will contain the new elements (in addition to the old ones).
 * 
 * @param node
 *            the node to start at
 * @param path
 *            the current path to append data to
 * @param key
 *            the key to stop at
 * @return true if the key was found among the specified node's children, false otherwise
 */
public static boolean getPath(Node node, List<Integer> path, int key) {
    if (node == null) {
        // leaf reached, and the key was not found
        return false;
    }

    // add data to the path
    path.add(node.data);

    // the OR is lazy here, so we treat everything in the given order
    // if getPath failed on the left children, path is unchanged and used for right children
    if (node.data == key || getPath(node.left, path, key) || getPath(node.right, path, key)) {
        // the key is found in the current node, its left children, or its right children
        return true;
    }

    // not found in either branch, remove our data
    path.remove(path.size() - 1);
    return false;
}

请注意,我没有使用path.remove(node.data),因为可能有多个节点包含该数据,并且第一个节点将被删除而不是最后一个。

【讨论】:

  • 其实我想出了一个更好的解决方案(更干净),我会在一分钟内发布它
猜你喜欢
  • 2016-03-15
  • 1970-01-01
  • 2013-07-22
  • 2021-06-18
  • 2012-11-12
  • 1970-01-01
  • 2011-05-02
  • 2019-08-04
  • 1970-01-01
相关资源
最近更新 更多