首页 > 试题广场 >

树上摘樱桃

[编程题]树上摘樱桃
  • 热度指数:1681 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解
有一棵二叉树,树上的叶子节点定义为“樱桃”。现在需要找出树上有多少个满足如下子结构的“樱桃”串,即一串上刚好有两颗“樱桃”。

比如如下的一棵树,红框标示的有两个符合要求的结构,答案就是2



又比如下面的这颗树,没有任何符合要求的子结构,则答案是0



输入描述:
第一行两个正整数m, n,空格分开,分别代表总共有树上有多少个节点,和树上有多少条边,2<=m<=100,  1<=n<=100
下面有n行,每行为3个部分,用空格分割,第一个数字为某非叶子节点的id, 第二个为该边为left还是right,第三个为子节点的id
注意:节点id彼此不会重复,id 1为根节点 


输出描述:
一个整数,标示符合要求的子结构的数量
示例1

输入

10 9
1 left 2
1 right 3
2 left 4
2 right 5
3 right 6
6 left 7
6 right 8
8 left 9
8 right 10

输出

2

说明

如题目说明的第一个样例图,可以看到,2-4-5子串,8-9-10子串,两个子串符合条件,所以答案为2
使用map这种数据结构就能够轻松解决
m, n = map(int, input().strip().split())
# 利用字典记录所有节点及其左右子节点
tree = dict()
for _ in range(n):
    parent, _, child = input().strip().split()
    if parent not in tree:
        tree[parent] = child
    else:
        tree[parent] += " " + child
count = 0
# 遍历所有的非叶子节点
for key in tree:
    if len(tree[key].split()) == 1:
        # 如果该节点没有两个子节点,则跳过
        continue
    else:
        # 否则检验该节点的两个叶子节点是否都是叶子节点,如果都不在字典中,则都为叶子节点,计数+1
        left, right = tree[key].split()
        if left not in tree and right not in tree:
            count += 1
print(count)


发表于 2021-01-18 12:24:13 回复(0)
let mn = readline().split(' ')
let m = mn[0],n = mn[1]
let line
let arr = []
let j = 0
while(line = readline()) {
    arr[j++] = line.trim().split(' ')//变成一个二维数据
}
let count = 0
let map = new Map()
for(let i = 0;i<arr.length;i++) {
    let j = 0
    map.has(arr[i][j]) ? map.set(arr[i][j],map.get(arr[i][j])+1):map.set(arr[i][j],1)
}
let x = 0
for(let i = 0;i<arr.length -1;i++) {
    let j  = 2
    if(!map.has(arr[i][j]) && !map.has(arr[i+1][j]) && (arr[i][0] == arr[i+1][0])) {
        count++
    }
}
console.log(count)
发表于 2021-07-08 21:52:16 回复(3)
const readline = require("readline")
 
const rl = readline.createInterface({
  input:process.stdin,
  output: process.stdout
})
 
const rows = []
let m, n// 节点数 边数
const obj = {}
let result = 0
 
rl.on("line", line => {
  rows.push(line)
  if (rows.length === 1) {
    const arr1 = line.trim().split(" ").map(item => parseInt(item))
    m = arr1[0]
  } else {
    const arr2 = line.trim().split(" ").map(item => parseInt(item))
    if (!obj[arr2[0]]) obj[arr2[0]] = []
    obj[arr2[0]].push(arr2[2])
  }
  if (rows.length === m) {
    // console.log(obj)
    for(let key in obj) {
      if (obj[key].length == 2 && obj[obj[key][0]] != 0 && !obj[obj[key][1]] != 0) {
        result += 1
      }
    }
    console.log(result)
    rows.length = 0
  }
})

发表于 2021-02-08 13:52:23 回复(0)
#include<iostream>
#include<vector>
#include<string>
using namespace std;
 
class Node{
public:
    Node *left = NULL, *right = NULL;
};
 
int numOfCherries(Node* root){
    if(!root) return 0;
    if(!root->left) return numOfCherries(root->right);
    if(!root->right) return numOfCherries(root->left);
    if(!root->left->left && !root->left->right && !root->right->left && !root->right->right) return 1;
    return numOfCherries(root->left) + numOfCherries(root->right);
}
 
