java:算法题(持续更新)

第一题:特征值计算

案例:定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,然后求出所有元素的最大值,最小值,总和,平均值,并输出出来。

要求:所有随机数都是两位数:[10,99]
提示:求[a,b]范围内的随机数: (int)(Math.random() * (b - a + 1)) + a;

答案:

package com.atguigu3.common_algorithm.exer1;

/**
     案例:定义一个int型的一维数组,包含10个元素,分别赋一些随机整数,然后求出所有元素的最大值,最小值,总和,平均值,并输出出来。

public class ArrayExer01 {
    public static void main(String[] args) {
        //1. 动态初始化方式创建数组
        int[] arr = new int[10];
        //2. 通过循环给数组元素赋值
        for (int i = 0; i < arr.length; i++) {
            arr[i] = (int)(Math.random() * (99 - 10 + 1)) + 10;
            System.out.print(arr[i] + "\t");
        }

        System.out.println();

        //3.1 求最大值
        int max = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if(max < arr[i]){
                max = arr[i];
            }
        }
        System.out.println("最大值为:" + max);

        //3.2 求最小值
        int min = arr[0];
        for (int i = 1; i < arr.length; i++) {
            if(min > arr[i]){
                min = arr[i];
            }
        }
        System.out.println("最小值为:" + min);


        //3.3 求总和
        int sum = 0;
        for (int i = 0; i < arr.length; i++) {
            sum += arr[i];
        }
        System.out.println("总和为:" + sum);

        //3.4 求平均值
        int avgValue = sum / arr.length;
        System.out.println("平均值为:" + avgValue);


    }
}

运行结果

代码解释: 

以上代码是一个Java程序,用于创建一个包含10个随机整数的一维数组,并计算该数组的最大值、最小值、总和和平均值,然后将这些值输出。 下面是代码的主要解释: 1. 首先,通过以下代码创建一个包含10个元素的整型数组 `arr`,并用动态初始化方式分配内存空间: ```java int[] arr = new int[10]; ``` 2. 使用一个循环,从0到9,为数组的每个元素赋予随机整数值,这些随机整数的范围在10到99之间: ```java for (int i = 0; i < arr.length; i++) { arr[i] = (int)(Math.random() * (99 - 10 + 1)) + 10; System.out.print(arr[i] + "\t"); } ``` 这个循环使用了 `Math.random()` 方法生成0到1之间的随机小数,然后将其缩放到10到99之间的整数范围,并将结果存储在数组的相应位置。同时,代码也打印了数组的元素值。 3. 接下来,计算数组的最大值、最小值、总和和平均值: - 求最大值(3.1):首先,创建一个变量 `max` 并将其初始化为数组的第一个元素 `arr[0]`。然后,使用一个循环遍历数组的所有元素,如果当前元素比 `max` 大,就更新 `max` 的值。最终,`max` 将包含数组的最大值。 - 求最小值(3.2):类似地,创建一个变量 `min` 并将其初始化为数组的第一个元素 `arr[0]`。然后,使用一个循环遍历数组的所有元素,如果当前元素比 `min` 小,就更新 `min` 的值。最终,`min` 将包含数组的最小值。 - 求总和(3.3):创建一个变量 `sum` 并将其初始化为0。然后,使用一个循环遍历数组的所有元素,将每个元素的值累加到 `sum` 上。最终,`sum` 将包含数组所有元素的总和。 - 求平均值(3.4):计算平均值只需将总和 `sum` 除以数组的长度 `arr.length`。结果将存储在 `avgValue` 变量中。 4. 最后,代码将计算得到的最大值、最小值、总和和平均值打印输出到控制台。 这段代码演示了如何创建和操作一维数组以及如何执行一些基本的数学计算。

 第二题:特征值计算

案例:评委打分

分析以下需求,并用代码实现:

(1)在编程竞赛中,有10位评委为参赛的选手打分,分数分别为:5,4,6,8,9,0,1,2,7,3

(2)求选手的最后得分(去掉一个最高分和一个最低分后其余8位评委打分的平均值)

答案

package com.atguigu3.common_algorithm.exer2;

/**
 *      (1)在编程竞赛中,有10位评委为参赛的选手打分,分数分别为:5,4,6,8,9,0,1,2,7,3
 *      (2)求选手的最后得分(去掉一个最高分和一个最低分后其余8位评委打分的平均值)
 */
public class ArrayExer02 {
    public static void main(String[] args) {

        int[] scores = {5,4,6,8,9,0,1,2,7,3};
        //声明三个特征值
        int sum = 0;
        int max = scores[0];
        int min = scores[0];

        for (int i = 0; i < scores.length; i++) {
            sum += scores[i]; //累加总分
            //用于获取最高分
            if(max < scores[i]){
                max = scores[i];
            }
            //用于获取最低分
            if(min > scores[i]){
                min = scores[i];
            }
        }

        int avg = (sum - max - min) / (scores.length - 2);
        System.out.println("去掉最高分和最低分之后,平均分为:" + avg);


    }
}

运行结果;

代码解释

 这段代码是一个Java程序,用于计算在编程竞赛中,10位评委为参赛选手打分的情况下,去掉一个最高分和一个最低分后,其余8位评委打分的平均值。以下是对代码的详细解释:

1. 首先,定义了一个整数数组 `scores`,其中包含了10位评委为选手打的分数。

2. 接下来,声明了三个整数变量:`sum`、`max` 和 `min`,用于分别表示总分、最高分和最低分。初始时,这些变量都被初始化为数组中的第一个元素 `scores[0]`,这是为了后续比较找到最高分和最低分的初始值。

3. 使用 `for` 循环遍历数组 `scores` 中的每个元素,计算总分并查找最高分和最低分。

   - 在循环中,通过 `sum += scores[i]` 累加每位评委打的分数到 `sum` 变量中,以计算总分。

   - 通过条件判断语句,找到最高分和最低分。`max` 变量记录最高分,如果当前评委的分数比 `max` 大,则更新 `max` 为当前分数;`min` 变量记录最低分,如果当前评委的分数比 `min` 小,则更新 `min` 为当前分数。

4. 计算平均分 `avg`,使用公式 `(sum - max - min) / (scores.length - 2)`。这里减去了最高分和最低分,并且除以数组长度减去2,因为去掉了一个最高分和一个最低分。

5. 最后,通过 `System.out.println` 打印出去掉最高分和最低分后的平均分。

总结:这段代码主要通过遍历数组来计算总分、找到最高分和最低分,然后根据规定的公式计算出去掉最高分和最低分后的平均分,并将结果打印出来。这种方式可以在比赛中消除一些不公平的因素,如个别评委的特别高或低分对选手总分的影响。

第三题:杨辉三角1

案例:使用二维数组打印一个 10 行杨辉三角。

   提示:
   1. 第一行有 1 个元素, 第 n 行有 n 个元素
   2. 每一行的第一个元素和最后一个元素都是 1
   3. 从第三行开始, 对于非第一个元素和最后一个元素的元素。即:
   yanghui[i][j] = yanghui[i-1][j-1] + yanghui[i-1][j];

答案;

package com.atguigu3.common_algorithm.exer3;

