📜  计算二叉树中总和大于X的所有Grandparent-Parent-Child Triplets

📅  最后修改于: 2021-05-06 19:26:49             🧑  作者: Mango

给定一个整数X和一个二叉树,任务是计算节点的三元组三元组的数量,以使它们的总和大于X,并且它们具有祖父母->父->子关系。

例子:

Input: X = 100

               10
         /           \
       1              22
    /    \          /    \
  35      4       15       67
 /  \    /  \    /  \     /  \
57  38  9   10  110 312  131 414
                    /          \
                   8            39
Output: 6
The triplets are:
22 -> 15 -> 110
22 -> 15 -> 312
15 -> 312 -> 8
22 -> 67 -> 131
22 -> 67 -> 414
67 -> 414 -> 39

方法:可以使用滚动汇总为3的滚动汇总方法解决问题(祖父母->父->子)

  1. 遍历树的前序或后序(INORDER WO N’T WORK)
  2. 维护一个堆栈,其中我们保持滚动总和,滚动周期为3
  3. 每当堆栈中有3个以上的元素,并且如果最高值大于X时,我们将结果加1。
  4. 当我们向上移动递归树时,我们在堆栈上执行POP操作,以便从堆栈中删除所有较低级别的滚动总和。

下面是上述方法的实现:

Python3
# Python3 implementation of the approach
 
# Class to store node information
class Node:
    def __init__(self, val = None, left = None, right = None):
        self.val = val
        self.left = left
        self.right = right
 
# Stack to perform stack operations
class Stack:
    def __init__(self):
        self.stack = []
 
    @property
    def size(self):
        return len(self.stack)
 
    def top(self):
        return self.stack[self.size - 1] if self.size > 0 else 0
 
    def push(self, val):
        self.stack.append(val)
 
    def pop(self):
        if self.size >= 1:
            self.stack.pop(self.size - 1)
        else:
            self.stack = []
 
    # Period is 3 to satisfy grandparent-parent-child relationship
    def rolling_push(self, val, period = 3):
         
        # Find the index of element to remove
        to_remove_idx = self.size - period
 
        # If index is out of bounds then we remove nothing, i.e, 0
        to_remove = 0 if to_remove_idx < 0 else self.stack[to_remove_idx]
 
        # For rolling sum what we want is that at each index i,
        # we remove out-of-period elements, but since we are not
        # maintaining a separate list of actual elements,
        # we can get the actual element by taking diff between current
        # and previous element. So every time we remove an element,
        # we also add the element just before it, which is
        # equivalent to removing the actual value and not the rolling sum.
 
        # If index is out of bounds or 0 then we add nothing
        # i.e, 0, because there is no previous element
        to_add = 0 if to_remove_idx <= 0 else self.stack[to_remove_idx - 1]
 
        # If stack is empty then just push the value
        # Else add last element to current value to get rolling sum
        # then subtract out-of-period elements,
        # then finally add the element just before out-of-period element
        self.push(val if self.size <= 0 else val + self.stack[self.size - 1]
            - to_remove + to_add)
 
    def show(self):
        for item in self.stack:
            print(item)
 
 
# Global variables used by count_with_greater_sum()
count = 0
s = Stack()
 
def count_with_greater_sum(root_node, x):
    global s, count
 
    if not root_node:
        return 0
 
    s.rolling_push(root_node.val)
 
    if s.size >= 3 and s.top() > x:
        count += 1
 
    count_with_greater_sum(root_node.left, x)
    count_with_greater_sum(root_node.right, x)
 
    # Moving up the tree so pop the last element
    s.pop()
 
 
if __name__ == '__main__':
    root = Node(10)
 
    root.left = Node(1)
    root.right = Node(22)
 
    root.left.left = Node(35)
    root.left.right = Node(4)
 
    root.right.left = Node(15)
    root.right.right = Node(67)
 
    root.left.left.left = Node(57)
    root.left.left.right = Node(38)
 
    root.left.right.left = Node(9)
    root.left.right.right = Node(10)
 
    root.right.left.left = Node(110)
    root.right.left.right = Node(312)
 
    root.right.right.left = Node(131)
    root.right.right.right = Node(414)
 
    root.right.left.right.left = Node(8)
 
    root.right.right.right.right = Node(39)
 
    count_with_greater_sum(root, 100)
 
    print(count)