int main(){
    int m, n;
    cin >> m >> n;
    //用vector里的index表示id,因为id从1开始,所以size为m+1
    vector<Node*> a(m+1);
    for(int i = 0; i < m+1; i++){
        a[i] = new Node();
    }
    for(int i = 0; i < n; i++){
        int id;
        cin >> id;
        string position;
        cin >> position;
        int child;
        cin >> child;
        if(position[0] == 'l'){
            a[id]->left = a[child];
        }
        else{
            a[id]->right = a[child];
        }
    }
    cout << numOfCherries(a[1]);
    return 0;
}

发表于 2021-08-20 23:45:13 回复(0)
#include<bits/stdc++.h>
using namespace std;
//首先构建二叉树并记录孩子节点数量,再遍历二叉树找出叶子节点
struct TreeNode{
    int val;
    int children;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int v):val(v),children(0),left(nullptr),right(nullptr){}
};

int main(){
    int m,n;
    while(cin >> m >> n){
        
        int root,child;
        string edge;
        queue<TreeNode*> q;
        TreeNode* head = new TreeNode(1);
        q.push(head);
        TreeNode* cur = head;
        while(n--)
        {
            cin >> root >> edge >> child;
            while(!q.empty() && q.front()->val != root)
            {
                q.pop();
            }
            cur = q.front();
            cur->children++;
            TreeNode* node = new TreeNode(child);
            q.push(node);
            if(edge == "left"){
                cur -> left = node;
            } else{
                cur -> right = node;
            }
        }
        
        int res = 0;
        while(!q.empty()){
            q.pop();
        }
        q.push(head);
        while(!q.empty()){
            cur = q.front();
            q.pop();
            if(cur->left){
                q.push(cur->left);
            }
            if(cur->right){
                q.push(cur->right);
            }
            if(cur->children == 2){
                if(cur->left->children==0 && cur->right->children==0){
                    res++;
                }
            }
        }
        
        cout << res << endl;
    }
}
发表于 2021-04-07 13:42:40 回复(0)
#include<iostream>
#include<string>
using namespace std;
#define m 10


//节点类
class m_point
{
public:
    int id;
    int left_id;
    int right_id;
    string m_style;     
};
m_point Charry[m];    //节点数组

//樱桃节点个数查找
int CharryFind()
{
    int result = 0;
    int j = 0;    //用于记录叶子节点个数
    int S_arr[m] = { 0 };    //叶子节点id记录数组
    //查找叶子节点
    for (int i = 1; i <= m; i++)
    {
        if ((Charry[i].left_id == 0) && (Charry[i].right_id == 0))
        {
            Charry[i].m_style = "S";        //叶子节点标记
            S_arr[j] = i;
            j++;
        }
        else
            Charry[i].m_style = "F";          //非叶子节点标记
    }
    cout << "叶子节点个数为:" << j << endl;
    //查找非叶子节点左右两边是否为叶子节点
    for (int i = 1; i <= m; i++)
    {
        if (Charry[i].m_style != "S")
        {
            for (int k = 1; k <= j; k++)
            {
                if (Charry[i].left_id == S_arr[k])
                {
                    for (int n = 1; n <= j; n++)
                    {
                        if (Charry[i].right_id == S_arr[n])
                            result++;
                    }
                }
            }
        }
    }
    return result;
}

//初始化节点
void CharryInit()
{

    for (int i = 1; i <= m; i++)
    {
        Charry[i].id = i;
        Charry[i].left_id = 0;
        Charry[i].right_id = 0;
    }
    Charry[1].left_id = 2;
    Charry[1].right_id = 3;

    Charry[2].left_id = 4;
    Charry[2].right_id = 5;

    Charry[3].right_id = 6;

    Charry[6].left_id = 7;
    Charry[6].right_id = 8;

    Charry[8].left_id = 9;
    Charry[8].right_id = 10;

}

int main()
{
    CharryInit();
    cout << "樱桃数为:" << CharryFind() << endl;
    return 0;
}
发表于 2022-08-18 20:09:03 回复(0)
#include <bits/stdc++.h>
using namespace std;