public class YangHuiTest {
    public static void main(String[] args) {

        //1. 创建二维数组
        int[][] yangHui = new int[10][];

        //2.使用循环结构,初始化外层数组元素
        for(int i = 0;i < yangHui.length;i++){
            yangHui[i] = new int[i + 1];
            //3. 给数组的元素赋值
            //3.1 给数组每行的首末元素赋值为1
            yangHui[i][0] = yangHui[i][i] = 1;
            //3.2 给数组每行的非首末元素赋值
            //if(i >= 2){
                for(int j = 1;j < yangHui[i].length - 1;j++){ //j从每行的第2个元素开始,到倒数第2个元素结束
                    yangHui[i][j] = yangHui[i - 1][j] + yangHui[i - 1][j - 1];
                }
            //}

        }
        //遍历二维数组
        for (int i = 0; i < yangHui.length; i++) {
            for (int j = 0; j < yangHui[i].length; j++) {
                System.out.print(yangHui[i][j] + "\t");
            }
            System.out.println();
        }


    }
}

运行结果:

代码解释:

总体理解 :

这段代码是一个Java程序,用于生成并打印杨辉三角形的前十行。下面是代码的解释:

1. `int[][] yangHui = new int[10][];`:在这行代码中,创建了一个名为 `yangHui` 的二维整数数组,该数组有10行。请注意,由于杨辉三角形的每一行的长度都不同,所以在这里只初始化了外层数组,而内层数组将在后续的循环中初始化。

2. 使用一个 `for` 循环结构来初始化外层数组的元素。`for(int i = 0;i < yangHui.length;i++)`:这个循环迭代从0到9的变量 `i`,对应着杨辉三角形的前10行。

3. 在每次循环中,执行以下操作:
   - `yangHui[i] = new int[i + 1];`:创建一个长度为 `i + 1` 的新的一维数组,并将其赋值给外层数组 `yangHui` 的第 `i` 个元素。这一步实际上初始化了内层数组,使得外层数组 `yangHui` 成为一个存储各行数据的二维数组。
   - `yangHui[i][0] = yangHui[i][i] = 1;`:将每一行的第一个元素和最后一个元素设置为1,因为杨辉三角形的每一行的首尾元素都是1。

4. 在注释中的代码段 `//3.2 给数组每行的非首末元素赋值` 下,有一个内部循环用于给内层数组的非首尾元素赋值。这部分代码被注释掉了,但实际上是杨辉三角形的计算核心。

   - `for(int j = 1;j < yangHui[i].length - 1;j++)`:这个循环从每行的第2个元素开始,一直到倒数第2个元素结束,因为首尾元素已经在前面的代码中赋值为1。
   - `yangHui[i][j] = yangHui[i - 1][j] + yangHui[i - 1][j - 1];`:这行代码计算当前行的非首尾元素的值,它等于上一行的相同列元素和上一行的前一列元素之和。这是杨辉三角形的特点,每个元素等于它上方两个元素之和。

5. 最后,通过两个嵌套的 `for` 循环遍历二维数组,并使用 `System.out.print` 打印每个元素的值,以创建杨辉三角形的图形。

总之,这段代码生成了一个包含杨辉三角形前十行数据的二维数组,并将其打印出来,展示了杨辉三角形的结构。每个元素都是由它上方的两个元素相加得到的。

分段理解:

一. yangHui[i] = new int[i + 1]这一步的理解

这行代码 `yangHui[i] = new int[i + 1];` 是用来初始化杨辉三角形的每一行的内层数组的操作。让我详细解释一下这一步的含义:

- `yangHui[i]`:这表示访问二维数组 `yangHui` 的第 `i` 行(外层数组的元素),其中 `i` 是循环变量,它代表当前行的索引。

- `new int[i + 1]`:在这里,我们创建了一个新的一维整数数组,并将其分配给第 `i` 行的元素。`i + 1` 表示当前行内数组的长度,因为在杨辉三角形中,每一行的长度都是递增的,第一行有一个元素,第二行有两个元素,第三行有三个元素,以此类推。因此,我们使用 `i + 1` 来表示当前行的长度。

通过这行代码,我们为外层数组 `yangHui` 中的每一行都创建了一个内层数组,这个内层数组的长度等于当前行的行数(`i + 1`)。这是因为每一行的元素个数都不同,所以我们需要在初始化每一行的时候分别创建不同长度的内层数组来存储该行的元素。

二 . yangHui[i][0] = yangHui[i][i] = 1;的理解

这行代码 `yangHui[i][0] = yangHui[i][i] = 1;` 是用来初始化杨辉三角形每一行的首尾元素为1的操作。让我详细解释一下这一步的含义:

- `yangHui[i]` 表示访问二维数组 `yangHui` 的第 `i` 行,其中 `i` 是循环变量,代表当前行的索引。

- `[0]` 表示访问当前行的第一个元素,也就是该行的首元素。

- `[i]` 表示访问当前行的最后一个元素,也就是该行的尾元素。在杨辉三角形中,每一行的首尾元素都是1。

- `=` 是赋值操作符,将右侧的值赋给左侧的元素。

因此,这行代码实际上是将当前行的首尾元素都设置为1。这是因为在杨辉三角形中,每一行的首尾元素都是1,这是杨辉三角形的特性。其他行内部的元素是通过相邻上一行的元素相加得到的,而首尾元素固定为1。

三   for(int j = 1;j < yangHui[i].length - 1;j++){ //j从每行的第2个元素开始,到倒数第2个元素结束
                  yangHui[i][j] = yangHui[i - 1][j] + yangHui[i - 1][j - 1];
                }这句代码的理解

这段代码是用来计算杨辉三角形的每一行的非首尾元素的值,它是杨辉三角形生成的核心部分。让我详细解释这段代码的含义:

```java
for(int j = 1;j < yangHui[i].length - 1;j++){
    yangHui[i][j] = yangHui[i - 1][j] + yangHui[i - 1][j - 1];
}
```

- `for(int j = 1; j < yangHui[i].length - 1; j++)`:这是一个内部的循环,它用于遍历当前行内部的元素,从第2个元素开始(`j` 初始值为1),一直到倒数第2个元素结束(`yangHui[i].length - 1` 表示当前行的长度减去1)。

- `yangHui[i][j]`:这是访问二维数组 `yangHui` 中的当前行 `i` 的第 `j` 个元素。`i` 代表当前行的索引,`j` 代表当前元素在当前行中的索引。

- `yangHui[i - 1][j]`:这是访问上一行 `i - 1` 的相同列 `j` 的元素的值。

- `yangHui[i - 1][j - 1]`:这是访问上一行 `i - 1` 的前一列 `j - 1` 的元素的值。

这行代码的目的是计算当前行 `i` 内部的元素,这些元素的值等于上一行的相同列元素和上一行的前一列元素之和。这是杨辉三角形的特性:每个内部元素都是由它上方的两个元素相加得到的。通过这个循环,杨辉三角形的每一行内部元素都得到了正确的计算和赋值。这样,整个杨辉三角形就被生成了。

解释得详细点

当生成杨辉三角形时,每一行的内部元素(除了首尾元素)都是由上一行的相邻元素相加得到的。让我详细解释一下这段代码的工作方式:

1. 外部循环 `for(int i = 0; i < yangHui.length; i++)` 遍历每一行(从第0行到第9行)。

2. 内部循环 `for(int j = 1; j < yangHui[i].length - 1; j++)` 遍历当前行的内部元素,从第2个元素到倒数第2个元素(因为每一行的首尾元素都是1,所以不需要计算它们)。

3. 在每一行的内部循环中,使用以下公式计算当前行的元素值:
   
   `yangHui[i][j] = yangHui[i - 1][j] + yangHui[i - 1][j - 1];`

   这个公式的含义是,当前行的第 `j` 个元素等于上一行的第 `j` 个元素与上一行的第 `j - 1` 个元素之和。这是杨辉三角形的性质之一:每个内部元素都是由它上方的两个元素相加得到的。

   例如,对于第三行(从0开始计数)的内部元素,计算如下:

   - `yangHui[2][1] = yangHui[1][1] + yangHui[1][0]`,即第3行的第2个元素等于第2行的第2个元素和第2行的第1个元素之和。
   - `yangHui[2][2] = yangHui[1][2] + yangHui[1][1]`,即第3行的第3个元素等于第2行的第3个元素和第2行的第2个元素之和。

