Skip to content

Commit 125a515

Browse files
Merge pull request #221
add new problem 27.09
2 parents fee3fcb + e9f4ae6 commit 125a515

File tree

5 files changed

+225
-17
lines changed

5 files changed

+225
-17
lines changed

contest/src/main/java/com/github/contest/Execute.kt

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
package com.github.contest
22

33

4-
import com.github.contest.binaryTree.TreeNode
5-
import com.github.contest.binaryTree.replaceValueInTree
4+
import com.github.contest.binaryTree.findDuplicateSubtreesProdVariant
5+
import com.github.contest.binaryTree.printTree
6+
import com.github.contest.binaryTree.toTreeNode
67
import com.github.contest.math.numberOfPowerfulInt
78
import com.github.contest.slidingWindow.customStructure.rabinKarpMultiPattern
89
import com.github.contest.slidingWindow.customStructure.slidingWindowClassic
@@ -15,18 +16,18 @@ import java.util.TreeMap
1516
*/
1617

1718
fun main() {
19+
val tree = listOf(1, 2, 3, 4, null, 2, 4, null, null, 4).toTreeNode()
20+
//tree.printTree()
1821

19-
// 5,4,9,1,10,null,7
20-
val root = TreeNode(5)
21-
root?.left = TreeNode(4)
22-
root?.right = TreeNode(9)
23-
root.left?.left = TreeNode(1)
24-
root?.left?.right = TreeNode(10)
25-
root?.right?.right = TreeNode(7)
22+
findDuplicateSubtreesProdVariant(tree).apply {
23+
this.forEach {
24+
it.printTree()
25+
}
26+
}
2627

27-
replaceValueInTree(root).also { println(it) }
2828
}
2929