struct TreeNode {
    int id;
    TreeNode* left;
    TreeNode* right;
    TreeNode(int _id) : id(_id), left(nullptr), right(nullptr) {}
};

int main() {
    int m, n;
    cin >> m >> n;
    int id1, id2;
    string relationship;
    // 为了节点id直接和下标对应,增加一个,不使用0下标
    vector<TreeNode*> nodes(m + 1, nullptr);
    while (cin >> id1 >> relationship >> id2) {
        if (nodes[id1] == nullptr) {
            TreeNode* node = new TreeNode(id1);
            nodes[id1] = node;
        }
        if (nodes[id2] == nullptr) {
            TreeNode* node = new TreeNode(id2);
            nodes[id2] = node;
        }
        if (relationship == "left") {
            nodes[id1]->left = nodes[id2];
        } else {
            nodes[id1]->right = nodes[id2];
        }
    }
    int count = 0;
    for (int i = 1; i < nodes.size(); ++i) {
        auto node = nodes[i];
        if (node->left != nullptr && node->right != nullptr) {
            if (node->left->left == nullptr && node->left->right == nullptr &&
               node->right->left == nullptr && node->right->right == nullptr) {
                count++;
            }
        }
    }
    cout << count << endl;
    return 0;
}

发表于 2022-06-15 14:56:19 回复(0)
from collections import defaultdict
 
count = 0
node_dict = defaultdict(list)
for _ in range(int(input().split(' ')[1])):
    temp = input().split(' ')
    node_dict[int(temp[0])].append(int(temp[2]))
for leaves in node_dict.values():
    if len(leaves) == 2 and leaves[0] not in node_dict and leaves[1] not in node_dict:
        count +=1
print(count)


发表于 2022-05-23 16:37:30 回复(0)
// 判断子节点是否作为父节点出现过
#include <iostream>
#include <vector>
using namespace std;


int main(){
    int nums = 0;
    int node = 0;
    cin >> nums >> node;
    int ans = 0;
    vector<vector<int>> leaves(nums + 1);
    int a = 0;
    int b = 0;
    string pos;
    for(int i = 0; i < node; ++i){
        cin >> a >> pos >> b;
        leaves[a].push_back(b);
    }

    for(auto i : leaves){
        if(i.size() == 2){
            if(leaves[i[0]].empty() && leaves[i[1]].empty()){
                ans++;
            }
        }
    }
    cout << ans << endl;

    return 0;
}

发表于 2022-04-30 10:48:46 回复(0)
ss = input().strip().split()
m = int(ss[0])
n = int(ss[1])
roots = []
for i in range(m):
    roots.append([None,None])
for i in range(n):
    ss = input().strip().split()
    parent = int(ss[0])-1
    string = ss[1]
    child = int(ss[2])-1
    if string == 'left':
        roots[parent][0]=child
    else:
        roots[parent][1]=child

nums = 0
for i in range(m):
    if (roots[i][0]!=None) and (roots[i][1]!=None):
        if ((roots[roots[i][0]][0])==None) and ((roots[roots[i][0]][1])==None) and ((roots[roots[i][1]][0])==None) and ((roots[roots[i][1]][1])==None):
            nums+=1
print(nums)
发表于 2022-04-26 21:37:51 回复(0)
// 子结构的数量的充分必要条件是node可以作为两个节点的父节点,且这两个节点没有对应的子节点。
// 不用创建树,使用两个哈希表
#include <bits/stdc++.h>
using namespace std;
int main()
{
    int m,n;
    cin >> m >> n;
    unordered_map<int, pair<int,int>> children;
    unordered_map<int,int> parent;
    for(int i = 0 ;i < n;i++)
    {
        int a,b;
        string str;
        cin >> a >> str >> b;
        if(children.find(a) == children.end())
            children[a] = make_pair(b, 0xffffff);
        else
            children[a].second = b;
        parent[a]++;
    }
    int ret = 0;
    for(auto it = children.begin(); it != children.end(); it++)
        if(it->second.second != 0xffffff)
            if(parent.find(it->second.first) == parent.end() && parent.find(it->second.second) == parent.end())
                ret++;
    cout << ret << endl;
    return 0;
}