4. 这个内部循环会为当前行的所有内部元素都计算出正确的值。这样,每一行都会在循环结束时被正确填充,每个元素都表示了杨辉三角形中的相应值。

总结:上面的代码段实际上是在生成杨辉三角形的一部分,通过计算每一行的内部元素,确保每个内部元素都满足杨辉三角形的规则,即等于它上方两个元素的和。这种方式逐行递推,最终形成了整个杨辉三角形的形状。希望这次解释更加清晰明了!

第四题:杨辉三角2

给定一个非负整数 numRows生成「杨辉三角」的前 numRows 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

示例 1:

输入: numRows = 5
输出: [[1],[1,1],[1,2,1],[1,3,3,1],[1,4,6,4,1]]

示例 2:

输入: numRows = 1
输出: [[1]]

提示:

  • 1 <= numRows <= 30

第四题:杨辉三角3

给定一个非负索引 rowIndex,返回「杨辉三角」的第 rowIndex 行。

在「杨辉三角」中,每个数是它左上方和右上方的数的和。

示例 1:

输入: rowIndex = 3
输出: [1,3,3,1]

示例 2:

输入: rowIndex = 0
输出: [1]

示例 3:

输入: rowIndex = 1
输出: [1,1]

提示:

  • 0 <= rowIndex <= 33

第五题:数组的赋值

使用简单数组
(1)创建一个名为ArrayTest的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
(3)显示array1的内容。
(4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
(5)打印出array1。

代码

package com.atguigu3.common_algorithm.exer4;


public class ArrayExer04 {
    public static void main(String[] args) {
        //(1)创建一个名为ArrayExer04的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
        int[] array1,array2;
        //(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
        array1 = new int[]{2,3,5,7,11,13,17,19};
        //(3)显示array1的内容。
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }
        //(4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
        array2 = array1;
        System.out.println();
        System.out.println(array1);  //[I@58372a00
        System.out.println(array2);   //[I@58372a00

        for (int i = 0; i < array2.length; i++) {
            if(i % 2 == 0){
                array2[i] = i;
            }
        }

        System.out.println();//换行
        //(5)打印出array1。
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }
    }
}

运行结果:

内存分析

代码解释

以上代码是一个Java程序,其目的是演示数组的初始化、赋值以及数组元素的修改。以下是对代码的逐步解释:

1. 首先,定义了一个名为 `ArrayExer04` 的Java类,并在该类的 `main` 方法中进行操作。

2. 在第2行和第3行中,声明了两个 `int` 数组变量 `array1` 和 `array2`,但它们并没有被初始化。这意味着它们目前是空数组,没有分配内存空间来存储整数元素。

3. 在第5行,使用大括号 `{}` 初始化了 `array1` 数组,并赋值为包含8个素数的数组:2, 3, 5, 7, 11, 13, 17, 19。

4. 接下来,使用一个 `for` 循环在第7行到第12行中,遍历并打印 `array1` 数组的内容。这将输出数组中的所有素数。

5. 在第14行,将 `array2` 初始化为 `array1`。这意味着 `array2` 和 `array1` 现在引用相同的数组对象,它们指向相同的内存位置。

6. 在第16行和第17行中,分别打印 `array1` 和 `array2` 的内存地址。由于它们引用相同的数组,因此它们的内存地址将是相同的。

7. 接下来,在第20行到第25行中,使用一个 `for` 循环遍历 `array2` 数组的偶数索引位置(0, 2, 4, 6),并将这些位置上的元素修改为与其索引值相等。这意味着偶数索引位置上的元素会变为0, 2, 4, 6,而奇数索引位置上的元素保持不变。

8. 最后,在第27行到第32行中,再次遍历并打印 `array1` 数组的内容。由于 `array1` 和 `array2` 引用相同的数组,因此数组中的元素已经被修改,所以输出将显示被修改后的值。

需要注意的是,由于 `array1` 和 `array2` 引用相同的数组对象,因此对其中一个数组的修改也会影响另一个数组,因为它们实际上指向同一块内存空间。这是因为在第14行中,`array2` 被赋值为 `array1`,这只是将引用复制给了 `array2`,而不是创建了一个新的数组。

第六题:数组的复制

案例:复制、赋值

使用简单数组
(1)创建一个名为ArrayTest的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
(3)显示array1的内容。
(4)赋值array2变量等于array1,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
(5)打印出array1。

思考:array1和array2是什么关系?
【answer】array1和array2是两个变量,共同指向了堆空间中的同一个数组结构。即二者的地址值相同。

拓展:修改题目,实现array2对array1数组的复制

代码

package com.atguigu3.common_algorithm.exer4;


public class ArrayExer04_1 {
    public static void main(String[] args) {
        //(1)创建一个名为ArrayExer04的类,在main()方法中声明array1和array2两个变量,他们是int[]类型的数组。
        int[] array1,array2;
        //(2)使用大括号{},把array1初始化为8个素数:2,3,5,7,11,13,17,19。
        array1 = new int[]{2,3,5,7,11,13,17,19};
        //(3)显示array1的内容。
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }
        //(4)复制array1数组给array2,修改array2中的偶索引元素,使其等于索引值(如array[0]=0,array[2]=2)。
        array2 = new int[array1.length];
        for (int i = 0; i < array1.length; i++) {
            array2[i] = array1[i];
        }

        System.out.println();
        System.out.println(array1);  //[I@58372a00
        System.out.println(array2);   //[I@4dd8dc3

        for (int i = 0; i < array2.length; i++) {
            if(i % 2 == 0){
                array2[i] = i;
            }
        }

        System.out.println();//换行
        //(5)打印出array1。
        for (int i = 0; i < array1.length; i++) {
            System.out.print(array1[i] + "\t");
        }
    }
}

运行结果:

内存分析

代码解释

这段代码与之前的代码类似,但有一个重要的区别:在第4步中,它在初始化 `array2` 时创建了一个新的数组,而不是将 `array2` 直接赋值为 `array1` 的引用。以下是对代码的逐步解释:

1. 首先,定义了一个名为 `ArrayExer04_1` 的Java类,并在该类的 `main` 方法中进行操作。

2. 在第2行和第3行中,声明了两个 `int` 数组变量 `array1` 和 `array2`,但它们并没有被初始化。这意味着它们目前是空数组,没有分配内存空间来存储整数元素。

3. 在第5行,使用大括号 `{}` 初始化了 `array1` 数组,并赋值为包含8个素数的数组:2, 3, 5, 7, 11, 13, 17, 19。

4. 接下来,使用一个 `for` 循环在第7行到第12行中,遍历并打印 `array1` 数组的内容。这将输出数组中的所有素数。

5. 在第14行,创建了一个新的 `array2` 数组,其长度与 `array1` 相同。这样就分配了一块新的内存空间来存储 `array2` 的元素。

6. 在第16行到第21行中,通过循环将 `array1` 数组的元素复制到了 `array2` 数组中。现在,`array2` 包含了与 `array1` 相同的元素值,但它们是两个不同的数组对象。

7. 接下来,在第23行和第24行中,分别打印 `array1` 和 `array2` 的内存地址。由于它们是两个不同的数组对象,因此它们的内存地址将不相同。

