Skip to content

Commit 415da09

Browse files
KhArtNJavaenhorse
authored andcommitted
Добавлен пример кода эффективного алгоритма удаления нескольких рядом стоящих элементов из середины списка, реализуемого ArrayList.
1 parent 67ac054 commit 415da09

1 file changed

Lines changed: 108 additions & 0 deletions

File tree

jcf.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,114 @@ _O(N)_. Вставка элемента в конец списка осущес
314314
## Предложите эффективный алгоритм удаления нескольких рядом стоящих элементов из середины списка, реализуемого `ArrayList`.
315315
Допустим нужно удалить `n` элементов с позиции `m` в списке. Вместо выполнения удаления одного элемента `n` раз (каждый раз смещая на 1 позицию элементы, стоящие «правее» в списке), нужно выполнить смещение всех элементов, стоящих «правее» `n + m` позиции на `n` элементов «левее» к началу списка. Таким образом, вместо выполнения `n` итераций перемещения элементов списка, все выполняется за 1 проход.
316316

317+
Пример:
318+
319+
```java
320+
package test1;
321+
322+
import java.io.*;
323+
import java.util.ArrayList;
324+
325+
public class Main {
326+
//позиция с которой удаляем
327+
private static int m = 0;
328+
//количество удаляемых элементов
329+
private static int n = 0;
330+
//количество элементов в списке
331+
private static final int size = 1000000;
332+
//основной список (для удаления вызовом remove() и его копия для удаления путём перезаписи)
333+
private static ArrayList<Integer> initList, copyList;
334+
335+
public static void main(String[] args){
336+
337+
initList = new ArrayList<>(size);
338+
for (int i = 0; i < size; i++)
339+
initList.add(i);
340+
System.out.println("Список из 1.000.000 элементов заполнен");
341+
342+
copyList = new ArrayList<>(initList);
343+
System.out.println("Создана копия списка\n");
344+
345+
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
346+
try{
347+
System.out.print("С какой позиции удаляем? > ");
348+
m = Integer.parseInt(br.readLine());
349+
System.out.print("Сколько удаляем? > ");
350+
n = Integer.parseInt(br.readLine());
351+
} catch(IOException e){
352+
System.err.println(e.toString());
353+
}
354+
System.out.println("\nВыполняем удаление вызовом remove()...");
355+
long start = System.currentTimeMillis();
356+
357+
for (int i = m - 1; i < m + n - 1; i++)
358+
initList.remove(i);
359+
360+
long finish = System.currentTimeMillis() - start;
361+
System.out.println("Время удаления с помощью вызова remove(): " + finish);
362+
System.out.println("Размер исходного списка после удаления: " + initList.size());
363+
364+
System.out.println("\nВыполняем удаление путем перезаписи...\n");
365+
start = System.currentTimeMillis();
366+
367+
removeEfficiently();
368+
369+
finish = System.currentTimeMillis() - start;
370+
System.out.println("Время удаления путём смещения: " + finish);
371+
System.out.println("Размер копии списка:" + copyList.size());
372+
}
373+
374+
private static void removeEfficiently(){
375+
/* если необходимо удалить все элементы, начиная с указанного,
376+
* то удаляем элементы с конца до m
377+
*/
378+
if (m + n >= size){
379+
int i = size - 1;
380+
while (i != m - 1){
381+
copyList.remove(i);
382+
i--;
383+
}
384+
} else{
385+
//переменная k необходима для отсчёта сдвига начиная от места вставка m
386+
for (int i = m + n, k = 0; i < size; i++, k++)
387+
copyList.set(m + k, copyList.get(i));
388+
389+
/* удаляем ненужные элементы в конце списка
390+
* удаляется всегда последний элемент, так как время этого действия
391+
* фиксировано и не зависит от размера списка
392+
*/
393+
int i = size - 1;
394+
while (i != size - n - 1){
395+
copyList.remove(i);
396+
i--;
397+
}
398+
//сокращаем длину списка путём удаления пустых ячеек
399+
copyList.trimToSize();
400+
}
401+
}
402+
}
403+
```
404+
405+
Результат выполнения:
406+
```
407+
run:
408+
Список из 1.000.000 элементов заполнен
409+
Создана копия списка
410+
411+
С какой позиции удаляем? > 600000
412+
Сколько удаляем? > 20000
413+
414+
Выполняем удаление вызовом remove()...
415+
Время удаления с помощью вызова remove(): 22359
416+
Размер исходного списка после удаления: 980000
417+
418+
Выполняем удаление путем перезаписи...
419+
420+
Время удаления путём смещения: 62
421+
Размер копии списка:980000
422+
СБОРКА УСПЕШНО ЗАВЕРШЕНА (общее время: 33 секунды)
423+
```
424+
317425
[к оглавлению](#java-collections-framework)
318426

319427
## Сколько необходимо дополнительной памяти при вызове `ArrayList.add()`?

0 commit comments

Comments
 (0)