发表于 2022-03-25 21:55:05 回复(0)
import java.util.*;
public class Test {



    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String number = sc.nextLine();
        String[] numbers = number.split(" ");
        int n = Integer.parseInt(numbers[0]);
        int sides = Integer.parseInt(numbers[1]);
        int[][] nums=new int[n + 1][2];
        int[] sons = new int[n + 1];
        int count = 0;
        for (int i = 0; i < sides; i++) {
            String str = sc.nextLine();
            String[] strs = str.split(" ");
            int index = Integer.parseInt(strs[0]);
            int sonIndex = Integer.parseInt(strs[2]);
            sons[index]++;
            if ("left".equals(strs[1])){
                nums[index][0] = sonIndex;
            }else nums[index][1] = sonIndex;
        }
        for (int i = 1; i < n+1; i++) {
            if (sons[i] == 2) {
                if (sons[nums[i][0]] == 0 && sons[nums[i][1]] == 0){
                    count++;
                }
            }
        }
        System.out.println(count);

    }




}

发表于 2022-03-17 10:17:03 回复(0)
把每个节点存到数组里面,数组里面一个指向左孩子,一个指右孩子,每一行输入都是输入了一个节点和他的孩子,然后只要哪个节点的左右孩子都是叶子节点,计数器加一
#include<stdio.h>
typedef struct BiTnode{
	int lchild;
	int rchild;
	int id;
	
	//int *parent;
}BiTnode,BiTree;
int main(void){
	int m;	int n; char temp;	int left;	int right;
	scanf("%d",&m);	scanf("%c",&temp);	scanf("%d",&n);
	BiTree a[m+1];
	for(int i=0;i<m+1;i++){
		a[i].id=0;
		a[i].lchild=0;
		a[i].rchild=0;
	}
	//printf("%d\t",a[2].id);printf("%d\t",a[2].lchild);printf("%d\t",a[2].rchild);
	for(int i=0;i<n;i++){
		int num;	char str[4];
		scanf("%d",&num);
		scanf("%s",str);
//		printf("%s",str);
		//a[i]->id=i;
		a[num].id=num;
//		printf("%s",str);
		if(str[0]=='l'){
//			printf("%s",str);
			scanf("%d",&left);
			//printf("%d\n",left);
			a[num].lchild=left;
		//	printf("%d",a[1].lchild);
		}else if(str[0]=='r'){
			scanf("%d",&right);
			a[num].rchild=right;
			//printf("%d",a[num].rchild);
		}
	}
	int number=0;
	for(int i=0;i<m;i++){
		//printf("123");
		if((a[i].lchild!=0)&&(a[i].rchild!=0)&&(a[a[i].lchild].lchild==0)&&(a[a[i].lchild].rchild==0)&&(a[a[i].rchild].lchild==0)&&(a[a[i].rchild].rchild==0))
		{
			number++;
			//printf("123");
	}	
	}
	/*printf("%d\t",a[1].lchild);
	printf("%d\t",a[1].rchild);
	
	printf("%d\t",a[a[1].lchild].lchild);printf("%d\t",a[a[1].lchild].rchild);
	
	printf("%d\t",a[a[1].rchild].lchild);printf("%d\t",a[a[1].rchild].rchild);*/
	printf("%d",number);
	return 0;
}

发表于 2022-03-13 20:52:38 回复(0)
m,n=map(int,input().strip().split())

class TreeNode():
    def __init__(self,val=0,left=None,right=None):
        self.val=val
        self.left=left
        self.right=right
tmp=[]
for i in range(n):
    father,direction,son=input().strip().split()
    tmp.append((int(father),direction,int(son)))
used=[None for _ in range(m+1)]
for bian in tmp:
    father,direction,son=bian
    if not used[father]:
        root=TreeNode()
        used[father]=root
    else:
        root=used[father]
    if not used[son]:
        node=TreeNode()
        used[son]=node
    else:
        node=used[son]
    if direction=='left':
        root.left=node
    else:
        root.right=node