C++
// CPP implementation to print
// the nodes having a single child
#include 
using namespace std;
 
// Class of the Binary Tree node
struct Node
{
  int data;
  Node *left, *right;
 
  Node(int x)
  {
    data = x;
    left = right = NULL;
  }
};
 
// global variable
int cont = 0;
 
void preorder(Node* grandParent,
              Node* parent,
              Node* child,
              int sum)
{
  if(grandParent != NULL &&
     parent != NULL &&
     child != NULL &&
     (grandParent -> data +
      parent -> data +
      child->data) > sum)
  {
    cont++;
    //uncomment below lines if you
    // want to print triplets
    /*System->out->print(grandParent
      ->data+"-->"+parent->data+"-->
      "+child->data);
      System->out->println();*/
  }
  if(child == NULL)
    return;
   
  preorder(parent, child,
           child -> left, sum);
  preorder(parent, child,
           child -> right, sum);
}
 
//Driver code
int main()
{
  Node *r10 = new Node(10);
  Node *r1 = new Node(1);
  Node *r22 = new Node(22);
  Node *r35 = new Node(35);
  Node *r4 = new Node(4);
  Node *r15 = new Node(15);
  Node *r67 = new Node(67);
  Node *r57 = new Node(57);
  Node *r38 = new Node(38);
  Node *r9 = new Node(9);
  Node *r10_2 = new Node(10);
  Node *r110 = new Node(110);
  Node *r312 = new Node(312);
  Node *r131 = new Node(131);
  Node *r414 = new Node(414);
  Node *r8 = new Node(8);
  Node *r39 = new Node(39);
 
  r10 -> left = r1;
  r10 -> right = r22;
  r1 -> left = r35;
  r1 -> right = r4;
  r22 -> left = r15;
  r22 -> right = r67;
  r35 -> left = r57;
  r35 -> right = r38;
  r4 -> left = r9;
  r4 -> right = r10_2;
  r15 -> left = r110;
  r15 -> right = r312;
  r67 -> left = r131;
  r67 -> right = r414;
  r312 -> left = r8;
  r414 -> right = r39;
 
  preorder(NULL, NULL,
           r10, 100);
  cout << cont;
}
 
// This code is contributed by Mohit Kumar 29


Java
class Node{
    int data;
    Node left;
    Node right;
    public Node(int data)
    {
        this.data=data;
    }
}
 class TreeTriplet {
    static int count=0; // global variable
    public void preorder(Node grandParent,Node parent,Node child,int sum)
    {
        if(grandParent!=null && parent!=null && child!=null && (grandParent.data+parent.data+child.data) > sum)
        {
            count++;
            //uncomment below lines if you want to print triplets
            /*System.out.print(grandParent.data+"-->"+parent.data+"-->"+child.data);
            System.out.println();*/           
        }
        if(child==null)
          return;       
        preorder(parent,child,child.left,sum);
        preorder(parent,child,child.right,sum);       
    }
    public static void main(String args[])
    {       
        Node r10 = new Node(10);
        Node r1 = new Node(1);
        Node r22 = new Node(22);
        Node r35 = new Node(35);
        Node r4 = new Node(4);
        Node r15 = new Node(15);
        Node r67 = new Node(67);
        Node r57 = new Node(57);
        Node r38 = new Node(38);
        Node r9 = new Node(9);
        Node r10_2 = new Node(10);
        Node r110 = new Node(110);
        Node r312 = new Node(312);
        Node r131 = new Node(131);
        Node r414 = new Node(414);
        Node r8 = new Node(8);
        Node r39 = new Node(39);
         
        r10.left=r1;
        r10.right=r22;
        r1.left=r35;
        r1.right=r4;
        r22.left=r15;
        r22.right=r67;
        r35.left=r57;
        r35.right=r38;
        r4.left=r9;
        r4.right=r10_2;
        r15.left=r110;
        r15.right=r312;
        r67.left=r131;
        r67.right=r414;
        r312.left=r8;
        r414.right=r39;   
 
        TreeTriplet p = new TreeTriplet();
        p.preorder(null, null, r10,100);
        System.out.println(count);
}
     
     
}
 // This code is contributed by Akshay Siddhpura


