Skip to content

Commit a41b5e8

Browse files
committed
sprint5
1 parent 4c4e406 commit a41b5e8

3 files changed

Lines changed: 156 additions & 176 deletions

File tree

src/main/java/algorithms/sprint5/PyramidSort.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import java.io.InputStream;
44
import java.io.OutputStream;
55

6+
//https://contest.yandex.ru/contest/24810/run-report/160623687/
7+
68
public class PyramidSort {
79

810
/*
Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
// https://contest.yandex.ru/contest/24810/run-report/160624033/
2+
3+
// <template>
4+
class Node {
5+
private int value;
6+
private Node left;
7+
private Node right;
8+
9+
Node(Node left, Node right, int value) {
10+
this.left = left;
11+
this.right = right;
12+
this.value = value;
13+
}
14+
15+
public int getValue() {
16+
return value;
17+
}
18+
19+
public Node getRight() {
20+
return right;
21+
}
22+
23+
public void setRight(Node right) {
24+
this.right = right;
25+
}
26+
27+
public Node getLeft() {
28+
return left;
29+
}
30+
31+
public void setLeft(Node left) {
32+
this.left = left;
33+
}
34+
35+
public void setValue(int value) {
36+
this.value = value;
37+
}
38+
}
39+
// <template>
40+
41+
public class Solution {
42+
43+
/*
44+
* Принцип работы алгоритма:
45+
* Используем свойство бинарного дерева поиска.
46+
* Если удаляемый ключ меньше значения в текущей вершине,
47+
* продолжаем поиск в левом поддереве.
48+
* Если больше — в правом.
49+
* Когда вершина с нужным ключом найдена, возможны три случая:
50+
*
51+
* 1) У вершины нет левого ребёнка.
52+
* Тогда на её место должно встать правое поддерево.
53+
*
54+
* 2) У вершины нет правого ребёнка.
55+
* Тогда на её место должно встать левое поддерево.
56+
*
57+
* 3) У вершины есть оба ребёнка.
58+
* Тогда берём максимальный элемент из левого поддерева
59+
* (это предшественник текущей вершины в порядке BST),
60+
* записываем его значение в текущую вершину,
61+
* а затем удаляем этот элемент из левого поддерева.
62+
*
63+
* Почему алгоритм корректен:
64+
* 1) По свойству BST искомый ключ может находиться только
65+
* в одном из двух поддеревьев, поэтому рекурсивный спуск
66+
* идёт ровно по нужному пути.
67+
*
68+
* 2) Если у удаляемой вершины не более одного ребёнка,
69+
* замена вершины её единственным поддеревом
70+
* сохраняет порядок ключей в дереве.
71+
*
72+
* 3) Если у вершины два ребёнка, максимум левого поддерева:
73+
* - меньше значения любой вершины из правого поддерева;
74+
* - не меньше всех остальных значений из левого поддерева.
75+
* Поэтому после замены текущего ключа на этот максимум
76+
* свойство BST сохраняется.
77+
*
78+
* 4) После этого мы удаляем из левого поддерева вершину,
79+
* значение которой перенесли вверх. Так как ключи уникальны,
80+
* удаляется ровно одна нужная вершина.
81+
*
82+
* Временная сложность: O(h), где h — высота дерева,
83+
* потому что мы спускаемся только по одному пути вниз.
84+
*
85+
* Пространственная сложность: O(h) из-за стека рекурсии.
86+
*/
87+
88+
public static Node remove(Node root, int key) {
89+
if (root == null) {
90+
return null;
91+
}
92+
93+
if (key < root.getValue()) {
94+
root.setLeft(remove(root.getLeft(), key));
95+
return root;
96+
}
97+
98+
if (key > root.getValue()) {
99+
root.setRight(remove(root.getRight(), key));
100+
return root;
101+
}
102+
103+
if (root.getLeft() == null) {
104+
return root.getRight();
105+
}
106+
107+
if (root.getRight() == null) {
108+
return root.getLeft();
109+
}
110+
111+
Node predecessor = findMax(root.getLeft());
112+
root.setValue(predecessor.getValue());
113+
root.setLeft(remove(root.getLeft(), predecessor.getValue()));
114+
return root;
115+
}
116+
117+
private static Node findMax(Node node) {
118+
while (node.getRight() != null) {
119+
node = node.getRight();
120+
}
121+
return node;
122+
}
123+
124+
private static void test() {
125+
Node node1 = new Node(null, null, 2);
126+
Node node2 = new Node(node1, null, 3);
127+
Node node3 = new Node(null, node2, 1);
128+
Node node4 = new Node(null, null, 6);
129+
Node node5 = new Node(node4, null, 8);
130+
Node node6 = new Node(node5, null, 10);
131+
Node node7 = new Node(node3, node6, 5);
132+
133+
Node newHead = remove(node7, 10);
134+
assert newHead.getValue() == 5;
135+
assert newHead.getRight() == node5;
136+
assert newHead.getRight().getValue() == 8;
137+
138+
Node root = new Node(
139+
new Node(new Node(null, null, 2), new Node(null, null, 4), 3),
140+
new Node(new Node(null, null, 7), new Node(null, null, 9), 8),
141+
5
142+
);
143+
Node result = remove(root, 5);
144+
assert result.getValue() == 4;
145+
assert result.getLeft().getValue() == 3;
146+
assert result.getRight().getValue() == 8;
147+
148+
Node single = new Node(null, null, 1);
149+
assert remove(single, 1) == null;
150+
151+
Node unchanged = new Node(null, null, 1);
152+
assert remove(unchanged, 2) == unchanged;
153+
}
154+
}

src/main/java/algorithms/sprint5/TreePartitioning.java

Lines changed: 0 additions & 176 deletions
This file was deleted.

0 commit comments

Comments
 (0)