8. 在第26行到第31行中,使用一个 `for` 循环遍历 `array2` 数组的偶数索引位置(0, 2, 4, 6),并将这些位置上的元素修改为与其索引值相等。这意味着 `array2` 中的偶数索引位置上的元素会变为0, 2, 4, 6,而奇数索引位置上的元素保持不变。

9. 最后,在第33行到第38行中,再次遍历并打印 `array1` 数组的内容。由于 `array1` 和 `array2` 是两个不同的数组对象,因此修改 `array2` 不会影响 `array1`,所以输出将显示未被修改的值。

总之,与之前的代码不同,这次代码创建了一个新的数组 `array2`,并将 `array1` 的值复制到 `array2`,使它们成为两个独立的数组对象,因此修改 `array2` 不会影响 `array1`。

第七题:数组元素的反转

案例:
定义数组:int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};
如何实现数组元素的反转存储?你有几种方法。

代码

package com.atguigu3.common_algorithm.exer5;


public class ArrayExer05 {
    public static void main(String[] args) {
        int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};

        //遍历
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
        System.out.println();

        //反转操作
        //方式1:
//        for(int i = 0;i < arr.length/2;i++){
//            //交互arr[i] 与 arr[arr.length - 1 - i]位置的元素
//            int temp = arr[i];
//            arr[i] = arr[arr.length - 1 - i];
//            arr[arr.length - 1 - i] = temp;
//        }
        //方式2:
        for(int i = 0,j = arr.length - 1;i < j;i++,j--){
            //交互arr[i] 与 arr[j]位置的元素
            int temp = arr[i];
            arr[i] = arr[j];
            arr[j] = temp;
        }

        //方式3:不推荐
//        int[] newArr = new int[arr.length];
//        for(int i = arr.length - 1;i >= 0;i--){
//            newArr[arr.length - 1 - i] = arr[i];
//        }

//        arr = newArr;

        //遍历
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
    }
}

运行结果:

实现思想:数组对称位置的元素互换。

代码解释

以上代码是一个 Java 程序,主要用于演示如何反转一个整数数组。下面我将逐行解释这段代码的功能和工作原理:

1. `int[] arr = new int[]{34,54,3,2,65,7,34,5,76,34,67};`:定义一个整数数组 `arr` 并初始化它包含了一组整数值。

2. 遍历数组元素并打印:使用一个 `for` 循环遍历数组 `arr` 中的元素,并将每个元素以制表符分隔打印出来,形成一行输出。

3. 反转操作:接下来有三种不同的方式来反转数组 `arr` 中的元素。

   a. **方式1**(已注释掉):使用一个 `for` 循环从数组的开始到中间,交换元素的位置,将第一个元素与倒数第一个元素交换,第二个元素与倒数第二个元素交换,以此类推。

   b. **方式2**:使用两个索引 `i` 和 `j` 分别从数组的开始和末尾向中间移动,交换元素的位置,将第一个元素与最后一个元素交换,第二个元素与倒数第二个元素交换,以此类推。这是一种更常见的反转数组的方式。

   c. **方式3**(已注释掉):创建一个新的整数数组 `newArr`,然后使用一个 `for` 循环将原数组 `arr` 中的元素从后向前复制到新数组 `newArr` 中,最后将 `arr` 指向新数组 `newArr`。这是一种不常见的反转数组的方式,通常不推荐使用。

4. 再次遍历数组并打印:使用另一个 `for` 循环遍历已经反转后的数组 `arr` 中的元素,并将每个元素以制表符分隔打印出来,形成一行输出。

最终,该代码会输出原始数组 `arr` 中的元素以及反转后的数组元素,以展示不同反转方式的效果。通常,方式2是反转数组的推荐方式,因为它既简单又高效。方式1和方式3是冗长和不必要的。

方式一详细解释:

当使用方式一来反转一个数组时,它采用了一个循环,该循环从数组的开头和结尾同时开始,然后交换元素的位置,直到达到数组中间。以下是方式一的详细解释:

1. 定义一个整数数组 `arr`,包含了一组整数值。

2. 使用一个 `for` 循环来遍历数组中的元素,循环的条件是 `i < arr.length/2`,这确保了我们只遍历数组的前半部分元素。

3. 在循环的每一次迭代中,我们执行以下操作:
   - 创建一个名为 `temp` 的整数变量,用于临时存储数组中的一个元素的值。
   - 将数组的第 `i` 个元素的值(即 `arr[i]`)赋给 `temp`,以保存它。
   - 然后,将数组的第 `i` 个元素的值设置为数组的倒数第 `i` 个元素的值(即 `arr[i] = arr[arr.length - 1 - i]`)。
   - 最后,将数组的倒数第 `i` 个元素的值设置为 `temp`,以完成元素的交换。

4. 当循环执行完毕后,整个数组中的元素都被反转了。

5. 最后,使用另一个 `for` 循环遍历已经反转后的数组 `arr` 中的元素,并将每个元素以制表符分隔打印出来,形成一行输出。

这样,通过方式一,数组中的元素从前往后逐对交换,直到整个数组都被反转。但是需要注意的是,这种方式相对于方式二来说多了一半的交换操作,因此效率略低。方式二使用两个索引同时从数组两端向中间移动,只需进行一半的交换操作,因此更为高效。

方式一流程:

arr.length=11
当i=0时     i<11  arr[0]=34 temp =arr[0]=34

这时把arr[0]里面的34给了temp  这时arr[0]的位置就空出来了  

arr[0] = arr[11-1-0]   = arr[0] =arr[10] =67

这时把arr[10]=67的值给arr[0]  这时的arr[0] =67

这时我们的arr[10]就空出来 

这时我们在把temp的34给arr[10]  变成arr[10]  =34

当i=1 i=2 i=3 i=4 i=5 时  以此类推

arr[i] = arr[arr.length - 1 - i] 怎么去理解

`arr[i] = arr[arr.length - 1 - i]` 是一行代码,用于实现数组元素的交换操作。让我解释这行代码的含义:

- `i` 是当前循环迭代中的索引,表示数组的前半部分元素的索引。
- `arr[i]` 表示数组 `arr` 中索引为 `i` 的元素的值,即当前迭代中的第一个元素。
- `arr.length` 表示数组 `arr` 的长度,也就是数组中元素的总数。
- `arr.length - 1 - i` 计算出了数组中索引为 `i` 元素对应的在数组中的对称位置的索引,即与当前元素交换的另一个元素的索引。

所以,`arr[i] = arr[arr.length - 1 - i]` 的含义是将数组中索引为 `i` 的元素的值赋值给数组中索引为 `arr.length - 1 - i` 的元素。这个操作实际上就是在进行元素交换,将数组的第 `i` 个元素与数组的倒数第 `i` 个元素互相交换位置。

这是一种常见的技巧,用于反转数组或进行元素位置的交换,通过使用两个索引来实现对称位置的元素交换,从而达到数组反转的目的。

当理解`arr[i] = arr[arr.length - 1 - i]`这行代码时,你可以按照以下步骤来思考:

1. 首先,我们要理解`arr[i]`和`arr[arr.length - 1 - i]`分别表示什么:

   - `arr[i]`表示数组`arr`中索引为`i`的元素的值。
   - `arr.length`表示数组`arr`的长度,也就是数组中元素的总数。
   - `arr.length - 1 - i`是一个计算,它找到了与索引`i`对称的位置在数组中的索引。