ret=0
def dfs(root):
    global ret
    if not root:
        return 0
    if not root.left and not root.right:
        return 1
    l=dfs(root.left)
    r=dfs(root.right)
    if l==1 and r==1:
        ret+=1
    return l+r+1
dfs(used[1])
print(ret)
       
给了根是哪个和所有的边,那就自己构建一个树吧。
然后一次后序遍历
发表于 2022-03-07 12:58:48 回复(0)
import java.io.*;
import java.lang.reflect.Array;
import java.util.*;
import java.util.stream.*;
 
public class Main{
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while(sc.hasNext()) {
            String firstLine = sc.nextLine();
            String[] nums = firstLine.split(" ");
            int m = Integer.parseInt(nums[0]);
            int n = Integer.parseInt(nums[1]);
            int[] degree = new int[m + 1];
            Arrays.fill(degree,0);
            Map<Integer,Integer> fathers = new HashMap<>();
            for(int i = 0 ;i < n;i ++) {
                String line = sc.nextLine();
                String[] segs = line.split(" ");
                int parent = Integer.parseInt(segs[0]);
                int son = Integer.parseInt(segs[2]);
                degree[parent] ++;
                fathers.put(son,parent);
            }
          int[] arr = IntStream.range(1,m + 1)
                    .filter(i -> degree[i] == 0)
                    .map(e -> fathers.get(e)).toArray();
          long ret = IntStream.of(arr).count()
                   - IntStream.of(arr).distinct().count();
          System.out.println(ret);
        }
    }
}

编辑于 2021-08-21 15:35:29 回复(0)
line = input().split()
node_num = int(line[0])
bian_num = int(line[1])
class TreeNode:
    def __init__(self,val):
        self.left = None
        self.right = None
        self.val = val
        
def postorder(node):
    if not node:
        return 0
    if not node.left and not node.right:
        return 1
    l = postorder(node.left)
    r = postorder(node.right)
    if l == 1 and r == 1:
        return 2
    l = 0 if l < 2 else l
    r = 0 if r < 2 else r
    return l + r

dic = dict()
for num in range(1,node_num+1):
    dic[num] = TreeNode(num)
for i in range(bian_num):
    line = input().split()
    a = int(line[0])
    op = line[1]
    b = int(line[2])
    node_a = dic[a]
    node_b = dic[b]
    if op == "left":
        node_a.left = node_b
    else:
        node_a.right = node_b
