将Java中ArrayList的remove()方法的时间复杂度由O(n)改为O(1)。
文章目录
一、ArrayList的概述
1、底层实现原理
ArrayList的底层是通过动态数组的数据结构实现的。动态数组的默认长度是10,ArrayList会根据实际的需要动态的调整数组容量,将数组长度扩容为原数组长度的1.5倍。
2、删除数组元素
为什么remove()方法的时间复杂度是O(n)呢?
因为ArrayList的元素都是存储在数组里,而数组是一段连续的内存,当删除数组中的某一个元素,则需要该元素后面的所有元素向前移动一个位置。例如数组中元素是[1,2,3,4,5],删除元素3,则元素3后面的元素4需要从索引位置3移动到索引位置2,以此类推。这样删除一个元素,其后元素移动的时间复杂度就是O(n)。
二、交换元素 + HashMap 实现O(1)。
1、算法思路
①先创建一个HashMap,键是数组中元素,值是该元素在数组中的索引。
②当需要删除一个元素的时候,先去HashMap里面查找该元素对应的索引,然后将该元素交换到数组的末尾删除。
③每次把需要删除的元素交换到数组末尾删除,这样就不需要再移动元素了,只需要交换一次元素,时间复杂度从O(n)降为了O(1),思路有木有很巧妙?
④需要特别注意的是,在每次交换元素以后,需要将原来末尾元素在HashMap中的位置做一次更新,否则下一次删除的就是上一次交换之前的末尾元素了。
2、代码实现
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class ListTest {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
list.add(1);
list.add(3);
list.add(5);
list.add(7);
System.out.println(list);//[1, 3, 5, 7]
Map<Integer,Integer> map = new HashMap<>();
//1、将list中元素及其索引存放进map
for (int i = 0; i < list.size(); i++) {
map.put(list.get(i),i);
}
System.out.println(map);//{1=0, 3=1, 5=2, 7=3}
//2、将删除元素与末尾元素交换
int val = 3;//3是需要删除的元素
int tailIndex = list.size() - 1;//tailIndex是末尾元素的索引
int removeIndex = map.get(val);//removeIndex是要删除元素的索引
//交换元素
int temp = list.get(tailIndex);
list.set(tailIndex,val);
list.set(removeIndex,temp);
//交换结果
System.out.println(list);//[1, 7, 5, 3]
//注意:需要在map中更新此时temp的索引
map.put(temp,removeIndex);
System.out.println(map);//{1=0, 3=1, 5=2, 7=1}
//删除末尾元素
list.remove(tailIndex);
map.remove(val,removeIndex);//将删除元素的键值对从map删除
System.out.println(list);//[1, 7, 5]
System.out.println(map);//{1=0, 5=2, 7=1}
}
}
三、总结
通过这个代码事例的学习,在刷题的过程一定要注重细节,对于每个方法的细节要深入剖析。欢迎大家与小赵同学讨论交流,可以点赞关注私信。