目录
-
自身的特点
- 内存数据的连续性,申请的内存空间也是连续性的
- 数组内都是相同的数据类型
-
适合解决的问题
- 随机访问 (根据下标)
-
时间复杂度
- 根据下标随机访问,时间复杂度为 O(1)
- 不根据下标访问,时间复杂度不确定,一个一个找时间复杂度为 O(n),二分查找O(logn)
-
不适合的场景
- 由于数组一定要保证数据的连续性,所以不适合插入与删除的场景
- 插入
- 有序数组
- 最好的时间复杂度 O(1) ,末尾插入,不需要移动数据插入
- 最坏的时间复杂度O(n) , 开头插入,所有数据后移
- 平均复杂度 O(n)
- 无序数组
- 直接将要插入的位置的元素移到最后面,在将新元素插入到那个位置,时间复杂度为 O(1)
- 有序数组
- 删除
- 最好的时间复杂度 O(1),删除末尾元素
- 最坏的时间复杂度O(n) ,从头删除,为保证数据的连续性,必须将后面的元素前移
- 优化:不要每次删除元素都搬移数据,可以先记录下来已被删除的数据,当数据没有内存空间时,统一执行一遍删除操作
-
数组和容器的对比
- 容器 ArrayList
- 细封了很多数组操作的细节,如插入、标记删除
- 动态扩容,但动态扩容是比较耗时的,因为如果数组没有空间,会在申请一个新内存空间,将数据都copy过去。所以如果知道存储数据的大小,最好在创建ArrayList指定好大小
- 数组 Array
- 如果需要极致要求性能的话,用数据。ArrayList只能存储基本类型的包装类,无法存储基本类型,装箱和拆箱是要耗费一些性能的。
- 总结
- 业务开发,使用ArrayList足以,耗费一丢丢性能,不会影响整体
- 非常底层的开发,要求性能极致,用数组
- 容器 ArrayList
-
代码练习
/**
* 给定一个整数数组,判断是否存在重复元素。
* 如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。
*/
public class Array_Practice01 {
/**
* 解法1:先排序,将数组内的数据排序,这样相同的两个数字就会在一块,然后每个元素和每个元素的后一个元素比较,如果有相同的返回true
*
* @param nums
* @return
*/
public boolean containsDuplicate(int[] nums) {
Arrays.sort(nums);
int a = nums.length;
for (int i = 0; i < a - 1; i++) {
if (nums[i] == nums[i + 1]) {
return true;
}
}
return false;
}
/**
* 解法2:哈希表 将数组中的每个元素插入到哈希表中,如存在返回true
*
* @param nums
* @return
*/
public boolean containsDuplicate1(int[] nums) {
HashSet set = new HashSet<Integer>();
for (int i = 0; i < nums.length; i++) {
if (!set.contains(nums[i])) {
set.add(nums[i]);
} else {
return true;
}
}
return false;
}
}