-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathLeetcode_958.cpp
More file actions
180 lines (153 loc) · 4.15 KB
/
Leetcode_958.cpp
File metadata and controls
180 lines (153 loc) · 4.15 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// 958. Check Completeness of a Binary Tree
// Link: https://leetcode.com/problems/check-completeness-of-a-binary-tree/
/*
Problem Description:
Given the root of a binary tree, determine if it is a complete binary tree.
A complete binary tree has all levels fully filled except possibly the last level,
and in the last level, all nodes are as far left as possible.
Time Complexity: O(N), where N is the number of nodes in the tree
- sizeOfTree: O(N) to count all nodes
- solve: O(N) to visit each node once
Space Complexity: O(H), where H is the height of the tree
- Recursion stack space for both sizeOfTree and solve functions
- In worst case (skewed tree): O(N)
- In best case (complete/perfect tree): O(log N)
Example Test Cases:
1. Complete Binary Tree:
1
/ \
2 3
/ \ /
4 5 6
Input: [1,2,3,4,5,6]
Output: true
Explanation: All nodes in last level are towards left
2. Incomplete Binary Tree:
1
/ \
2 3
/ \ \
4 5 7
Input: [1,2,3,4,5,null,7]
Output: false
Explanation: Node 7 should be towards left
3. Single Node:
1
Input: [1]
Output: true
Explanation: Single node is always complete
4. Perfect Binary Tree:
1
/ \
2 3
/ \ / \
4 5 6 7
Input: [1,2,3,4,5,6,7]
Output: true
Explanation: All levels are completely filled
5. Edge Case - Empty Tree:
Input: []
Output: true
Explanation: Empty tree is considered complete
Approach:
1. Get total size of tree using sizeOfTree function
2. Use array index property of complete binary trees:
- For node at index i:
- Left child is at 2i + 1
- Right child is at 2i + 2
3. If any index >= total size, tree is not complete
*/
#include <iostream>
#include <queue>
using namespace std;
// Definition for a binary tree node
struct TreeNode
{
int val;
TreeNode *left;
TreeNode *right;
TreeNode() : val(0), left(nullptr), right(nullptr) {}
TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
};
class Solution
{
private:
bool solve(TreeNode *root, int index, int size)
{
if (!root)
return true;
if (index >= size)
return false;
// Check left and right subtrees
if (!solve(root->left, index * 2 + 1, size))
return false;
if (!solve(root->right, index * 2 + 2, size))
return false;
return true;
}
int sizeOfTree(TreeNode *root)
{
if (!root)
return 0;
return 1 + sizeOfTree(root->left) + sizeOfTree(root->right);
}
public:
bool isCompleteTree(TreeNode *root)
{
if (!root)
return true;
int s = sizeOfTree(root);
return solve(root, 0, s);
}
// Helper function to create a tree from level-order array
static TreeNode *createTree(vector<int> &arr, int i = 0)
{
if (i >= arr.size() || arr[i] == -1)
return nullptr; // -1 represents null
TreeNode *root = new TreeNode(arr[i]);
root->left = createTree(arr, 2 * i + 1);
root->right = createTree(arr, 2 * i + 2);
return root;
}
};
// Test function
void runTest(vector<int> input, bool expected)
{
Solution sol;
TreeNode *root = Solution::createTree(input);
bool result = sol.isCompleteTree(root);
cout << "Input: [";
for (int i = 0; i < input.size(); i++)
{
if (i > 0)
cout << ",";
if (input[i] == -1)
cout << "null";
else
cout << input[i];
}
cout << "]\n";
cout << "Expected: " << (expected ? "true" : "false") << "\n";
cout << "Output: " << (result ? "true" : "false") << "\n";
cout << "Test " << (result == expected ? "PASSED" : "FAILED") << "\n\n";
}
int main()
{
// Test Case 1: Complete Binary Tree
vector<int> test1 = {1, 2, 3, 4, 5, 6};
runTest(test1, true);
// Test Case 2: Incomplete Binary Tree
vector<int> test2 = {1, 2, 3, 4, 5, -1, 7}; // -1 represents null
runTest(test2, false);
// Test Case 3: Single Node
vector<int> test3 = {1};
runTest(test3, true);
// Test Case 4: Perfect Binary Tree
vector<int> test4 = {1, 2, 3, 4, 5, 6, 7};
runTest(test4, true);
// Test Case 5: Incomplete at last level but not left-aligned
vector<int> test5 = {1, 2, 3, 4, -1, 6};
runTest(test5, false);
return 0;
}