目录
算法通关村 —— 不简单的数组增删改查
在面试中,数组大部分情况下都是int类型的,接下来我们就用int类型来实现数组增删改查的基本功能,接下来就让我们自己动手来实现吧。
1 数组创建和初始化
// 创建和初始化数组
// 第一种:直接创建数组然后通过循环赋值
int[] arr = new int[10];
for (int i = 0; i < 5; i++) {
arr[i] = i+1;
}
// 第二种
int[] arr2 = new int[]{0,1,2,3,4,5};
// 简化
int[] arr3 ={0,1,2,3,4,5};
第一种方法是先创建一个指定长度的数组,然后再通过循环对其赋值。但是这种方式在面试题中一般不行,因为很多题目会给定若干测试数组让你预测通过,例如像[1, 4, 6, 8, 9, 10]这样的数组就不好初始化了。所以采用第二种方法更好,很简单且实用。但注意在创建数组时大小就是元素的数量,是无法再插入元素的,如果需要增加新元素就不能这么用了。
2 数组元素查找
数组很多题目本质就是查找问题,而数组是查找到最佳载体,所以数组的题目特别多。很多复杂的算法都是为了提高查找效率,例如二分查找、二叉树、红黑树、B+树、Hash和堆等等。另一方面很多算法问题本质上都是查找问题,例如滑动窗口问题、回溯问题、动态规划问题都是在寻找目标结果。
查找元素有很多方式,下面是根据值是否相等来进行线性查找,基本实现代码如下:
/**
* 按值查找
* @param arr 查找数组
* @param size 数组元素数量
* @param key 查找元素值
* @return 相同元素索引
*/
public static int findByElement(int[] arr, int size, int key){
for (int i = 0; i <= size; i++){
if (arr[i] == key){
return i;
}
}
return -1;
}
下面再实现根据索引来查找相应元素的值,代码如下:
/**
* 按索引查找
* @param arr 查找数组
* @param size 数组元素数量
* @param index 查找元素索引
* @return 相同元素值
*/
public static int findByIndex(int[] arr, int size, int index){
if (index > size - 1){
return -1;
}
for (int i = 0; i <= size; i++){
if (i == index){
return arr[i];
}
}
return -1;
}
若数组是递增的,查找时如果相等或当前位置元素比目标值更大就停下了,下面是实现代码:
public static int findByElementInc(int[] arr, int size, int key){
for (int i = 0; i <= size; i++){
if (arr[i] == key){
return i;
} else if (arr[i] > key){
return -1;
}
}
return -1;
}
3 数组增加元素
增加和删除元素是数组最基本的操作,将给定的元素插入到有序数组的对应位置中,我们可以先找位置,再将其后的元素整体右移,最后插入到空位置上。这里要注意,算法必须能保证在数组的首部、尾部和中间位置插入都可以成功。下面是基本实现代码:
/**
* 增加元素
* @param arr 数组
* @param size 数组元素数量
* @param element 增加元素值
* @return 增加元素的索引
*/
public static int addByElementSequence(int[] arr, int size, int element){
// 若数组元素数量已达到数组最大大小,则报错
if (size >= arr.length)
return -1;
// 若比数组元素都大,则直接插在索引为size,即最后的位置
int index = size;
for (int i = 0; i < size; i++){
// 找到位置。存下索引
if (element < arr[i]){
index = i;
break;
}
}
// 后面的元素整体后移,注意要从后面的元素开始移
for (int j = size; j > index; j--){
arr[j] = arr[j-1];
}
// 插入元素
arr[index] = element;
return index;
}
除了上面的方式,还可以一开始就从后向一边移动一边查找,找到位置直接插入。这样效率更高,因为只遍历了一次,实现代码如下:
/**
* 增加元素 - 从后往前找
* @param arr 数组
* @param size 数组元素数量
* @param element 增加元素值
* @return 增加元素的索引
*/
public static int addByElementSequence2(int[] arr, int size, int element){
// 若数组元素数量已达到数组最大大小,则报错
if (size >= arr.length)
return -1;
// 若比数组元素都大,则直接插在索引为size,即最后的位置
int index = 0;
for (int i = size - 1; i >= 0; i--){
// 找到位置。存下索引
if (element < arr[i]){
arr[i+1] = arr[i];
}else if (element >= arr[i]){
arr[i+1] = element;
index = i + 1;
return index;
}
}
// 若目标值比所有元素都小,则添加到第一个位置
arr[0] = element;
return index;
}
3 删除数组元素
对于删除,就不能一边从后向前移动一边查找了,因为我们不确定删除的元素是否存在。
所以要分为两个步骤,先从最左侧开始查是否存在元素,如果元素存在,则从该位置开始执行删除操作。实现代码如下:
/**
* 按值删除
* @param arr 删除的数组
* @param size 数组大小
* @param key 删除元素值
* @return 数组大小
*/
public static int deleteByElement(int[] arr, int size, int key){
int index = -1;
for (int i = 0; i < size; i++) {
if (arr[i] == key){
index = i;
break;
}
}
// 如果删除的元素存在,则将后面的元素往前移
if (index != -1){
for (int j = index + 1; j < size; j++ ){
arr[j-1] = arr[j];
// 数组大小减一
}
size--;
}
return size;
}