2. 考虑一个具体的例子来帮助理解,假设数组`arr`有11个元素,索引从0到10,那么`arr.length`的值就是11。

   - 当`i`为0时,`arr[0]`表示数组的第一个元素,而`arr[arr.length - 1 - 0]`表示数组的倒数第一个元素(也就是第11个元素,因为`arr.length - 1`是10)。

   - 当`i`为1时,`arr[1]`表示数组的第二个元素,而`arr[arr.length - 1 - 1]`表示数组的倒数第二个元素。

   - 以此类推,当`i`为2时,`arr[2]`表示数组的第三个元素,而`arr[arr.length - 1 - 2]`表示数组的倒数第三个元素。

3. 因此,`arr[i] = arr[arr.length - 1 - i]`这行代码的作用是将数组`arr`中索引为`i`的元素的值与数组中索引为`arr.length - 1 - i`的元素的值进行交换。

这个代码行的核心思想是使用`i`从数组的前面向后遍历,同时使用`arr.length - 1 - i`从数组的后面向前遍历,然后将它们的元素值互相交换,实现了数组的反转操作。这个交换操作使得数组中的元素从前到后逐对交换,最终完成了数组的反转。希望这个详细解释能帮助你更好地理解这行代码的作用。

方式二详细解释:

方式二是一种常见的用于反转数组的方法,它使用两个索引变量分别从数组的两端向中间移动,逐对交换元素的位置。以下是方式二的详细解释:

1. 首先,定义两个整数变量 `i` 和 `j`,分别初始化为数组的第一个元素的索引(`i = 0`)和数组的最后一个元素的索引(`j = arr.length - 1`)。这两个索引将分别指向数组的前端和后端。

2. 使用一个循环,通常是一个 `for` 循环,条件是 `i < j`,这个条件确保只在 `i` 指向的元素在 `j` 指向的元素之前执行交换操作。

3. 在循环的每一次迭代中,执行以下操作:
   - 交换 `arr[i]` 和 `arr[j]` 的值。这意味着将数组中索引为 `i` 的元素与索引为 `j` 的元素交换位置。
   - 增加 `i`,也就是将 `i` 向右移动一个位置,以指向下一个元素。
   - 减少 `j`,也就是将 `j` 向左移动一个位置,以指向下一个元素。

4. 继续循环,重复步骤3,直到 `i` 不再小于 `j`,这意味着整个数组已经被反转。

5. 循环结束后,数组 `arr` 中的元素的顺序已经被完全反转。

这个方式的关键思想是使用两个索引,一个从前往后,一个从后往前,逐步缩小它们之间的距离,同时交换它们所指向的元素的值。通过这种方式,数组中的元素从前到后逐对交换,最终达到了反转数组的目的。

这是一种效率高且常见的反转数组的方式,因为它只需要一次遍历数组,而不需要额外的数组来存储中间结果,因此在性能上比方式一和方式三更优。

方式二流程

当i=0 时  j=10;

当i=1 时  j=9;

当i=2 时  j=8;

当i=3 时  j=7;

当i=4 时  j=6;

当i=5时  j=5;

当i=0 j=10  时

arr[0]=34;

temp =34 ;

这时的arr[0]就空出来 

把arr[10]=67赋值给arr[0]  这时的arr[0]  = 67;  这时的arr[10] 就空出来 

然后把tmpe的值34赋值给arr[10]

这样就完成了arr[0] 与arr[10]的交换

直到i<j 也就是说直到i=4  j=6时  就不在交换

方式三详细解释:

方式三是通过创建一个新的数组来反转原数组的方式。以下是方式三的详细解释:

1. 首先,定义一个新的整数数组 `newArr`,该数组的长度与原数组 `arr` 的长度相同,即 `int[] newArr = new int[arr.length];`。这个新数组用于存储反转后的元素。

2. 使用一个 `for` 循环,循环变量 `i` 从原数组的最后一个元素开始,逐步减小,直到 `i` 为0为止。

3. 在循环的每一次迭代中,将原数组 `arr` 中的元素 `arr[i]` 复制到新数组 `newArr` 中的位置 `newArr[arr.length - 1 - i]`,即将原数组中的最后一个元素复制到新数组的第一个位置,将倒数第二个元素复制到新数组的第二个位置,以此类推。

4. 当循环结束时,新数组 `newArr` 中的元素已经按照与原数组 `arr` 相反的顺序排列,完成了数组的反转操作。

5. 最后,可以选择将原数组 `arr` 指向新数组 `newArr`,以便在后续代码中使用反转后的数组。这是通过 `arr = newArr;` 来实现的。

需要注意的是,方式三虽然可以实现数组反转,但它需要额外的内存来存储新数组 `newArr`,因此在空间复杂度上比较低效。而方式二是一种更常用的高效方法,因为它只需要在原数组上进行元素位置的交换,不需要额外的数组。所以通常情况下,方式三不如方式二高效。

方式三流程

当i=10时

把arr[11]=67 的值  复制到新数组newArr[0]上

newArr[0]=arr[10]=67

newArr[2]=arr[9]=34

即将原数组中的最后一个元素复制到新数组的第一个位置,将倒数第二个元素复制到新数组的第二个位置,以此类推。

第八题: 数组的扩容

案例1:数组的扩容:

现有数组 int[] arr = new int[]{1,2,3,4,5};
现将数组长度扩容1倍,并将10,20,30三个数据添加到arr数组中,如何操作?

代码

package com.atguigu4.search_sort.exer1;

public class ArrayExer01_1 {
    public static void main(String[] args) {
        int[] arr = new int[]{1,2,3,4,5};

        //扩容1倍容量
//        int[] newArr = new int[arr.length * 2];
        //或
        int[] newArr = new int[arr.length << 1];

        //将原有数组中的元素复制到新的数组中
        for (int i = 0; i < arr.length; i++) {

            newArr[i] = arr[i];
        }

        //将10,20,30三个数据添加到新数组中
        newArr[arr.length] = 10;
        newArr[arr.length + 1] = 20;
        newArr[arr.length + 2] = 30;

        //将新的数组的地址赋值给原有的数组变量
        arr = newArr;

        //遍历arr
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }
    }
}

运行结果:

代码解释

以上代码是一个Java程序,它演示了如何扩容一个整数数组并将新元素添加到扩容后的数组中。让我逐步解释代码的每一部分:

1. 创建一个名为 `ArrayExer01_1` 的Java类。

2. 在 `main` 方法中,首先创建一个初始整数数组 `arr`,其中包含五个整数元素:1, 2, 3, 4, 5。

3. 接下来,需要创建一个新的整数数组 `newArr` 来存储扩容后的元素。数组 `newArr` 的长度是原始数组 `arr` 长度的两倍,这是通过位运算 `arr.length << 1` 来计算的,这相当于将原始长度左移一位,即乘以2。

4. 使用一个 `for` 循环,将原始数组 `arr` 中的元素复制到新数组 `newArr` 中。这个循环遍历了 `arr` 中的每个元素,并将它们复制到相同索引位置的 `newArr` 中。

5. 接下来,将三个新的整数值(10, 20, 30)添加到新数组 `newArr` 中。它们被添加到原始数组 `arr` 的末尾,通过索引 `arr.length`、`arr.length + 1` 和 `arr.length + 2` 来完成。

6. 最后,将新数组 `newArr` 的引用赋给原始数组变量 `arr`。这意味着现在 `arr` 引用了扩容后的数组,原始数组 `arr` 不再引用原始数组,而是指向了新数组 `newArr`。

7. 最后一个 `for` 循环用于遍历并打印数组 `arr` 中的所有元素,以展示扩容和元素添加的结果。

总之,这段代码演示了如何通过创建一个新的、更大容量的数组来实现扩容,并将原有数组的元素复制到新数组中,然后将新数组的引用赋给原有数组变量,从而完成了数组的扩容操作。

解释通过索引 arr.length、arr.length + 1 和 arr.length + 2 来完成。

