Skip to content

Commit 9ac8095

Browse files
committed
优化索引
> 2024/05/26 15:01:25 解答成功: 执行耗时:18 ms,击败了37.62% 的Java用户 内存消耗:52.1 MB,击败了38.60% 的Java用户
1 parent 3013773 commit 9ac8095

File tree

1 file changed

+94
-48
lines changed

1 file changed

+94
-48
lines changed

hello-algo/lagou-algo/leetcode-question/src/main/java/com/shuzijun/leetcode/editor/cn/Lc1206DesignSkiplist.java

Lines changed: 94 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,40 @@ public static void main(String[] args) {
7575

7676
//leetcode submit region begin(Prohibit modification and deletion)
7777
class Skiplist {
78+
7879
final int HEAD_VALUE = -1; // 链表头节点的值
7980
final Node HEAD = new Node(HEAD_VALUE);
8081

8182
Node head; // 最左上角的头节点,所有操作在开始位置
8283
int levels; // 当前层级,即 head 节点所在的最高层数
84+
int length; // 链表长度
8385

8486
public Skiplist() {
8587
head = HEAD;
8688
levels = 1;
89+
length = 1;
90+
}
91+
92+
public Node get(int target) {
93+
return get(target, head);
94+
}
95+
96+
public Node get(int target, Node from) {
97+
Node n = from;
98+
while (n != null) {
99+
// 1.在同一层级上向右查找,直到链接结尾,或者找到
100+
while (n.right != null && n.right.val < target) {
101+
n = n.right;
102+
}
103+
// 2.若找到,返回true
104+
Node right = n.right; // 要查找的节点
105+
if (right != null && right.val == target) {
106+
return n; // 返回要查找的节点的前一个
107+
}
108+
// 3.若右侧数据较大,向下一层
109+
n = n.down;
110+
}
111+
return null;
87112
}
88113

89114
/**
@@ -94,27 +119,30 @@ public Skiplist() {
94119
* 3.链表结尾,或大于,往下
95120
*
96121
* </pre>
122+
*
97123
* @param target
98124
* @return
99125
*/
100126
public boolean search(int target) {
101-
Node n = head;
102-
while (n != null) {
103-
// 1.在同一层级向右查找,直到链表的结尾
104-
while (n.right != null && n.right.val < target) {
105-
n = n.right; // 向右
106-
}
107-
// 2.若找到,返回true
108-
Node right = n.right; // 要查找的节点
109-
if(right != null && right.val == target) {
110-
return true;
111-
}
112-
113-
// 3.若右侧数据较大,向下一层
114-
n = n.down; // 往下
115-
}
116-
117-
return false;
127+
// Node n = head;
128+
// while (n != null) {
129+
// // 1.在同一层级向右查找,直到链表的结尾
130+
// while (n.right != null && n.right.val < target) {
131+
// n = n.right; // 向右
132+
// }
133+
// // 2.若找到,返回true
134+
// Node right = n.right; // 要查找的节点
135+
// if(right != null && right.val == target) {
136+
// return true;
137+
// }
138+
//
139+
// // 3.若右侧数据较大,向下一层
140+
// n = n.down; // 往下
141+
// }
142+
//
143+
// return false;
144+
Node node = get(target);
145+
return node != null;
118146
}
119147

120148
/**
@@ -124,6 +152,7 @@ public boolean search(int target) {
124152
* 2.插入新节点
125153
* 3.根据扔硬币决定(是否)生成索引
126154
* </pre>
155+
*
127156
* @param num
128157
*/
129158
public void add(int num) {
@@ -152,13 +181,15 @@ public void add(int num) {
152181

153182
Node newNode = new Node(num, node.right, null);
154183
node.right = newNode;
184+
length++;
155185

156186
// 3.根据扔硬币决定(是否)生成索引
157187
addIndicesByCoinFlip(newNode, nodes, i);
158188
}
159189

160190
/**
161191
* 抛硬币
192+
*
162193
* @param target
163194
* @param nodes
164195
* @param indices 可以创建的层数
@@ -168,21 +199,22 @@ private void addIndicesByCoinFlip(Node target, Node[] nodes, int indices) {
168199
// 1.抛硬币,在现有层级范围内建立索引
169200
Random random = new Random();
170201
int coins = random.nextInt(2); // 0 or 1, 50%概率
171-
while (coins == 1 && indices > 0) {
172-
Node prev = nodes[--indices]; // 数组的倒数第二个元素,level 2,(循环下一次为 level 3)
173-
Node newIndex = new Node(target.val, prev.right, downNode); // newIndex指向当前节点
174-
prev.right = newIndex; //
175-
//indices--;
176-
downNode = newIndex; // 保存新的向下节点
177-
coins = random.nextInt(2); // 0 or 1, 50%概率
178-
}
179-
// 2.抛硬币,决定是否建立一层超出跳表层数的索引层
180-
if(coins == 1) { // 新建一个索引层级
181-
// 新建索引节点和头节点
182-
Node newIndex = new Node(target.val, null, downNode); // 新层级,右边为null,下为上一次的down节点
183-
Node newHead = new Node(HEAD_VALUE, newIndex, head); // 头节点
184-
head = newHead; // head 指针上移
185-
levels++; // 跳表层数加 1
202+
while (coins == 1 && levels < length >> 6) { // 除以2的2次方
203+
if (indices > 0) {
204+
Node prev = nodes[--indices]; // 数组的倒数第二个元素,level 2,(循环下一次为 level 3)
205+
Node newIndex = new Node(target.val, prev.right, downNode); // newIndex指向当前节点
206+
prev.right = newIndex; //
207+
//indices--;
208+
downNode = newIndex; // 保存新的向下节点
209+
coins = random.nextInt(2); // 0 or 1, 50%概率
210+
} else {
211+
// 2.抛硬币,决定是否建立一层超出跳表层数的索引层
212+
// 新建索引节点和头节点
213+
Node newIndex = new Node(target.val, null, downNode); // 新层级,右边为null,下为上一次的down节点
214+
Node newHead = new Node(HEAD_VALUE, newIndex, head); // 头节点
215+
head = newHead; // head 指针上移
216+
levels++; // 跳表层数加 1
217+
}
186218
}
187219
}
188220

@@ -193,34 +225,48 @@ private void addIndicesByCoinFlip(Node target, Node[] nodes, int indices) {
193225
* 2.与当前层链表断开
194226
* 3.下移,删除每一层
195227
* </pre>
228+
*
196229
* @param num
197230
* @return
198231
*/
199232
public boolean erase(int num) {
200233
boolean exist = false;
201-
Node n = head;
202-
while (n != null) {
203-
// 1.获取该指定数据节点的前一个节点
204-
while (n.right != null && n.right.val < num) {
205-
n = n.right; // 向右
206-
}
207-
// 2.与当前层链表断开
208-
Node right = n.right; // 要删除的节点
209-
if(right != null && right.val == num) {
210-
n.right = right.right; // 前一节点 指向待删除节点的后一节点
211-
right.right = null; // help GC
212-
exist = true;
213-
}
234+
// Node n = head;
235+
// while (n != null) {
236+
// // 1.获取该指定数据节点的前一个节点
237+
// while (n.right != null && n.right.val < num) {
238+
// n = n.right; // 向右
239+
// }
240+
// // 2.与当前层链表断开
241+
// Node right = n.right; // 要删除的节点
242+
// if(right != null && right.val == num) {
243+
// n.right = right.right; // 前一节点 指向待删除节点的后一节点
244+
// right.right = null; // help GC
245+
// exist = true;
246+
// }
247+
//
248+
// // 3.下移,删除每一层
249+
// // 删除下一层
250+
// n = n.down;
251+
// }
252+
Node node = get(num, head);
253+
while (node != null) {
254+
Node right = node.right; // 要删除的节点
255+
node.right = right.right;
256+
right.right = null; // help GC
257+
exist = true;
214258

215-
// 3.下移,删除每一层
216-
// 删除下一层
217-
n = n.down;
259+
node = get(num, node.down);
260+
}
261+
if (exist) {
262+
length--; // 链表长度减 1
218263
}
219264

220265
return exist;
221266
}
222267

223268
class Node {
269+
224270
int val;
225271
Node right, down;
226272

0 commit comments

Comments
 (0)