数组的创建和初始化
数组的创建和初始化一般有两种方式,一种是循环赋值,一种是直接赋值
利用循环赋值
循环赋值的优点是赋值方便,不需要自己一个一个手写需要赋值的元素,但是这种方式缺点也很明显,就是无法指定需要赋值的元素
int[] array1 = new int[10];
for (int i = 0; i < array1.length; i++) {
array1[i] = i + 1;
}
如果想要给数组指定元素赋值的话,可以采用以下方式
直接赋值
这种赋值方式就可以自己指定需要赋值的元素了,缺点正好和 循环赋值 的优点相反,就是有点点累
// 1
int[] array2 = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
// 2
int[] array3 = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
查找一个元素
只需要在遍历数组的过程中,判断待查找元素是否与数组元素相等,如果相等放回其下标,如果在遍历结束后还没有找到该元素,则直接返回 -1
private static int findElement(int[] array, int key, int length) {
for (int i = 0; i < length; i++) {
if (key == array[i]) {
return i;
}
}
return -1;
}
增加一个元素
在添加元素之前需要判断当前数组中已赋值的元素是否超过了数组的长度,如果超过了则无法添加元素
一般数组增加元素
遍历得到当前数组中已存入的元素个数,然后在其后边插入元素即可
private static void addElement(int[] arr, int len, int key) {
// 1. 得到数组中已存储元素的个数
int size = 0;
for (int i = 0; i < len; i++) {
if (arr[i] != 0) {
size++;
}
}
// 2. 判断数组是否为满
if (size == len) {
throw new IllegalArgumentException("Add failed. Array is full.");
}
// 3. 插入元素
arr[size] = key;
}
顺序数组添加元素
在遍历数组的过程中需要找到待插入位置,需要保证元素在该位置插入之后不会影响数组的从小到大(从大到小)的顺序
private static void addOderElement(int[] arr, int len, int key) {
// 1. 得到数组中已存储元素的个数
int size = 0;
for (int i = 0; i < len; i++) {
if (arr[i] != 0) {
size++;
}
}
// 2. 判断数组是否为满
if (size == len) {
throw new IllegalArgumentException("Add failed. Array is full.");
}
// 3. 找到元素的插入位置
int index = -1;
for (int i = 0; i < size; i++) {
if (key < arr[i]) {
index = i;
break;
}
}
// 4. 将元素后移
for (int i = size; i > index; i--) {
arr[i] = arr[i - 1];
}
// 5. 插入元素
arr[index] = key;
}
删除一个元素
在遍历数组的过程中遇到和待删除元素相等的数组元素时,记录其位置,然后将当前位置之后的元素依次向前移动一位即可完成删除(其实相当于是让后面的元素覆盖了前面的元素),最后将数组内已赋值元素数量减一
private static int deleteByIndex(int[] arr, int size, int key) {
// 1. 找到删除元素在数组中的位置
int index = -1;
for (int i = 0; i < size; i++) {
if (key == arr[i]) {
index = i;
}
}
// 2. 将后边元素依次向前移动一位
if (index != -1) {
for (int i = index; i < size - 1; i++) {
arr[i] = arr[i + 1];
}
size--;
}
return size;
}
算法题热热身
判断数组是否单调
力扣 864 题
分析
数组单调说明数组中的元素要么都是递增的,要么都是递减的。所以本题的解决思路就是当数组中元素是递增的时候那它一定不可能递减,反之亦然,以此来定义两个布尔类型的变量以此来判断数组是否单调
private static boolean isMonotonic(int[] arr) {
boolean pro = true, inc = true;
for (int i = 0; i < arr.length - 1; i++) {
if (arr[i + 1] > arr[i]) {
inc = false;
} else if (arr[i + 1] < arr[i]) {
pro = false;
}
}
return pro || inc;
}
合并两个有序数组
力扣 88 题
分析
可以从数组一的最大索引值开始向前遍历,一边遍历一边将数组一和数组二中已赋值的较大元素赋值给数组一的最大索引
public static void merge01(int[] num1, int m, int[] num2, int n) {
int q = m + n - 1; // 数组 num1 的最大索引值
int size1 = m - 1, size2 = n - 1; // 数组 num1 和数组 num2 的最大索引值
while (size1 >= 0 && size2 >= 0) {
if (num1[size1] <= num2[size2]) {
num1[q--] = num2[size2--];
} else {
num1[q--] = num1[size1--];
}
}
while (size1 != -1) {
num1[q--] = num1[size1--];
}
while (size2 != -1) {
num1[q--] = num2[size2--];
}
}
优化分析
以上代码中最后两个while
循环的功能都是一样的,就是将剩余未参与比较的元素再依次赋值给数组num1
剩余未被遍历到的空间,而这一步其实可以进行优化的,数组num1
中未被赋值的元素是不需要重新再被赋值的,只需要将num2
中未被赋值的元素(如果存在的话)继续赋值。另外在第一个while
循环中的if
判断也可以替换为三元表达式,代码如下
public static void merge02(int[] num1, int m, int[] num2, int n) {
int rear = m + n - 1; // 合并元素时从 num1 的最大长度减一的索引值开始
int index1 = m - 1; // 数组 num1 的最后一个元素的索引值
int index2 = n - 1; // 数组 num2 的最后一个元素的索引值
while (index1 >= 0 && index2 >= 0) {
num1[rear--] = num1[index1] > num2[index2] ? num1[index1--] : num2[index2--];
}
while (index2 >= 0) {
num1[rear--] = num2[index2--];
}
}