root = dic[1]
print(postorder(root)//2)
发表于 2021-08-21 10:02:33 回复(0)
#include<bits/stdc++.h>
using namespace std;
const int MAXSIZE=101;
struct Node{
    int id=0;
    int left=0,right=0;
    bool leaf=true;
};
Node tree[MAXSIZE];
int m,n;
int ans;
int main(){
    cin>>m>>n;
    int id;
    string str;
    int child;
    for(int i=1;i<=n;i++){
        cin>>id>>str>>child;
        tree[id].leaf=false;
        if(str=="left"){
            tree[id].id=id,tree[id].left=child;
            tree[child].id=child;
        }
        if(str=="right"){
            tree[id].id=id,tree[id].right=child;
            tree[child].id=child;
        }
    }
    for(int i=1;i<=m;i++){
        if(tree[i].left!=0&&tree[i].right!=0&&tree[tree[i].left].leaf&&tree[tree[i].right].leaf){
            ans++;
        }
    }
    cout<<ans<<endl;
    return 0;
}
发表于 2021-08-18 23:39:27 回复(0)
//C++,2ms
#include <iostream>
#include <vector>
#include <string>

using namespace std;

int main()
{
    int edge,res = 0;  //res为结果
    cin>>edge>>edge;  //不需要节点数,只需要边的个数
    vector<int> n(2*edge); //每条边俩节点,都依次添加进vector中
    string str;  //凑数用的,用来去掉left和right
    
    int k=0;
    for(int i=0; i<edge; i++)   //把所有节点放进去(会有重复)
        cin>>n[k++]>>str>>n[k++]; //n:{1,2,1,3,2,4,2,5......}类似这样
    
    for(int i=0; i < n.size();)
    {
        if(n[i]==n[i+2]) //这个if测试节点的左右是否都有子节点
        {
            if(i == n.size()-4 || n[i+4]!=n[i+1] && n[i+4]!=n[i+3])
            {//这个测试左右子节点有没有子节点,即测试原节点是否有孙节点
                res++;
                i+=4;
            }
            else
                i+=4;
        }
        else
            i+=2;
    }
    
    cout<<res<<endl;
    return 0;
}


发表于 2021-06-27 11:09:26 回复(0)
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
 
int main()
{
    int nodeNum,lineNum;
    int res=0;
    vector<int> fatherVec;
    vector<int> sonVec;
    cin >> nodeNum;
    cin >> lineNum;
    while(lineNum--)
    {
        string RelaPos;
        int father, son;
        cin >> father;
        cin >> RelaPos;
        cin >> son;
        fatherVec.push_back(father);
        sonVec.push_back(son);
    }
    int index=sonVec.size()-1;
    while(index-1>=0)
    {
        if(fatherVec[index]==fatherVec[index-1] && (count(fatherVec.begin(),fatherVec.end(),sonVec[index])==0) &&
        (count(fatherVec.begin(),fatherVec.end(),sonVec[index-1])==0))
            res++;
        index--;
    }
    cout << res << endl;
    return 0;
}

发表于 2021-05-29 13:33:18 回复(0)
//两种方法,分别对应的时下面函数的solve() 和 solve2();

import java.util.HashMap;
import java.util.Scanner;

public class Test2 {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        String[] nums_bins = sc.nextLine().split(" ");
        int n = Integer.valueOf(nums_bins[0]);
        int b = Integer.valueOf(nums_bins[1]);
        HashMap<Integer,TreeNode> map = new HashMap<Integer, TreeNode>();
        HashMap<Integer,Integer> leftMap = new HashMap<Integer, Integer>();
        TreeNode left = null;
        TreeNode right = null;
        for(int i=0;i<b;i++) {
            String[] strs = sc.nextLine().split(" ");
            int num = Integer.valueOf(strs[0]);
            if(map.containsKey(num)) {
                left = map.get(num);
            } else {
                TreeNode newNode = new TreeNode(num);
                map.put(num,newNode);
                left = newNode;
            }
            leftMap.put(num,leftMap.getOrDefault(num, 0)+1);
            num = Integer.valueOf(strs[2]);
            if(map.containsKey(num)) {
                right = map.get(num);
            } else {
                TreeNode newNode = new TreeNode(num);
                map.put(num,newNode);
                right = newNode;
            }
            if(strs[1].equals("left")) {
                left.left = right;
            } else {
                left.right = right;
            }
            
        }
        solve(map.get(1));
        //solve2(map,leftMap);
        System.out.println(res);
    }
    
    public static int res = 0;
    public static void solve(TreeNode root) {
        if(root == null) {
            return;
        }
        if(root.left == null && root.right == null) {
            return;
        }
        inOrder(root);
    }
    public static boolean inOrder(TreeNode root) {
        if(root.left == null && root.right == null) {
            return true;
        }
        boolean left = false;
        boolean right = false;
        if(root.left != null) {
            left = inOrder(root.left);
        }
        if(root.right != null) {
            right = inOrder(root.left);
        }
        if(left && right) {
            res++;
        }
        return false;
    }
    
    public static void solve2(HashMap<Integer,TreeNode> map, HashMap<Integer,Integer> leftMap) {
        for(Integer key : leftMap.keySet()) {
            if(leftMap.get(key) == 2) {
                int left = map.get(key).left.val;
                int right = map.get(key).right.val;
                if(!leftMap.containsKey(left) && !leftMap.containsKey(right)) {
                    res++;
                }
            }
        }
    }
    
    public static class TreeNode{
        public int val;
        public TreeNode left;
        public TreeNode right;
        
        public TreeNode(int val) {
            this.val = val;
        }
    }
}
发表于 2021-04-17 09:45:22 回复(0)