数组算法

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;
}