30+
3031
class Example(val param: String) { // Primary constructor parameter
3132
init {
3233
println("init block: $param") // Can access param!

contest/src/main/java/com/github/contest/binaryTree/BinaryTreeAlternativeSolution.kt

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,46 @@ fun isSubtreeSerialization(root: TreeNode?, subRoot: TreeNode?): Boolean {
4848
fun serialize(root: TreeNode?): String {
4949
if (root == null) return "null"
5050

51-
// Use preorder traversal with markers
5251
return "#${root.`val`} ${serialize(root.left)} ${serialize(root.right)}"
52+
}
53+
54+
/**
55+
* 652. Find Duplicate Subtrees
56+
* Alternative Solution
57+
* Using Serialize + Traverse
58+
*/
59+
60+
fun findDuplicateSubtreesOtherSolution(root: TreeNode?): List<TreeNode?> {
61+
val result = mutableListOf<TreeNode?>()
62+
val subtreeMap = mutableMapOf<String, Int>() // serialization -> count
63+
serialize(root, subtreeMap, result)
64+
return result
65+
}
66+
67+
private fun serialize(
68+
node: TreeNode?,
69+
subtreeMap: MutableMap<String, Int>,
70+
result: MutableList<TreeNode?>
71+
): String {
72+
if (node == null) return "#"
73+
74+
// Postorder serialization: left + right + root
75+
val serial = buildString {
76+
append(serialize(node.left, subtreeMap, result))
77+
append(",")
78+
append(serialize(node.right, subtreeMap, result))
79+
append(",")
80+
append(node.`val`)
81+
}
82+
83+
84+
val count = subtreeMap.getOrDefault(serial, 0)
85+
subtreeMap[serial] = count + 1
86+
87+
88+
if (count == 1) {
89+
result.add(node)
90+
}
91+
92+
return serial
5393
}

contest/src/main/java/com/github/contest/binaryTree/BinaryTreeLeetcode.kt

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,6 @@ import kotlin.math.abs
77
* 1261. Find Elements in a Contaminated Binary Tree
88
*/
99

10-
class TreeNode(var `val`: Int) {
11-
var left: TreeNode? = null
12-
var right: TreeNode? = null
13-
}
1410

1511
class FindElements(private val root: TreeNode?) {
1612

@@ -317,7 +313,7 @@ fun printTree(root: TreeNode?): List<List<String>> {
317313
val rows = height(root)
318314
val col = (1 shl rows) - 1
319315
val res = MutableList(rows) { _ ->
320-
MutableList(col) { "" }
316+
MutableList(col) { " " }
321317
}
322318
val rootPos = (col - 1) / 2
323319
val queue = LinkedList<Triple<TreeNode, Int, Int>>().apply {
@@ -353,3 +349,59 @@ private fun height(root: TreeNode?): Int = when {
353349
root == null -> 0
354350
else -> 1 + maxOf(height(root.left), height(root.right))
355351
}
352+
353+
/**
354+
* 652. Find Duplicate Subtrees
355+
*/
356+
357+
fun findDuplicateSubtrees(root: TreeNode?): List<TreeNode?> {
358+
root ?: return listOf()
359+
360+
if (root.left == null && root.right == null) return listOf()
361+
362+
val paths = mutableMapOf<String, Pair<TreeNode, Int>>()
363+
val res = mutableListOf<TreeNode?>()
364+
val queue = LinkedList<TreeNode>().apply {
365+
offer(root)
366+
}
367+
368+
while (queue.isNotEmpty()) {
369+
val size = queue.size
370+
371+
for (i in 0 until size) {
372+
val node = queue.poll()
373+
val path = serializeDuplicateSubTree(node)
374+
if (paths.contains(path)) {
375+
val stub = TreeNode(0) to 0
376+
paths[path] = paths.getOrDefault(path, stub).let {
377+
it.copy(second = it.second + 1)
378+
}
379+
} else {
380+
paths[path] = Pair(node, 1)
381+
}
382+
383+
node.left?.let {
384+
queue.offer(it)
385+
}
386+
387+
node.right?.let {
388+
queue.offer(it)
389+
}
390+
}
391+
}
392+
393+
for ((_, value) in paths) {
394+
if (value.second > 1) {
395+
res.add(value.first)
396+
}
397+
}
398+
399+
return res
400+
401+
}
402+
403+
private fun serializeDuplicateSubTree(root: TreeNode?): String = when {
404+
root == null -> "null"
405+
else -> "#${root.`val`} , ${serialize(root?.left)} , ${serialize(root?.right)}"
406+
}
407+

contest/src/main/java/com/github/contest/binaryTree/BinaryTreeProdVariant.kt

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,44 @@ fun mergeTreesProdVariant(root1: TreeNode?, root2: TreeNode?): TreeNode? = when
7777
newRoot.right = mergeTreesProdVariant(root1?.right, root2?.right)
7878
newRoot
7979
}
80-
}
80+
}
81+
82+
/**
83+
* 652. Find Duplicate Subtrees
84+
* Prod Variant
85+
* Using DFS
86+
*/
87+
88+
fun findDuplicateSubtreesProdVariant(root: TreeNode?): List<TreeNode?> {
89+
val hashToTreeNode = mutableMapOf<String, TreeNode>()
90+
return buildList {
91+
fun dfs(root: TreeNode?): String {
92+
if (root == null) return "#"
93+
94+
val hash = buildString {
95+
append(root.`val`)
96+
append(",")
97+
append("${dfs(root.left)}")
98+
append(",")
99+
append("${dfs(root.right)}")
100+
}
101+
102+
add(hash to root)
103+
hashToTreeNode[hash] = root
104+
105+
return hash
106+
}
107+
dfs(root)
108+
}.groupingBy { it.first }
109+
.eachCount()
110+
.toList()
111+
.filter { it.second > 1 }
112+
.let { freq ->
113+
buildList {
114+
freq.forEach {
115+
add(hashToTreeNode[it.first])
116+
}
117+
}
118+
}
119+
120+
}
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
package com.github.contest.binaryTree
2+
3+
import java.util.LinkedList
4+
5+
class TreeNode(var `val`: Int) {
6+
var left: TreeNode? = null
7+
var right: TreeNode? = null
8+
}
9+
10+
fun TreeNode?.printTree() {
11+
if (this == null) println("null")
12+
13+
val printedTree = printTree(this)
14+
15+
printedTree.forEach {
16+
it.joinToString(" ").also { level ->
17+
println(level)
18+
}
19+
}
20+
}
21+
22+
23+
fun List<Int?>.toTreeNode(): TreeNode? {
24+
25+
val root = TreeNode(this.first()!!)
26+
val queue = LinkedList<TreeNode>().apply {
27+
offer(root)
28+
}
29+
30+
var i = 1
31+
32+
while (queue.isNotEmpty() && i < size) {
33+
val node = queue.poll()
34+
35+
if (i < size && this[i] != null) {
36+
node.left = TreeNode(this[i]!!)
37+
queue.offer(node.left)
38+
}
39+
40+
i++
41+
42+
if (i < size && this[i] != null) {
43+
node.right = TreeNode(this[i]!!)
44+
queue.offer(node.right)
45+
}
46+
47+
i++
48+
}
49+
50+
return root
51+
}
52+
53+
private fun List<Int?>.validationTree(): Unit? {
54+
if (isEmpty()) return null
55+
if (first() == null) throw IllegalArgumentException("First Element Shouldn't be NULL")
56+
57+
58+
for (i in 0 until size) {
59+
60+
if (this[i] == null) {
61+
62+
val leftChildIndex = 2 * i + 1
63+
val rightChildIndex = 2 * i + 2
64+
65+
if (leftChildIndex < size && this[leftChildIndex] != null) throw IllegalArgumentException(
66+
"Left subTree shouldn't have child"
67+
)
68+
if (rightChildIndex < size && this[rightChildIndex] != null) throw IllegalArgumentException(
69+
"Right subTree shouldn't have child"
70+
)
71+
}
72+
}
73+
74+
return Unit
75+
}

0 commit comments

Comments
 (0)