【问题标题】:Sum of K smallest elements in Binary search Tree二叉搜索树中K个最小元素的总和
【发布时间】:2017-05-04 12:14:46
【问题描述】:

任何人都可以建议,以下代码用于查找 BST 中 k 个最小元素的总和有什么问题?它返回树中所有节点的总和。

public int findSum(Node root, int k){
            int count = 0;
            return findSumRec(root, k, count);
        }

        private int findSumRec(Node root, int k, int count) {

            if(root == null)
                return 0;
            if(count > k)
                return 0;

            int sum = findSumRec(root.left, k, count);
            if(count >= k)
                return sum;

            sum += root.data;
            count++;

            if(count >= k)
                return sum;
            return sum + findSumRec(root.right, k, count);
            }

【问题讨论】:

  • 我会重用代码进行中序遍历,以便将遍历限制为仅 7 个元素
  • 什么是预期输出的示例输入?你得到的是什么输出?
  • 您的代码正在将树中的所有数字相加,验证它是否最小的逻辑在哪里
  • @Saurabh Jhunjhunwala :我使用了中序遍历方法。时刻计数等于 k(直到我需要找到总和),总和被返回。

标签: java algorithm recursion binary-search-tree


【解决方案1】:

嗯,Java 是一种按值传递的语言,因此在一个方法调用中更改count 的值不会更改调用它的方法的count 的值。

假设在递归过程中的某个时刻,当k5 并且count4 时,您正在调用:

        int sum = findSumRec(root.left, 5, 4);

假设此调用将传递给它的count 增加到5,并返回一些sum

现在您回到调用findSumRec(root.left, 5, 4) 的方法并检查:

        if(4 >= 5)
            return sum;

即使最近返回的递归调用将count 带到5,这意味着你应该完成,调用者仍然将count 视为4(因为它不是同一个count 变量),因此树的遍历将继续,直到您访问树的所有节点并将所有节点求和。

您必须使用一些可变实例来修改count

例如,您可以使用具有单个元素的数组:

public int findSum(Node root, int k){
    int[] count = {0};
    return findSumRec(root, k, count);
}

private int findSumRec(Node root, int k, int[] count) {
    ...
    change each count to count[0]
    ...
}

编辑:我刚刚用我建议的更正测试了你的代码,它可以工作。

public int findSum(Node root, int k) {
    int[] count = {0};
    return findSumRec(root, k, count);
}

private int findSumRec(Node root, int k, int[] count) {

    if(root == null)
        return 0;
    if(count[0] > k)
        return 0;

    int sum = findSumRec(root.left, k, count);
    if(count[0] >= k)
        return sum;

    sum += root.val;
    count[0]++;

    if(count[0] >= k)
        return sum;
    return sum + findSumRec(root.right, k, count);
}

关键是所有对findSumRec 的递归方法调用必须共享count 变量的值并且能够更改它。当count 是传递给方法的原始变量时,这是不可能的,因为每个方法都会获得该变量的不同副本。

使用数组是一种选择。另一种选择是使用包含您的方法的类的成员变量,而不是将其作为参数传递。这样它仍然可以是int

【讨论】:

  • 您能否详细说明一下。因为根据我的理解,只有初始调用使用“count = 0”。发布第一次调用,剩余的所有递归调用将使用更新后的计数值(每个节点添加的计数++)完成。
  • @aman_coder 我详细说明了我的答案。我用我的修复测试了你的代码,它可以工作,所以这是唯一的问题。
【解决方案2】:

我想你正在寻找这样的东西,这是我在 java 中的代码

import java.io.*;

public class Main {

  public static class Node {
    int val;
    Node left;
    Node right;
    public Node(int data) {
      this.val = data;
      this.left = null;
      this.right = null;
    }
  }

  public static int sum_ans = 0;

  public static int count_k_smallest_sum(Node root, int count, int k)
  {
    if(count>=k)
    {
      return 100005;
    }
    if(root.left == null && root.right == null)
    {
      sum_ans += root.val;
      return count+1;
    }
    int cnt = count;
    if(root.left != null)
    {
      cnt = count_k_smallest_sum(root.left, cnt, k);
    }
    if(cnt >= k)
    {
      return 100005;
    }
    sum_ans += root.val;
    cnt++;

    if(cnt >= k)
    {
      return 100005;
    }

    if(root.right != null)
    {
      cnt = count_k_smallest_sum(root.right, cnt, k);
    }

    return cnt;
  }

  public static void main(String args[]) throws Exception {
    Node root = new Node(10);
    Node left1 = new Node(5);
    Node right1 = new Node(11);
    Node left2 = new Node(3);
    Node right2 =new Node(12);
    Node left3 = new Node(2);
    Node right3 = new Node(7);
    Node right4 = new Node(4);
    root.left = left1;
    root.right = right1;
    right1.right = right2;
    left1.left = left2;
    left1.right = right3;
    left2.left = left3;
    left2.right = right4;
    int cnt = count_k_smallest_sum(root, 0, 3);
    System.out.println(sum_ans);
  }
}

在方法中查看我的代码逻辑 - count_k_smallest_sum。

希望这会有所帮助!

【讨论】:

  • 嘿@zenwraight,感谢您提供解决方案,它也工作得很好。但是,我有兴趣在我尝试实施的方法中找到错误。我只是想使用递归中序遍历方法来实现这一点(与您的非常相似)。 Eran 提供的建议可能对此有所帮助,但我仍然有一些疑问。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-01-20
  • 1970-01-01
  • 2021-12-21
  • 1970-01-01
  • 2011-11-11
  • 1970-01-01
相关资源
最近更新 更多