Python
# Python3 program to implement
# the above approach
class Node:
     
    def __init__(self,
                 data):
         
        self.left = None
        self.right = None
        self.data = data       
 
# global variable
count = 0
     
def preorder(grandParent, parent,
             child, sum):
     
    global count
         
    if(grandParent != None and
       parent != None and
       child != None and
       (grandParent.data +
        parent.data +
        child.data) > sum):    
        count += 1
             
        # uncomment below lines if
        # you want to print triplets 
        # System.out.print(grandParent.
        # data+"-->"+parent.data+"-->
        # "+child.data); System.out.println();          
    if(child == None):
        return;
           
    preorder(parent, child,
             child.left, sum);
    preorder(parent, child,
             child.right, sum); 
     
# Driver code
if __name__ == "__main__":
     
    r10 = Node(10);
    r1 = Node(1);
    r22 = Node(22);
    r35 = Node(35);
    r4 = Node(4);
    r15 = Node(15);
    r67 = Node(67);
    r57 = Node(57);
    r38 = Node(38);
    r9 = Node(9);
    r10_2 = Node(10);
    r110 = Node(110);
    r312 = Node(312);
    r131 = Node(131);
    r414 = Node(414);
    r8 = Node(8);
    r39 = Node(39);
           
    r10.left = r1;
    r10.right = r22;
    r1.left = r35;
    r1.right = r4;
    r22.left = r15;
    r22.right = r67;
    r35.left = r57;
    r35.right = r38;
    r4.left = r9;
    r4.right = r10_2;
    r15.left = r110;
    r15.right = r312;
    r67.left = r131;
    r67.right = r414;
    r312.left = r8;
    r414.right = r39;    
   
    preorder(None, None,
             r10, 100)
    print(count);
         
# This code is contributed by Rutvik_56


C#
// C# program to find an index which has
// same number of even elements on left and
// right, Or same number of odd elements on
// left and right.
using System;
     
public class Node
{
    public int data;
    public Node left;
    public Node right;
    public Node(int data)
    {
        this.data = data;
    }
}
 
class GFG
{
    static int count = 0; // global variable
    public void preorder(Node grandParent,
                         Node parent,
                         Node child, int sum)
    {
        if(grandParent != null && parent != null &&
                 child != null && (grandParent.data +
                     parent.data + child.data) > sum)
        {
            count++;
             
            // uncomment below lines if you want to print triplets
            /*System.out.print(grandParent.data+"-->"+parent.data+"-->"+child.data);
            System.out.println();*/       
        }
        if(child == null)
            return;    
        preorder(parent,child,child.left,sum);
        preorder(parent,child,child.right,sum);    
    }
     
    // Driver Code
    public static void Main(String []args)
    {    
        Node r10 = new Node(10);
        Node r1 = new Node(1);
        Node r22 = new Node(22);
        Node r35 = new Node(35);
        Node r4 = new Node(4);
        Node r15 = new Node(15);
        Node r67 = new Node(67);
        Node r57 = new Node(57);
        Node r38 = new Node(38);
        Node r9 = new Node(9);
        Node r10_2 = new Node(10);
        Node r110 = new Node(110);
        Node r312 = new Node(312);
        Node r131 = new Node(131);
        Node r414 = new Node(414);
        Node r8 = new Node(8);
        Node r39 = new Node(39);
         
        r10.left = r1;
        r10.right = r22;
        r1.left = r35;
        r1.right = r4;
        r22.left = r15;
        r22.right = r67;
        r35.left = r57;
        r35.right = r38;
        r4.left = r9;
        r4.right = r10_2;
        r15.left = r110;
        r15.right = r312;
        r67.left = r131;
        r67.right = r414;
        r312.left = r8;
        r414.right = r39;
 
        GFG p = new GFG();
        p.preorder(null, null, r10,100);
        Console.WriteLine(count);
}
}
 
// This code is contributed by 29AjayKumar


输出:
6