在代码的这一部分中,我们要向新数组 `newArr` 中添加三个新的整数值(10, 20, 30)。这三个值将被添加到新数组的末尾。

首先,我们知道新数组的长度是原始数组 `arr` 长度的两倍,因此 `newArr` 的长度是 `arr.length * 2`。由于数组的索引是从0开始的,所以新数组的有效索引范围是从0到 `newArr.length - 1`。

1. `newArr[arr.length] = 10;`:这行代码将值10添加到新数组 `newArr` 的索引位置为 `arr.length` 的地方。由于 `arr.length` 正好等于原始数组 `arr` 的长度,所以这个操作相当于在新数组的末尾添加了值10。

2. `newArr[arr.length + 1] = 20;`:这行代码将值20添加到新数组 `newArr` 的索引位置为 `arr.length + 1` 的地方。因为 `arr.length` 对应着新数组的末尾,所以 `arr.length + 1` 对应着新数组的倒数第二个位置。

3. `newArr[arr.length + 2] = 30;`:最后,这行代码将值30添加到新数组 `newArr` 的索引位置为 `arr.length + 2` 的地方。因为 `arr.length` 对应着新数组的末尾,所以 `arr.length + 2` 对应着新数组的倒数第三个位置。

总之,这三行代码通过使用数组的索引来将新的整数值添加到新数组 `newArr` 的末尾,索引的计算是基于原始数组 `arr` 的长度和新数组的长度。这样,我们就成功地将三个新值添加到了新数组中。

第九题: 数组的缩容

案例:数组的缩容:

现有数组 int[] arr={1,2,3,4,5,6,7}。现需删除数组中索引为4的元素。

代码

package com.atguigu4.search_sort.exer1;


public class ArrayExer01_2 {
    public static void main(String[] args) {
        int[] arr={1,2,3,4,5,6,7};

        int deleteIndex = 4;

        //方式1:不新建数组
//        for(int i = deleteIndex;i < arr.length - 1;i++){
//            arr[i] = arr[i + 1];
//        }
//
//        //修改最后元素,设置为默认值
//        arr[arr.length - 1] = 0;


        //方式2:新建数组,新的数组的长度比原有数组的长度少1个
        int[] newArr = new int[arr.length - 1];
        for (int i = 0; i < deleteIndex; i++) {
            newArr[i] = arr[i];
        }

        for(int i = deleteIndex;i < arr.length - 1;i++){
            newArr[i] = arr[i + 1];
        }

        arr = newArr;

        //遍历arr数组
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + "\t");
        }

    }
}

运行结果;

方式一;

方式2 :

代码解释

以上代码是一个 Java 程序,它演示了如何从一个整数数组中删除指定索引位置的元素。这个程序使用了两种不同的方法来实现这个目标,并且在删除元素后遍历了更新后的数组。下面对代码进行解释:

1. 首先,声明了一个名为 `ArrayExer01_2` 的 Java 类。

2. 在 `main` 方法中,创建了一个整数数组 `arr`,其中包含了一组整数。

3. 定义了一个整数变量 `deleteIndex`,它表示要删除的元素的索引位置,此处设置为 `4`。

4. 然后,程序展示了两种不同的方式来从数组 `arr` 中删除指定索引位置的元素:

   a. **方式1(注释掉的部分)**:在这种方式下,程序使用一个循环来移动数组中的元素,将要删除的元素之后的元素依次往前移动一个位置,然后将最后一个元素设置为默认值 `0` 来占位。这样就模拟了删除元素的效果。但需要注意的是,这种方式修改了原始数组 `arr`,因此如果需要保留原始数组,就需要在删除操作之前创建一个备份。

   b. **方式2**:在这种方式下,程序创建了一个新的整数数组 `newArr`,其长度比原数组 `arr` 少 1,用于存储删除元素后的结果。然后,程序使用两个循环来填充 `newArr`,第一个循环将删除元素之前的元素复制到 `newArr` 中,第二个循环将删除元素之后的元素复制到 `newArr` 中。最后,程序将 `arr` 引用指向了新的数组 `newArr`,从而实现了删除元素的效果。

5. 最后,程序通过一个循环遍历 `arr` 数组,并打印出删除元素后的数组内容。

总之,这段代码演示了如何从数组中删除指定索引位置的元素,并提供了两种不同的实现方式。方式1修改原始数组,方式2创建一个新的数组来存储删除元素后的结果。方式2更安全,因为它不会改变原始数组,但需要额外的内存来存储新的数组。

方式一的详细解释

方式一使用了一个循环来删除数组中指定索引位置的元素,并且修改了原始数组。下面详细解释方式一的每个步骤:

1. 首先,定义了一个整数变量 `deleteIndex`,表示要删除的元素的索引位置,这里设置为 `4`,意味着要删除数组 `arr` 中索引为 4 的元素(数组索引从 0 开始计数)。

2. 接下来,使用一个 `for` 循环来遍历数组 `arr`。循环的起始条件是 `i` 等于 `deleteIndex`,即从要删除的元素的位置开始。

3. 在循环中,执行了如下操作:
   
   - `arr[i] = arr[i + 1];`:这行代码将当前位置 `i` 处的元素设置为下一个位置 `i + 1` 处的元素的值。通过这行代码,当前位置的元素被后一个位置的元素覆盖,相当于将后一个元素向前移动了一个位置。

4. 循环继续,`i` 递增,直到循环结束。此时,整个数组中的元素都向前移动了一个位置,覆盖了要删除的元素。

5. 最后,为了确保数组长度不变,需要修改最后一个元素,将其设置为默认值 `0` 或者其他适当的值。这是因为前面的循环将最后一个元素移到了倒数第二个位置,但是原数组的长度不变,所以需要将最后一个位置的元素设置为默认值。

总结来说,方式一通过循环遍历数组,从要删除的元素位置开始,将每个元素向前移动一个位置,直到删除元素后,最后一个位置需要被设置为默认值,以保持数组长度不变。这种方式会修改原始数组 `arr`,慎用,特别是在需要保留原始数组的情况下。

方式二的详细解释

方式二使用了一个新的数组 `newArr` 来存储删除指定索引位置的元素后的结果,不会修改原始数组 `arr`。以下是方式二的详细解释:

1. 创建一个整数数组 `newArr`,它的长度比原始数组 `arr` 少 1,用于存储删除元素后的结果。

2. 使用一个 `for` 循环来遍历 `arr` 数组的元素,循环的条件是 `i < deleteIndex`,即遍历到要删除元素的位置之前。

   - 在循环中,将 `arr` 数组中的元素复制到 `newArr` 中相同的位置。这是因为删除元素前的元素不受影响,可以直接复制到新数组中。

3. 在第一个循环结束后,`newArr` 中已经包含了要删除元素之前的所有元素。

4. 使用另一个 `for` 循环来继续遍历 `arr` 数组的元素,循环的条件是 `i >= deleteIndex` 且 `i < arr.length - 1`,这是为了遍历要删除的元素之后的元素。

   - 在这个循环中,将 `arr` 数组中的元素复制到 `newArr` 中的前一个位置,也就是将要删除的元素之后的元素依次往前移动一个位置。

5. 在第二个循环结束后,`newArr` 中已经包含了除了要删除的元素之外的所有元素,而且这些元素都是按照原始顺序排列的。

6. 最后,将 `arr` 引用指向新的数组 `newArr`,这样原始数组 `arr` 就指向了删除元素后的新数组。

7. 最终,通过一个循环遍历新的数组 `arr`,打印出删除元素后的数组内容。

