数据结构的题目,题目给出了输入输出,所以只用核心算法,两种,第一种会有一个测试点超时,因为时间复杂度接近N^2,想看正确答案可以直接移步第二种答案。第二种时间复杂度接近2N.对于2*10^4的数据体量来说降了很多。
第一种思路:对于root1左根右非递归遍历(由于二叉搜索树的特征,这样得到的就是升序),同时对于root1的每一个结点数据,先遍历一遍a看a中是否已经有这个节点,再调用Find函数去找root2里是否有这个节点。入锅满足连个要求就把T->val存储。
缺点:时间复杂度接机N^2,对于重复结点的判断没有必要专门遍历一遍a,完全可以直接和a[i-1]去比,因为按照升序序列遍历,相同的两个节点本身就连在一起。Find函数也是每一次都从root2的根开始遍历,没有必要。这些都在第二种方法里改进了。
int Find(TreeNode* T,int c){
if(T){
if(c==T->val) return 1;
if(c>T->val){
return Find(T->right,c);
}
else return Find(T->left,c);
}
return 0;
}
//左根右升序 ,中序遍历root1
int findSum(TreeNode *root1, TreeNode *root2, int target, int a[], int b[]){
TreeNode* stack[99999];
int top=-1,t,i=0,j=0,f;
TreeNode *T=root1;
while(T||top!=-1){
while(T){
stack[++top]=T;
T=T->left;
}
T=stack[top--];
f=1;
for(j=0;j<i;j++){
if(a[j]==T->val){
f=0;
break;
}
}
if(f&&Find(root2,target-T->val)){
a[i]=T->val;
b[i++]=target-T->val;
}
T=T->right;
}
return i;
}
第二种方法(正确的)思路:先对root2左根右遍历得到升序序列并存在数组B里,遍历完后B的下标ib正好在最后一个元素的位置,再对root1左根右升序遍历,同时对每一个结点的值T->val,先和a[ia]比较是否相等,再和B[ib]比较,如果二者的和大于target就ib--,B向前走,直到等于或者小于时即可跳出,若等于还要存储在a里。当ib<0或者while不满足是说明其中一棵树遍历完了则结束。
注意数组元素最大限,这个段错误卡了我很久没找出来,还以为算法有问题。
int findSum(TreeNode *root1, TreeNode *root2, int target, int a[], int b[]){
TreeNode* stack[99999];//最多5个9再多就段错误了
int top=-1,ib=-1,ia=0,f2,B[99999];
TreeNode *T=root2;
while(T||top!=-1){
while(T){
stack[++top]=T;
T=T->left;//注意root2是也是左根右读
}
T=stack[top--];
B[++ib]=T->val;
T=T->right;
}
T=root1;//再遍历A但不存储
while(T||top!=-1){
while(T){
stack[++top]=T;
T=T->left;
}
T=stack[top--];
if((ia==0)||((ia>0)&&(a[ia-1]!=T->val))){//不和前一个元素重复
f2=0;
while(ib>=0){
if(B[ib]+T->val>=target){
if(B[ib]+T->val==target){
f2=1;
break;
}
else ib--; //B向前走
}
else break;
}
if(f2){
a[ia]=T->val;
b[ia++]=target-T->val;
}
if(ib<0) break;//root2的元素已经走完了
}
T=T->right;
}
return ia;
}
题目如下:
A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties:
-
The left subtree of a node contains only nodes with keys less than the node's key.
-
The right subtree of a node contains only nodes with keys greater than or equal to the node's key.
-
Both the left and right subtrees must also be binary search trees.
Given two binary search trees, T1 and T2, and an integer N, you are supposed to find a number A from T1 and a number B from T2 such that A+B=N.
Structure description:
The tree structure is shown below:
typedef struct TreeNode { int val; struct TreeNode *left, *right; } TreeNode;
Function definition:
You should find all solutions satisfying A+B=N. The function definition is as follows:
int findSum(TreeNode *root1, TreeNode *root2, int target, int a[], int b[]);
root1
and root2
are the roots for T1 and T2 respectively. The number of nodes for each tree n ≤2×104,
and key value of each node k: −2×109≤k≤2×109. N
is the target number. For each test case, the function returns nsum
, the number of solutions, then saves all the solutions in a
and b
. That is, each solution is in the format N = a[i] + b[i]
(0≤i<nsum). In case there are multiple solutions, values in a
must be in ascending order. Note: the same solution should be saved only once.
Input Specification:
Each input file contains one test case. Each case gives the information of T1, T2, and N, in the following format:
The first line contains a positive integer n1 (≤2×104), which is the number of nodes in T1. Then n1 lines follow, where the i-th line contains the key value k (−2×109≤k≤2×109) and the parent node index of the i-th node (0≤i<n1). Since the root has no parent, its parent index is defined to be −1. After T1, T2 is given in the same format as T1. Finally, the last line gives the target N (with the same range of k).
Output Specification:
Firstly, you should print in a line true
if at least one solution exists, then output all the solutions in the following lines, each in the format N = A + B
. In the case of multiple solutions, you must ensure that values A
are in ascending order. Note: the same equation should be printed only once. If there is no solution, simply print false
.
Test program example:
#include <stdio.h>
#include <stdlib.h>
#define MAX_SIZE 20000
int values_1[MAX_SIZE];
int parents_1[MAX_SIZE];
int values_2[MAX_SIZE];
int parents_2[MAX_SIZE];
typedef struct TreeNode {
int val;
struct TreeNode *left, *right;
} TreeNode;
TreeNode *buildTree(int values[], int parents[], int n); /* details omitted */
int findSum(TreeNode *root1, TreeNode *root2, int N, int a[], int b[]);
int main() {
int n;
scanf("%d", &n);
for (int i = 0; i < n; i++) {
scanf("%d %d", &values_1[i], &parents_1[i]);
}
int m;
scanf("%d", &m);
for (int i = 0; i < m; i++) {
scanf("%d %d", &values_2[i], &parents_2[i]);
}
int N;
scanf("%d", &N);
TreeNode *root1 = buildTree(values_1, parents_1, n);
TreeNode *root2 = buildTree(values_2, parents_2, m);
int a[MAX_SIZE];
int b[MAX_SIZE];
int nsum = findSum(root1, root2, N, a, b);
if (nsum) {
printf("true\n");
for (int i = 0; i < nsum; i++)
printf("%d = %d + %d\n", N, a[i], b[i]);
} else
printf("false\n");
return 0;
}
int findSum(TreeNode *root1, TreeNode *root2, int N, int a[], int b[]) {
/* your implementation of this function */
}
Sample Input 1:
8
12 2
16 5
13 4
18 5
15 -1
17 4
14 2
18 3
7
20 -1
16 0
25 0
13 1
18 1
21 2
28 2
36
Sample Output 1:
true
36 = 15 + 21
36 = 16 + 20
36 = 18 + 18
Sample Input 2:
5
10 -1
5 0
15 0
2 1
7 1
3
15 -1
10 0
20 0
40
Sample Output 2:
false