一、概念
什么是数组?
数组是线性表最基本的结构,有序的元素序列。
二、特征
- 由相同类型的元素组成,并且元素成线性排列。
- 有固定的长度,通过下表进行查询。
- 每个元素有都有自己唯一的下标编号。
重点:第一个数据索引是0!!!最后一个数据索引是length-1!!数组的长度length和数组中存储的数据size不一定相等!!!
三、基本操作(java版本)
3.1创建与初始化
1、创建一个未初始化的数组
int[] a = new int[10];
2、初始化
int[] arr = new int[10];
//1、利用循环的方法
for (int i = 0; i < 4; i++) {
arr[i] = i+3;
}
//2、利用赋值的方法
arr[0] = 1;
arr[1] = 2;
//3、利用大括号的方法
int[] arr2 = new int[]{0, 1, 2, 3, 5, 6, 8};
int[] arr3 = {2, 5, 0, 4, 6, -10};
注:1、java中未初始化会默认初始化为0。
2、初始化可以只初始化一部分。初始化必须连续,不能出现空缺!
3、可以只初始化或者使用中间一部分。
3.2增加、删除、查询
1、增加
我们这里所指的增加,是指创建一个长度为length的数组,初始化的时候只初始化了部分(小于等于length)。
代码:
public class BasicAddByElement {
public static void main(String[] args) {
//初始化数组
int[] arr = initArray();
int size = 4;//数组中已有元素的数量
//测试中间位置插入元素
addByElementSequence(arr, size, 2);
printList("通过元素顺序插入", arr, 5);
//在上面基础上继续测试,尾部位置插入元素
size = size + 1;
addByElementSequence(arr, size, 9);
printList("通过元素顺序,尾部插入", arr, 6);
//在上面基础上继续测试,首部位置插入元素
size = size + 1;
addByElementSequence(arr, size, 1);
printList("通过元素顺序,尾部插入", arr, 7);
}
/**
* @param arr
* @param size 数组已经存储的元素数量
* @param element 待插入的元素元素
* @return
*/
public static int addByElementSequence(int[] arr, int size, int element) {
if (size >= arr.length) {
throw new IllegalArgumentException("数组满了!");
}
int index = size;
//按照顺序的插入
for (int i = 0; i < size; i++) {
if (element < arr[i]) {
index = i;
break;
}
}
for (int j = size-1; j >= index; j--) {
arr[j+1] = arr[j];
}
arr[index] = element;
return index;
}
/**
* 初始化要使用的数组
* @return
*/
private static int[] initArray() {
int[] arr = new int[20];
arr[0] = 3;
arr[1] = 4;
arr[2] = 7;
arr[3] = 8;
return arr;
}
}
注: 重点是如何查找到插入的位置,向后移动,再将值覆盖该位置的值。
2、删除
删除数组中值为key的元素。
代码:
public class BasicDelete {
public static void main(String[] args) {
int[] arr = new int[]{2, 3, 4, 9, 10, 11, 12};
System.out.println(Arrays.toString(arr));
int size = 8;
size = removeByElement(arr, size, 2);
System.out.println(size);
printList("根据索引删除", arr, size);
}
/**
* 遍历数组,如果发现目标元素,则将其删除,
* 数组的删除就是从目标元素开始,用后续元素依次覆盖前继元素
*
* @param arr 数组
* @param size 数组中的元素个数
* @param key 要删除的目标值
*/
public static int removeByElement(int[] arr, int size, int key) {
int index = -1;
if (size > arr.length) {
throw new IllegalArgumentException("数组中元素的个数不对!!");
}
for (int i = 0; i < size; i++) {
if (arr[i] == key) {
index = i;
break;
}
}
if (index != -1) {
for (int i = index + 1; i < size; i++) {
arr[i - 1] = arr[i];
}
size--;
}
return size;
}
}
注:删除并不是真正删除,只是将该位置的元素用后面的元素进行覆盖,数组长度不会变短!!
3、查询
查询数组中值为key的元素,并返回下标。
代码:
public class BasicSearch {
public static void main(String[] args) {
int[] arr = new int[]{2, 3, 4, 5, 6, 7, 8, 9, 10};
//通过元素查找
int key = 10;
System.out.println("元素" + key + "的索引位置为:" + findByElement(arr, 9, key));
}
/**
* @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;
}
}
四、基础使用
4.1单调数组
问题描述:判断一个给定的数组是否为单调数组。
示例1:
输入:int[] nums = {1, 2, 2, 3, 4, 6, 6};
输出:true
示例2:
输入:int[] nums = {1, 2, 2, 3, 4, 2, 6};
输出:false
思路:遍历数组,若当前位置的元素大于下一个位置的元素 ,直接返回FALSE,否则继续遍历。
重点:如何保存下一个位置的索引,防止出界问题!
代码:
public static boolean test(int[] nums) {
for (int i = 0; i < nums.length; i++) {
//判断i+1是否出界
int next = i < nums.length-1 ? i+1: nums.length-1;
if (nums[i]>nums[next]) {
return false;
}
}
return true;
}
4.2数组的合并
问题描述:给你两个按非递减顺序 排列的整数数组 nums1 和 nums2,另有两个整数 m 和 n ,分别表示 nums1 和 nums2 中的元素数目。请你合并 nums2 到 nums1 中,使合并后的数组同样按 非递减顺序排列。
示例1:
输入:nums1 = [1,2,3,0,0,0], m = 3, nums2 = [2,5,6], n = 3
输出:[1,2,2,3,5,6]
解释:合并 [1,2,3] 和 [2,5,6] 的结果是 [1,2,2,3,5,6]
思路:
方法一:直接将nums2接到nums1中,然后利用sort排序。
方法二:假设nums2不是一个数组,而只是一个元素!!这不就和我们之间讲过的数组的插入一样吗?此时再回到这个问题中就简单了,将nums2遍历一遍就可以了。
方法三:这是对方法一的优化,记录一下nums1上次插入的位置,不用每次遍历。
方法四:创建一个新的数组,同时遍历nums1和nums2将小的放入新数组中,小的继续遍历。
方法五:从后向前插入,A和B的元素数量是固定的,所以排序后最远位置一定是A和B元素都最大的那个,依次类推,每次都找最大的那个从后向前填就可以了。
重点:如何简化。
代码:
/**
* 方法1:先合并再排序实现排序
*
* @param nums1 第一个数组
* @param nums1_len 第一个数组的长度
* @param nums2 第二个数组,将nums2合并到nums1中
* @param nums2_len 第二个数组的长度
*/
public static void merge1(int[] nums1, int nums1_len, int[] nums2, int nums2_len) {
for (int i = 0; i < nums2_len; ++i) {
nums1[nums1_len + i] = nums2[i];
}
Arrays.sort(nums1);
}
/**
* 方法2:两个数组从后向前逐步合并
*
* @param nums1
* @param nums1_len
* @param nums2
* @param nums2_len
*/
public static void merge2(int[] nums1, int nums1_len, int[] nums2, int nums2_len) {
int i = nums1_len + nums2_len - 1;
int len1 = nums1_len - 1, len2 = nums2_len - 1;
while (len1 >= 0 && len2 >= 0) {
if (nums1[len1] <= nums2[len2])
nums1[i--] = nums2[len2--];
else if (nums1[len1] > nums2[len2])
nums1[i--] = nums1[len1--];
}
//假如A或者B数组还有剩余
while (len2 != -1) nums1[i--] = nums2[len2--];
while (len1 != -1) nums1[i--] = nums1[len1--];
}
/**
* 方法3:优化上面的方法2
*
* @param nums1
* @param nums1_len
* @param nums2
* @param nums2_len
*/
public static void merge3(int[] nums1, int nums1_len, int[] nums2, int nums2_len) {
int indexA=nums1_len-1;
int indexB=nums2_len-1;
int index=nums1_len+nums2_len-1;
while (indexA>=0&&indexB>=0){
nums1[index--]=nums1[indexA]>=nums2[indexB]?nums1[indexA--]:nums2[indexB--];
}
//假如A或者B数组还有剩余
while (indexB>=0){
nums1[index--]=nums2[indexB--];
}
}