总结来说,方式二通过创建一个新的数组 `newArr` 来存储删除元素后的结果,不修改原始数组 `arr`。它分两个循环处理,第一个循环复制删除元素之前的元素,第二个循环复制删除元素之后的元素,然后通过修改数组引用将原始数组指向新数组来实现删除操作。这种方式保留了原始数组的完整性,是一种更安全的方法。

第十题:线性查找

案例1:线性查找

定义数组:int[] arr1 = new int[]{34,54,3,2,65,7,34,5,76,34,67};
查找元素5是否在上述数组中出现过?如果出现,输出对应的索引值。

代码

package com.atguigu4.search_sort.exer2;


public class LinearSearchTest {
    public static void main(String[] args) {

        int[] arr1 = new int[]{34,54,3,2,65,7,34,5,76,34,67};

        int target = 5;
//        target = 15;

        //查找方式:线性查找
        //方式1:
//        boolean isFlag = true;
//        for(int i = 0;i < arr1.length;i++){
//            if(target == arr1[i]){
//                System.out.println("找到了" + target + ",对应的位置为:" + i);
//                isFlag = false;
//                break;
//            }
//        }
//
//        if(isFlag){
//            System.out.println("不好意思,没有找到此元素");
//        }

        //方式2:
        int i = 0;
        for(;i < arr1.length;i++){
            if(target == arr1[i]){
                System.out.println("找到了" + target + ",对应的位置为:" + i);
                break;
            }

        }

        if(i == arr1.length){
            System.out.println("不好意思,没有找到此元素");
        }


    }
}

代码解释

这段代码是一个Java程序,它实现了线性查找(Linear Search)算法来查找一个目标值在一个整数数组中的位置。以下是对代码的详细解释:

1. 导入包:代码开头的`package com.atguigu4.search_sort.exer2;`指定了这个类所属的包。

2. 主方法(`public static void main(String[] args)`):这是程序的入口点,代码从这里开始执行。

3. 创建整数数组(`int[] arr1 = new int[]{34,54,3,2,65,7,34,5,76,34,67};`):在这里定义了一个名为`arr1`的整数数组,其中包含了一些整数值。

4. 设置目标值(`int target = 5;`):这里定义了一个名为`target`的整数变量,它表示要查找的目标值。在当前代码中,目标值被设置为5,但也可以将其设置为其他整数以进行不同的查找。

5. 使用线性查找方式查找目标值:
   - 方式1:这部分代码被注释掉了,但是它是一种典型的线性查找方式。它使用一个布尔变量`isFlag`来跟踪是否找到了目标值。然后,通过一个`for`循环遍历整数数组`arr1`,检查每个元素是否等于目标值。如果找到了目标值,就打印出它的位置,并将`isFlag`设置为`false`,然后使用`break`语句退出循环。如果遍历完整个数组后`isFlag`仍然为`true`,则表示没有找到目标值。
   
   - 方式2:这部分代码是实际执行的线性查找方式。它使用一个整数变量`i`来表示目标值的位置。通过一个`for`循环遍历整数数组`arr1`,检查每个元素是否等于目标值。如果找到了目标值,就打印出它的位置,并使用`break`语句退出循环。如果遍历完整个数组后`i`等于数组的长度(`i == arr1.length`),则表示没有找到目标值。

总之,这段代码演示了如何使用线性查找算法在一个整数数组中查找目标值,并根据查找结果输出相应的消息。方式1和方式2是两种不同的实现方式,方式2更加简洁,但方式1也是一种有效的线性查找方法。

方式一详细解释

当您运行方式一时,它使用了一个名为`isFlag`的布尔变量来跟踪是否找到了目标值。下面是对方式一的详细解释:

```java
// 方式1:
boolean isFlag = true; // 初始化一个布尔变量isFlag为true,表示初始状态下还没有找到目标值
for (int i = 0; i < arr1.length; i++) { // 使用for循环遍历整数数组arr1
    if (target == arr1[i]) { // 如果目标值等于当前数组元素
        System.out.println("找到了" + target + ",对应的位置为:" + i); // 打印出找到目标值的位置
        isFlag = false; // 设置isFlag为false,表示已经找到目标值
        break; // 退出for循环,因为已经找到目标值
    }
}

if (isFlag) { // 如果isFlag仍然为true,表示没有找到目标值
    System.out.println("不好意思,没有找到此元素");
}
```

这是方式一的执行流程:

1. 初始化一个布尔变量`isFlag`为`true`,表示初始状态下还没有找到目标值。

2. 使用`for`循环遍历整数数组`arr1`,遍历从索引0到数组的最后一个元素。在循环的每一轮中,它检查当前数组元素是否等于目标值`target`。

3. 如果找到了目标值,就执行以下操作:
   - 打印出消息,指示找到了目标值以及其位置。
   - 将`isFlag`设置为`false`,表示已经找到目标值。
   - 使用`break`语句退出`for`循环,因为不需要再继续查找了。

4. 在`for`循环结束后,检查`isFlag`的值。如果`isFlag`仍然为`true`,表示在整个数组中都没有找到目标值,因此打印一条消息表示没有找到此元素。

总之,方式一通过设置一个布尔变量`isFlag`来跟踪查找的状态,如果找到目标值,则将`isFlag`设置为`false`,如果在循环结束后`isFlag`仍然为`true`,则表示没有找到目标值。这是一种典型的线性查找实现方式,但方式二更加简洁。

方式二详细解释

方式二是使用一个整数变量`i`来表示目标值的位置,通过一个`for`循环遍历整数数组`arr1`来查找目标值的位置。以下是方式二的详细解释:

```java
// 方式2:
int i = 0; // 初始化一个整数变量i为0,用于表示目标值的位置
for (; i < arr1.length; i++) { // 使用for循环遍历整数数组arr1
    if (target == arr1[i]) { // 如果目标值等于当前数组元素
        System.out.println("找到了" + target + ",对应的位置为:" + i); // 打印出找到目标值的位置
        break; // 退出for循环,因为已经找到目标值
    }
}

if (i == arr1.length) { // 如果i等于数组的长度,表示在整个数组中都没有找到目标值
    System.out.println("不好意思,没有找到此元素");
}
```

这是方式二的执行流程:

1. 初始化一个整数变量`i`为0,用于表示目标值的位置。

2. 使用`for`循环遍历整数数组`arr1`,遍历从索引0到数组的最后一个元素。在循环的每一轮中,它检查当前数组元素是否等于目标值`target`。

3. 如果找到了目标值,就执行以下操作:
   - 打印出消息,指示找到了目标值以及其位置。
   - 使用`break`语句退出`for`循环,因为不需要再继续查找了。

4. 在`for`循环结束后,检查`i`的值。如果`i`等于数组的长度,表示在整个数组中都没有找到目标值,因此打印一条消息表示没有找到此元素。

方式二的优点是代码更加简洁,不需要额外的布尔变量来跟踪查找的状态。它通过检查`i`是否等于数组的长度来判断是否找到了目标值。如果在循环结束后`i`仍然等于数组的长度,那么就表示没有找到目标值。这种方式更加紧凑和易读。

第十一题:二分法查找

代码:

package com.atguigu4.search_sort.exer2;


public class BinarySearchTest {
    public static void main(String[] args) {

        int[] arr2 = new int[]{2,4,5,8,12,15,19,26,37,49,51,66,89,100};

        int target = 5;
//        target = 17;

        int head = 0;//默认的首索引
        int end = arr2.length - 1;//默认的尾索引


        boolean isFlag = false;//判断是否找到了指定元素

        while(head <= end){

            int middle = (head + end) / 2;

            if(target == arr2[middle]){
                System.out.println("找到了" + target + ",对应的位置为:" + middle);
                isFlag = true;
                break;
            }else if(target > arr2[middle]){
                head = middle + 1;
            }else{//target < arr2[middle]
                end = middle - 1;
            }
        }

        if(!isFlag){
            System.out.println("不好意思,未找到");
        }
    }
}