高效的方法:可以通过维护3个变量来解决问题,这些变量称为祖父母,父母和孩子。可以在恒定空间中完成操作,而无需使用其他数据结构。

  1. 按顺序遍历树
  2. 维护3个变量,分别称为grandParent,parent和child
  3. 只要我们的总和超过目标,我们就可以增加计数或打印三元组。

下面是上述方法的实现:

C++

// CPP implementation to print
// the nodes having a single child
#include 
using namespace std;
 
// Class of the Binary Tree node
struct Node
{
  int data;
  Node *left, *right;
 
  Node(int x)
  {
    data = x;
    left = right = NULL;
  }
};
 
// global variable
int cont = 0;
 
void preorder(Node* grandParent,
              Node* parent,
              Node* child,
              int sum)
{
  if(grandParent != NULL &&
     parent != NULL &&
     child != NULL &&
     (grandParent -> data +
      parent -> data +
      child->data) > sum)
  {
    cont++;
    //uncomment below lines if you
    // want to print triplets
    /*System->out->print(grandParent
      ->data+"-->"+parent->data+"-->
      "+child->data);
      System->out->println();*/
  }
  if(child == NULL)
    return;
   
  preorder(parent, child,
           child -> left, sum);
  preorder(parent, child,
           child -> right, sum);
}
 
//Driver code
int main()
{
  Node *r10 = new Node(10);
  Node *r1 = new Node(1);
  Node *r22 = new Node(22);
  Node *r35 = new Node(35);
  Node *r4 = new Node(4);
  Node *r15 = new Node(15);
  Node *r67 = new Node(67);
  Node *r57 = new Node(57);
  Node *r38 = new Node(38);
  Node *r9 = new Node(9);
  Node *r10_2 = new Node(10);
  Node *r110 = new Node(110);
  Node *r312 = new Node(312);
  Node *r131 = new Node(131);
  Node *r414 = new Node(414);
  Node *r8 = new Node(8);
  Node *r39 = new Node(39);
 
  r10 -> left = r1;
  r10 -> right = r22;
  r1 -> left = r35;
  r1 -> right = r4;
  r22 -> left = r15;
  r22 -> right = r67;
  r35 -> left = r57;
  r35 -> right = r38;
  r4 -> left = r9;
  r4 -> right = r10_2;
  r15 -> left = r110;
  r15 -> right = r312;
  r67 -> left = r131;
  r67 -> right = r414;
  r312 -> left = r8;
  r414 -> right = r39;
 
  preorder(NULL, NULL,
           r10, 100);
  cout << cont;
}
 
// This code is contributed by Mohit Kumar 29

Java

class Node{
    int data;
    Node left;
    Node right;
    public Node(int data)
    {
        this.data=data;
    }
}
 class TreeTriplet {
    static int count=0; // global variable
    public void preorder(Node grandParent,Node parent,Node child,int sum)
    {
        if(grandParent!=null && parent!=null && child!=null && (grandParent.data+parent.data+child.data) > sum)
        {
            count++;
            //uncomment below lines if you want to print triplets
            /*System.out.print(grandParent.data+"-->"+parent.data+"-->"+child.data);
            System.out.println();*/           
        }
        if(child==null)
          return;       
        preorder(parent,child,child.left,sum);
        preorder(parent,child,child.right,sum);       
    }
    public static void main(String args[])
    {       
        Node r10 = new Node(10);
        Node r1 = new Node(1);
        Node r22 = new Node(22);
        Node r35 = new Node(35);
        Node r4 = new Node(4);
        Node r15 = new Node(15);
        Node r67 = new Node(67);
        Node r57 = new Node(57);
        Node r38 = new Node(38);
        Node r9 = new Node(9);
        Node r10_2 = new Node(10);
        Node r110 = new Node(110);
        Node r312 = new Node(312);
        Node r131 = new Node(131);
        Node r414 = new Node(414);
        Node r8 = new Node(8);
        Node r39 = new Node(39);
         
        r10.left=r1;
        r10.right=r22;
        r1.left=r35;
        r1.right=r4;
        r22.left=r15;
        r22.right=r67;
        r35.left=r57;
        r35.right=r38;
        r4.left=r9;
        r4.right=r10_2;
        r15.left=r110;
        r15.right=r312;
        r67.left=r131;
        r67.right=r414;
        r312.left=r8;
        r414.right=r39;   
 
        TreeTriplet p = new TreeTriplet();
        p.preorder(null, null, r10,100);
        System.out.println(count);
}
     
     
}
 // This code is contributed by Akshay Siddhpura

