数组算法
3. 数组算法
3.1 找出数组中指定元素的下标位置
/*
需求:
找出数组中指定元素的下标位置
需求分析:
在一个数组中,找出指定元素对应的下标位置。
必要条件:
1. 数组
2. 指定的值
反馈的数据:
找到的下标位置
方法分析:
方法名:
indexOf
形式参数列表:
1. int[] arr 查询数据的数组
2. int find 指定需要查询的数据
返回值类型:
int类型,操作成功返回值大于等于0,没有找到,返回 -1
固定格式:
public static
public static int indexOf(int[] arr, int find)
*/
/**
* 在一个数组中,找出指定元素对应的下标位置。
*
* @param arr 查询数据的数组
* @param find 指定需要查询的数据
* @return int类型,操作成功返回值大于等于0,没有找到,返回 -1
*/
public static int indexOf(int[] arr, int find) {
// 1. 参数合法性判断
if (null == arr || arr.length == 0) {
System.out.println("Input parameter is invalid!");
return -1;
}
// 2. 定义一个变量用于保存指定元素下标的位置
int index = -1;
// 3. 利用循环,找出在数组中指定的元素下标位置
for (int i = 0; i < arr.length; i++) {
// 下标为 i的元素,和find 一致
if (find == arr[i]) {
index = i;
break;
}
}
// 4. 返回对应的下标
return index;
}
3.2 找出指定下标上的元素
/*
2. 找出指定下标上的元素
【前景约束:数组中的所有元素值都是大于 0 的】
需求分析:
在指定的数组中,获取指定下标的元素
要求:
1. 数组容量不能为 0
2. 数组的空间首地址不能为null
3. 指定的下标范围一定是要在有效下标范围以内
0 <= index <= arr.length - 1
整个方法所需的外来数据:
1. 需要对应的数组
2. 告知指定的下标位置
返回值类型
数组是什么类型,返回值就是什么类型
方法分析:
方法名:
get
形式参数列表:
int[] arr 指定查询数据的数组
int index 指定查询数据的下标位置
返回值类型:
int 找到元素,返回对应的值,大于0,没有元素,操作失败,返回 0
固定格式:
public static
public static int get(int[] arr, int index)
*/
/**
* 在指定的数组中,获取指定下标的元素
* @param arr 指定查询数据的数组
* @param index 指定查询数据的下标位置
* @return 找到元素,返回对应的值,大于0,没有元素,操作失败,返回 0
*/
public static int get(int[] arr, int index) {
// 参数合法性判断
if (null == arr || arr.length == 0 || index < 0 || index > arr.length - 1) {
System.out.println("Input parameter is invalid!");
return 0;
}
return arr[index];
}
3.3 添加元素到数组指定下标位置 【重点】
/*
3 添加元素到数组指定下标位置 【重点】
【前景要求】
a. 数组中存在空余位置
b. 0在数组中是无效元素,仅仅是一个占位符
int[] arr = {1, 3, 5, 7, 9, 11, 13, 15, 17, 0};
需求分析:
在一个存在空余位置数组中,添加一个元素,到数组的指定下标位置
需要什么外来数据:
1. 带有空位子的数组
2. 指定下标位置
3. 指定的数据,要求数据类型一致化
需要考虑的问题:
1. 数组容量不能为 0
2. 数组的首地址不能为 null
3. 插入的下标位置必须是有效下标范围
返回的数据:
boolean 操作成功 true,否则 false
方法分析:
方法名:
add
形式参数列表:
int[] arr 存在空位置的一个int类型数组
int index 指定插入数据的下标位置
int insert 指定插入的数据
返回值类型:
boolean 操作成功 true,否则 false
固定格式:
public static
public static boolean add(int[] arr, int index, int insert);
*/
/**
* 在一个存在空余位置数组中,添加一个元素,到数组的指定下标位置
* @param arr 存在空位置的一个int类型数组
* @param index 指定插入数据的下标位置
* @param insert 指定插入的数据
* @return 操作成功 true,否则 false
*/
public static boolean add(int[] arr, int index, int insert) {
// 1. 参数合法性判断
if (null == arr || arr.length == 0 || index < 0 || index > arr.length - 1) {
System.out.println("Input parameter is invalid!");
return false;
}
// 2. 数组中从指定下标位置开始的元素,整体右移
for (int i = arr.length - 1; i > index; i--) {
/*
i = 9
index = 3
arr[9] = arr[8];
arr[8] = arr[7];
arr[7] = arr[6];
arr[6] = arr[5];
arr[5] = arr[4];
arr[4] = arr[3];
*/
arr[i] = arr[i - 1];
}
// 3. 给予指定下标位置元素赋值操作
arr[index] = insert;
return true;
}
3.4 删除数组中指定下标的元素【重点】
/*
4 删除数组中指定下标的元素【重点】
【前景要求】
a. 0 是无效元素
b. 如果数组中出现了空位置,需要使用 0 占位
需求分析:
在数组中删除指定下标的元素,从删除数据的位置开始,之后的元素需要向前移动
1 3 5 7 9 11 13 15 17 19 ==> 1 5 7 9 11 13 15 17 19 0
方法执行需要的外来数据:
删除数据的数组
一个指定的下标位置
注意事项:
1. 数组的容量不能为 0
2. 数组的首地址不能为 null
3. 删除的下标位置必须在有效下标范围以内
反馈的数据:
boolean 操作成功 true 失败 false
方法分析:
方法名:
remove
形式参数列表:
int[] arr 删除数据的目标数组
int index 指定删除的下标位置
返回值类型:
boolean 操作成功 true 失败 false
固定格式:
public static
public static boolean remove(int[] arr, int index)
*/
/**
* 在数组中删除指定下标的元素,从删除数据的位置开始,之后的元素需要向前移动
* @param arr 删除数据的目标数组
* @param index 指定删除的下标位置
* @return 操作成功 true 失败 false
*/
public static boolean remove(int[] arr, int index) {
// 参数合法性判断
if (null == arr || arr.length == 0 || index < 0
|| index > arr.length - 1) {
System.out.println("Input parameter is invalid!");
return false;
}
// 从删除位置开始循环,到数组的最大容量截止
for (int i = index; i < arr.length - 1; i++) {
/*
arr[2] = arr[3];
arr[3] = arr[4];
arr[4] = arr[5];
arr[5] = arr[6];
arr[6] = arr[7];
arr[7] = arr[8];
arr[8] = arr[9];
arr[9] = arr[10]; ArrayIndexOutOfBoundsException 数组下标越界
*/
arr[i] = arr[i + 1];
}
// 最后一位赋值为 0
arr[arr.length - 1] = 0;
return true;
}
3.5 找出数组中指定元素的所有下标位置【重点】
/*
5 找出数组中指定元素的所有下标位置【重点】
需求分析:
在数组中,找出对应的元素所在的下标位置,并且是可以在方法之外获取到当前的下标数据。
问题 1:
下标数据:
存在数据个数不可控情况!!!可能是没有,可能是多个。这样数据应该通过哪一种形式保存???
可以考虑使用数组保存下标数据。
问题 2:
使用数组保存下标数据。请问,保存下标数据的数组,容量是多少???
保存下标数据的数组容量和源数据数组容量一致!!!
方法运行需要外来的数据:
a. 源数据数组
b. 和源数据数组容量一致的保存【下标】数据的一个数组,该数组 int类型
c. 查询的数据到底是哪一个
返回的数据:
void 可行,当前方法会变成一个黑盒方法,不推荐。
boolean 可行,可以用于观察方法的运行状态,但是数据反馈不太满足我们的需求。
int 返回找到的目标元素个数,如果没有找到,返回 0
方法分析:
方法名:
findAllIndexes
形式参数列表:
int[] arr 源数据数组
int[] indexes 保存下标数据的数组
int find 需要查询的数据
返回值类型:
int 返回找到的目标元素个数,如果没有找到,返回 0
固定格式:
public static
public static int findAllIndexes(int[] arr, int[] indexes, int find)
*/
/**
* 在目标数组 arr 中,找出所有的指定数据 find,保存数据下标到 indexes数组中
* @param arr 源数据数组
* @param indexes 保存下标数据的数组
* @param find 需要查询的数据
* @return 返回找到的目标元素个数,如果没有找到,返回 0
*/
public static int findAllIndexes(int[] arr, int[] indexes, int find) {
// 参数合法性判断
if (null == arr || null == indexes || arr.length == 0 || indexes.length == 0
|| indexes.length < arr.length) {
System.out.println("Input parameter is invalid!");
// 没有找到任何一个目标数据!!!
return 0;
}
/*
需要执行循环,利用循环和 if 判断,找出在数组中指定元素下标位置。
并且保存到 indexes数组中!!!
找到第一个下标数据,保存到 indexes什么位置?
indexes数组下标为 0的位置
找到第二个下标数据,保存到 indexes什么位置?
indexes数组下标为 1的位置
我们需要一个数据,来保存下一次保存数据的下标位置
count有两个功能:
1. 记录下一次存放数据的位置
2. 记录当前找到的元素个数
*/
int count = 0;
for (int i = 0; i < arr.length; i++) {
// 找到目标元素,需要保存下标位置
if (arr[i] == find) {
// 尾插法
indexes[count++] = i;
// count += 1;
}
}
return count;
}
## 数组算法
@[toc]
#### 1. 添加元素到数组指定下标位置 【重点】
生活中的案例
一群人排队买烤冷面
前面有一个人,着急买了赶地铁,插队!!!
1 2 3 4 5 6 7 8
0 1 2 3 4 5 6 7 8
前景要求:
1. 使用int类型容量为10的数组作为演示,并且在数组中存在空位置可以插入数据使用
2. 0是无效数据,只做占位符使用
int[] array = {1, 3, 5, 7, 9, 2, 4, 6, 8, 0};
3. 插入数据中不要使用0
```java
/*
方法分析:
public static 不要问
返回值类型:
boolean 用于判断当前方法运行是否成功
方法名:
add 添加
形式参数列表:
1. int类型数组
2. 指定的下标位置
3. 插入的元素
(int[] array, int index, int insert)
public static boolean add(int[] array, int index, int insert)
*/
/**
* 添加元素到指定数组中的指定下标位置
*
* @param array int类型数组,并且存在空位置,使用0占位
* @param index 指定的下标位置,不能超出数组的有效下标范围
* @param insert int类型数据,这里暂时不考虑0
* @return 方法运行成功返回true,否则返回false
*/
public static boolean add(int[] array, int index, int insert) {
// 参数合法性判断
if (null == array || array.length == 0
|| index < 0 || index > array.length - 1) {
System.out.println("Input Parameter is Invalid!");
return false;
}
/*
需要借助于for循环
从最后一个有效位置开始,到指定插入数据位置结束
1 3 5 7 9 0
index = 2 放入 20
arr[5] = arr[4];
arr[4] = arr[3];
arr[3] = arr[2];
*/
for (int i = array.length - 1; i > index; i--) {
array[i] = array[i - 1];
}
// 把指定数据,放入到指定下标位置
array[index] = insert;
return true;
}
2. 删除数组中指定下标的元素【重点】
生活例子:
排队买海底捞
前面有人等不及了,走了~~
1 2 3 4 5 6 7 8 9 10
1 3 4 5 6 7 8 9 10
前景要求
1. 数组中的0是无效元素
2. 数组中删除指定下标的元素之后,需要将后面的元素整体前移,使用0占位
int[] arr = {1, 3, 5, 7, 9, 11, 13, 15, 17, 19};
删除下标为3的元素
==> {1, 3, 5, 9, 11, 13, 15, 17, 19, 0};
/*
方法分析:
public static 不要问
返回值类型:
boolean 监控方法的运行状态
方法名:
remove 删除 移除
形式参数列表:
1. int类型的数组
2. 指定的删除数据下标位置 有效范围以内
(int[] array, int index)
方法声明:
public static boolean remove(int[] array, int index);
*/
/**
* 在指定数组中,删除指定下标的元素
*
* @param array 删除数据的int类型数组
* @param index 删除数据的下标位置,必须是数组的有效下标范围以内
* @return 方法运行成功,返回true, 否则返回false
*/
public static boolean remove(int[] array, int index) {
// 参数合法性判断
if (null == array || array.length == 0
|| index < 0 || index > array.length - 1) {
System.out.println("Input Parameter is Invalid!");
return false;
}
/*
利用循环移动数据,删除元素,从删除位置开始,到最大下标结束
1 3 5 7 9 11
index 2
array[2] = array[3];
array[3] = array[4];
array[4] = array[5];
*/
for (int i = index; i < array.length - 1; i++) {
array[i] = array[i + 1];
}
// 最后一个原本的有效元素位置赋值为0,占位
array[array.length - 1] = 0;
return true;
}
3. 找出数组中最大元素,和下标为0元素交换位置 【重点】
前景要求:
这里使用的是int类型数组,容量为10,并且有初始化数据
int array = {1, 3, 5, 7, 9, 2, 4, 8, 10}
流程:
1. 使用for循环,找出数组中最大值的下标位置
2. 和下标为0的元素交换位置
结果{10, 3, 5, 7, 9, 2, 4, 8, 1}
/*
方法分析:
public static 不要问
返回值类型:
boolean 判断当前方法是否运行成功
方法名:
method1 假装这是一个符合命名规范的方法名
形式参数列表:
int[] array
方法声明:
public static boolean method1(int[] array)
*/
/**
* 找出数组中最大值元素,和下标为0的元素交换位置
*
* @param array int类型数组
* @return 方法运行成功返回true,失败返回false
*/
public static boolean method1(int[] array) {
// 参数合法性判断
if (null == array || array.length == 0) {
System.out.println("Input Parameter is Invalid!");
return false;
}
// 假设最大值是下标为0的元素
int maxIndex = 0;
for (int i = 1; i < array.length; i++) {
// 判断如果下标为i的元素是大于下标为maxIndex对应下标的元素
if (array[maxIndex] < array[i]) {
maxIndex = i;
}
}
// 判断当前0下标的元素不是最大值,如果是不需要交换
if (maxIndex != 0) {
int temp = array[maxIndex];
array[maxIndex] = array[0];
array[0] = temp;
}
return true;
}
4. 找出数组中次大元素,和下标为1元素交换位置 【重点】
上面的方法已经找出了对应的最大值,并且放到了下标为0的位置,我们从下标为1的位置开始,找出剩余数组的最大值下标,和下标为1的元素交换位置。
/*
方法分析:
public static 不要问
返回值类型:
boolean
方法名:
method2
形式参数列表:
这里需要一个int类型数组
int[] array
方法声明:
public static boolean method2(int[] array)
*/
/**
* 找出数组中次大值数据,放入到下标为1的位置
*
* @param array int类型数组
* @return 方法运行成功返回true,失败返回false
*/
public static boolean method2(int[] array) {
// 参数合法性判断
if (null == array || array.length == 0) {
System.out.println("Input Parameter is Invalid!");
return false;
}
int maxIndex = 1;
for (int i = 2; i < array.length; i++) {
if (array[maxIndex] < array[i]) {
maxIndex = i;
}
}
if (maxIndex != 1) {
int temp = array[maxIndex];
array[maxIndex] = array[1];
array[1] = temp;
}
return true;
}
5. 找出数组中指定元素的所有下标位置【重点】
/*
方法分析:
public static 不要问
方法名:
findAll
找出所有元素的下标位置
形式参数列表:
1. 这里需要一个查询数据的源数据数组,int类型
int[] src
2. 指定查询的元素,int
3.
问题
a. 指定元素对应的个数不能确定 最少0个,最多是源数据数组.length
b. 整个下标是 int类型
这里可以使用数组来保存查询的下标位置,而且是int类型数组
int[] index
返回值类型:
boolean
观察方法运行状态,成功与否 true false 稍稍略显苍白
void
辣鸡!!!
int
返回找到指定元素个数
没有找到对应元素,返回0.找到了返回值大于0
方法声明:
public static int findAll(int[] src, int find, int[] index)
*/
/**
* 找出源数据数组中所有指定元素的下标位置,存放到index数组内,返回值是找到的指定元素个数
*
* @param src int类型源数据数组
* @param find 查询的指定数据,int类型
* @param index 存放查询到下标的数组
* @return 返回值是找到的元素个数,没有找到返回0,找到返回值大于0
*/
public static int findAll(int[] src, int find, int[] index) {
// 参数合法性判断
if (null == src || null == index || src.length == 0 || index.lenght == 0
|| src.length > index.length) {
System.out.println("Input Parameter is Invalid!");
return 0;
}
/*
准备一个计数器
1. 找到目标元素的个数
2. index数组下一次存放元素的位置
3. 数组中【有效元素个数】
*/
int count = 0;
/* 遍历源数据数组 */
for (int i = 0; i < src.length; i++) {
/* 判断比较,比对对应的数据 */
if (src[i] == find) {
/* 这里需要把下标i保存到index数组中!!! 尾插法 */
index[count] = i;
count += 1;
}
}
return count;
}