代码解释:

这段代码是一个使用二分查找算法来查找一个有序整数数组中特定目标元素的Java程序。下面是对代码的详细解释:

1. 首先,定义了一个名为`BinarySearchTest`的Java类,其中包含了`main`方法,即程序的入口点。

2. 在`main`方法中,创建了一个有序整数数组`arr2`,该数组包含了一些预先排好序的整数。

3. 定义了一个整数变量`target`,用于存储要查找的目标元素的值。在此代码中,`target`被初始化为5,表示要查找值为5的元素。

4. 接下来,定义了两个整数变量`head`和`end`,它们分别表示查找范围的起始索引和结束索引。初始时,`head`被设置为0,表示查找范围的开头,`end`被设置为数组`arr2`的最后一个元素的索引,表示查找范围的末尾。

5. 创建了一个布尔变量`isFlag`,用于标志是否找到了目标元素。初始时,`isFlag`被设置为`false`,表示尚未找到目标元素。

6. 进入一个`while`循环,条件是`head`小于等于`end`,即查找范围没有缩小到一个空范围。循环将在找到目标元素或确定不存在目标元素时终止。

7. 在循环内部,计算中间元素的索引并将其存储在`middle`变量中。这是通过将`head`和`end`相加然后除以2来实现的,从而得到中间位置的索引。

8. 接下来,通过比较目标元素`target`与数组`arr2`中的`middle`位置的元素来确定下一步的查找方向。
   - 如果`target`等于`arr2[middle]`,则表示已经找到目标元素,程序会输出相应的消息并将`isFlag`设置为`true`,然后退出循环。
   - 如果`target`大于`arr2[middle]`,则说明目标元素位于当前查找范围的右半部分,因此将`head`更新为`middle + 1`,以缩小查找范围。
   - 如果`target`小于`arr2[middle]`,则说明目标元素位于当前查找范围的左半部分,因此将`end`更新为`middle - 1`,以缩小查找范围。

9. 如果循环结束后仍然没有找到目标元素(即`isFlag`仍然为`false`),则输出一条未找到的消息。

总之,这段代码实现了二分查找算法,用于在有序整数数组中查找特定目标元素。如果找到了目标元素,它会输出目标元素的位置,否则会输出未找到的消息。这种算法的时间复杂度是O(log n),其中n是数组的大小,因为它在每次迭代中将查找范围减半。

运行结果:

第十二题: 数组的最大子序列和

第十三题:扑克牌

第十四题;回形数

第十五题:正序、逆序遍历英文字母

第十六:判断单词是否是回文单词

第十七题:寻找锦鲤

 

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持Java的任何平台上无需重新编译即可运行,这得益于其独特的跨平台性,通过Java虚拟机(JVM)实现不同操作系统上的兼容。 Java的特点包括: 面向对象:Java全面支持面向对象的特性,如封装、继承和多态,使得代码更易于维护和扩展。 安全:Java提供了丰富的安全特性,如禁止指针运算、自动内存管理和异常处理机制,以减少程序错误和恶意攻击的可能性。 可移植性:Java字节码可以在所有安装了JVM的设备上执行,从服务器到嵌入式系统,再到移动设备和桌面应用。 健壮性与高性能:Java通过垃圾回收机制确保内存的有效管理,同时也能通过JIT编译器优化来提升运行时性能。 标准库丰富:Java拥有庞大的类库,如Java SE(Java Standard Edition)包含基础API,用于开发通用应用程序;Java EE(Java Enterprise Edition)提供企业级服务,如Web服务、EJB等;而Java ME(Java Micro Edition)则针对小型设备和嵌入式系统。 社区活跃:Java有着全球范围内庞大的开发者社区和开源项目,持续推动技术进步和创新。 多线程支持:Java内建对多线程编程的支持,使并发编程变得更加简单直接。 动态性:Java可以通过反射、注解等机制实现在运行时动态加载类和修改行为,增加了程序的灵活性。 综上所述,Java凭借其强大的特性和广泛的适用范围,在企业级应用、互联网服务、移动开发等领域均扮演着举足轻重的角色,是现代软件开发不可或缺的重要工具之一。
Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems公司于1995年5月正式发布。它的设计目标是“一次编写,到处运行(Write Once, Run Anywhere)”,这意味着开发者可以使用Java编写应用程序,并在支持Java的任何平台上无需重新编译即可运行,这得益于其独特的跨平台性,通过Java虚拟机(JVM)实现不同操作系统上的兼容。 Java的特点包括: 面向对象:Java全面支持面向对象的特性,如封装、继承和多态,使得代码更易于维护和扩展。 安全:Java提供了丰富的安全特性,如禁止指针运算、自动内存管理和异常处理机制,以减少程序错误和恶意攻击的可能性。 可移植性:Java字节码可以在所有安装了JVM的设备上执行,从服务器到嵌入式系统,再到移动设备和桌面应用。 健壮性与高性能:Java通过垃圾回收机制确保内存的有效管理,同时也能通过JIT编译器优化来提升运行时性能。 标准库丰富:Java拥有庞大的类库,如Java SE(Java Standard Edition)包含基础API,用于开发通用应用程序;Java EE(Java Enterprise Edition)提供企业级服务,如Web服务、EJB等;而Java ME(Java Micro Edition)则针对小型设备和嵌入式系统。 社区活跃:Java有着全球范围内庞大的开发者社区和开源项目,持续推动技术进步和创新。 多线程支持:Java内建对多线程编程的支持,使并发编程变得更加简单直接。 动态性:Java可以通过反射、注解等机制实现在运行时动态加载类和修改行为,增加了程序的灵活性。 综上所述,Java凭借其强大的特性和广泛的适用范围,在企业级应用、互联网服务、移动开发等领域均扮演着举足轻重的角色,是现代软件开发不可或缺的重要工具之一。
算法数据结构涵盖了以下主要内容: 数据结构(Data Structures): 逻辑结构:描述数据元素之间的逻辑关系,如线性结构(如数组、链表)、树形结构(如二叉树、堆、B树)、图结构(有向图、无向图等)以及集合和队列等抽象数据类型。 存储结构(物理结构):描述数据在计算机中如何具体存储。例如,数组的连续存储,链表的动态分配节点,树和图的邻接矩阵或邻接表表示等。 基本操作:针对每种数据结构,定义了一系列基本的操作,包括但不限于插入、删除、查找、更新、遍历等,并分析这些操作的时间复杂度和空间复杂度。 算法算法设计:研究如何将解决问的步骤形式化为一系列指令,使得计算机可以执行以求解问算法特性:包括输入、输出、有穷性、确定性和可行性。即一个有效的算法必须能在有限步骤内结束,并且对于给定的输入产生唯一的确定输出。 算法分类:排序算法(如冒泡排序、快速排序、归并排序),查找算法(如顺序查找、二分查找、哈希查找),图论算法(如Dijkstra最短路径算法、Floyd-Warshall算法、Prim最小生成树算法),动态规划,贪心算法,回溯法,分支限界法等。 算法分析:通过数学方法分析算法的时间复杂度(运行时间随数据规模增长的速度)和空间复杂度(所需内存大小)来评估其效率。 学习算法数据结构不仅有助于理解程序的内部工作原理,更能帮助开发人员编写出高效、稳定和易于维护的软件系统。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值