Python

# Python3 program to implement
# the above approach
class Node:
     
    def __init__(self,
                 data):
         
        self.left = None
        self.right = None
        self.data = data       
 
# global variable
count = 0
     
def preorder(grandParent, parent,
             child, sum):
     
    global count
         
    if(grandParent != None and
       parent != None and
       child != None and
       (grandParent.data +
        parent.data +
        child.data) > sum):    
        count += 1
             
        # uncomment below lines if
        # you want to print triplets 
        # System.out.print(grandParent.
        # data+"-->"+parent.data+"-->
        # "+child.data); System.out.println();          
    if(child == None):
        return;
           
    preorder(parent, child,
             child.left, sum);
    preorder(parent, child,
             child.right, sum); 
     
# Driver code
if __name__ == "__main__":
     
    r10 = Node(10);
    r1 = Node(1);
    r22 = Node(22);
    r35 = Node(35);
    r4 = Node(4);
    r15 = Node(15);
    r67 = Node(67);
    r57 = Node(57);
    r38 = Node(38);
    r9 = Node(9);
    r10_2 = Node(10);
    r110 = Node(110);
    r312 = Node(312);
    r131 = Node(131);
    r414 = Node(414);
    r8 = Node(8);
    r39 = Node(39);
           
    r10.left = r1;
    r10.right = r22;
    r1.left = r35;
    r1.right = r4;
    r22.left = r15;
    r22.right = r67;
    r35.left = r57;
    r35.right = r38;
    r4.left = r9;
    r4.right = r10_2;
    r15.left = r110;
    r15.right = r312;
    r67.left = r131;
    r67.right = r414;
    r312.left = r8;
    r414.right = r39;    
   
    preorder(None, None,
             r10, 100)
    print(count);
         
# This code is contributed by Rutvik_56

C#

// C# program to find an index which has
// same number of even elements on left and
// right, Or same number of odd elements on
// left and right.
using System;
     
public class Node
{
    public int data;
    public Node left;
    public Node right;
    public Node(int data)
    {
        this.data = data;
    }
}
 
class GFG
{
    static int count = 0; // global variable
    public void preorder(Node grandParent,
                         Node parent,
                         Node child, int sum)
    {
        if(grandParent != null && parent != null &&
                 child != null && (grandParent.data +
                     parent.data + child.data) > sum)
        {
            count++;
             
            // uncomment below lines if you want to print triplets
            /*System.out.print(grandParent.data+"-->"+parent.data+"-->"+child.data);
            System.out.println();*/       
        }
        if(child == null)
            return;    
        preorder(parent,child,child.left,sum);
        preorder(parent,child,child.right,sum);    
    }
     
    // Driver Code
    public static void Main(String []args)
    {    
        Node r10 = new Node(10);
        Node r1 = new Node(1);
        Node r22 = new Node(22);
        Node r35 = new Node(35);
        Node r4 = new Node(4);
        Node r15 = new Node(15);
        Node r67 = new Node(67);
        Node r57 = new Node(57);
        Node r38 = new Node(38);
        Node r9 = new Node(9);
        Node r10_2 = new Node(10);
        Node r110 = new Node(110);
        Node r312 = new Node(312);
        Node r131 = new Node(131);
        Node r414 = new Node(414);
        Node r8 = new Node(8);
        Node r39 = new Node(39);
         
        r10.left = r1;
        r10.right = r22;
        r1.left = r35;
        r1.right = r4;
        r22.left = r15;
        r22.right = r67;
        r35.left = r57;
        r35.right = r38;
        r4.left = r9;
        r4.right = r10_2;
        r15.left = r110;
        r15.right = r312;
        r67.left = r131;
        r67.right = r414;
        r312.left = r8;
        r414.right = r39;
 
        GFG p = new GFG();
        p.preorder(null, null, r10,100);
        Console.WriteLine(count);
}
}
 
// This code is contributed by 29AjayKumar
输出:
6






时间复杂度: O(n)