首页 > 试题广场 >

遍历二叉树

[编程题]遍历二叉树
  • 热度指数:139 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 256M,其他语言512M
  • 算法知识视频讲解

某地主担心农民偷取他的粮食,雇人挖了大量地窖来屯粮,这些地窖层层排列,只有一个总入口。 每个地窖都有一个随机且唯一的数字编号(1 ... N)。聪明的农夫经过一番侦察,发现所有的地窖形成了一颗满二叉树,只有叶子节点中才存放有粮食,粮食数量与地窖编号相同。 狡猾的地主设置了报警装置,只要任意两个相邻的叶子节点中粮食被偷,就会自动报警。
农夫事先并不知道地窖分布图,但是他无意间得到了地窖组成的二叉树的前序遍历和中序遍历结果,请帮忙计算一下,在不触发报警装置的情况下,农夫最多可以偷取地主多少粮食。
提示:

  1. 如果一个二叉树的层数为K,且节点总数是2k -1 ,则它就是满二叉树,如下图所示。
  2. 下图中节点1和节点2,节点2和节点3均为相邻的叶子节点, 节点1和节点3不属于相邻叶子节点;


输入描述:

第一行输入一个数字n表示有n个节点的满二叉树

第二行n个数字a[0],a[1]...a[n-1]用空格隔开,表示二叉树的前序遍历

第三行n个数字b[0],b[1]...b[n-1]用空格隔开,表示二叉树的中序遍历

数据范围:

3<=n<=105 且n可以表示成2k-1(k为整数)

a[0]...a[n-1]中1,2...n每个数字分别出现一次

b[0]...b[n-1]中1,2...n每个数字分别出现一次



输出描述:
输出一个数字,表示农夫最多可以偷取地主多少粮食
示例1

输入

3
2 1 3
1 2 3

输出

3
#include <stdio.h>
#include <stdlib.h>

typedef int ElemType;

typedef struct TreeNode {
  ElemType data;
  struct TreeNode* left;
  struct TreeNode* right;
} TreeNode, *PTreeNode;

// ==================== function declaration ====================
PTreeNode construct(int* preorder, int* inorder, int i, int j, int n);
void collectLeaves(PTreeNode root, int* leaves, int* leavesSize);

int main(const int argc, const char* const argv[]) {
  int n;
  fscanf(stdin, "%d", &n);
  
  int preorder[n], inorder[n];
  int i;
  for (i = 0; i < n; ++i)
    fscanf(stdin, "%d", preorder + i);
  for (i = 0; i < n; ++i)
    fscanf(stdin, "%d", inorder + i);
  
  PTreeNode root = construct(preorder, inorder, 0, 0, n);
  int leaves[n], leavesSize = 0;
  collectLeaves(root, leaves, &leavesSize);
  
  // dynamic programming
  int dp2 = 0, dp1 = 0;
  for (i = 0; i < leavesSize; ++i) {
    int dp = fmax(dp2 + *(leaves + i), dp1);
    dp2 = dp1;
    dp1 = dp;
  }
  
  return fprintf(stdout, "%d", dp1), 0;
}

PTreeNode construct(int* preorder, int* inorder, int i, int j, int n) {
  if (n <= 0) return NULL;
  PTreeNode root = (PTreeNode) malloc(sizeof(TreeNode));
  if (!root) return root;
  root->data = *(preorder + i);
  root->left = root->right = NULL;
  if (n == 1) return root;
  
  int k = j;
  while (*(inorder + k) != *(preorder + i)) ++k;
  int l = k - j;
  
  root->left  = construct(preorder, inorder, i + 1, j, l);
  root->right = construct(preorder, inorder, i + 1 + l, k + 1, n - 1 - l);
  return root;
}

void collectLeaves(PTreeNode root, int* leaves, int* leavesSize) {
  if (!root) return;
  if (!root->left && !root->right) {
    *(leaves + (*leavesSize)++) = root->data;
    return;
  }
  collectLeaves(root->left,  leaves, leavesSize);
  collectLeaves(root->right, leaves, leavesSize);
}

发表于 2021-07-21 08:22:43 回复(0)
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

vector<int> getLeavesByPreOrder(const int& n, int i = 0) {	//根据前序遍历确定叶节点
	static vector<int> leaves;
	int temp;
	cin >> temp;
	if ((i << 1) + 1 >= n) {								//添加叶节点
		leaves.push_back(temp);
		return leaves;
	}
	getLeavesByPreOrder(n, (i << 1) + 1);
	getLeavesByPreOrder(n, (i << 1) + 2);
	return leaves;
}
int main() {
	int n;
	cin >> n;
	vector<int> leaves = getLeavesByPreOrder(n);
	vector<int> dp(leaves.size());
	dp[0] = leaves[0];
	dp[1] = max(leaves[0], leaves[1]);
	for (int i = 2; i < dp.size(); i++)
		dp[i] = max(dp[i - 2] + leaves[i], dp[i - 1]);
	cout << dp.back();
	return 0;
}


编辑于 2020-06-05 18:00:42 回复(0)
using namespace std;
#include <iostream>
#include <string.h>
#include <stdlib.h>
#include <algorithm>

static int tree[100000];
static int dp[100000];
static void getTree(int lvl, int target, int* plen)
{
    int t;
    if (lvl >= target)
    {
        cin >> tree[(*plen)++];
        return;
    }
    else
    {
        cin >> t;
        getTree(lvl + 1, target, plen);
        getTree(lvl + 1, target, plen);
    }
}
static inline int max(int x, int y)
{
    return x > y ? x : y;
}
int main()
{
    int n, k, i, len, tmp;
    while (cin >> n)
    {
        k = n + 1;
        i = 0;
        while (k > 1)
        {
            k >>= 1;
            i++;
        }
        k = i;
        len = 0;
        getTree(0, k - 1, &len);
        for (i = 0; i < n; i++)
            cin >> tmp;
        dp[0] = tree[0];
        dp[1] = tree[1];
        dp[2] = tree[2] + dp[0];
        for (i = 3; i < len; i++)
            dp[i] = tree[i] + max(dp[i - 2], dp[i - 3]);
        if (len <= 1)
            cout << dp[len - 1];
        else
            cout << max(dp[len - 1], dp[len - 2]);
        cout << endl;
    }
    return 0;
}

编辑于 2020-03-09 21:31:18 回复(0)