数组
三种数组定义的方式
int[] array = {1,2,3,4,5,6};
int[] array2 = new int[3];
int[] array3 = new int[]{1,2,3,4,5,6};
第一种:
int[] array = {1,2,3,4,5,6};定义一个数组且初始化
虽然没写new,但实际上也是一个对象
注:
int[10] array = {1,2,3,4,5,6};写法错误,int[] 属于类型,中括号里面不能加任何的数字,相当于在这里破坏了它的类型。
第二种:
int[] array2 = new int[3];定义数组未初始化

第三种:
int[] array3 = new int[]{1,2,3,4,5,6};定义且初始化

数组的使用
求数组长度:array.length
访问数组元素:array[i] //i为该元素索引下标
越界访问数组元素array[-1]报错:ArrayIndexOutOfBoundsException:-1
更改数组元素:array[i] = n
数组赋值的三种方法
第一种
逐个赋值:可以通过索引来逐个给数组元素赋值。例如,对于一个整型数组arr,可以使用以下方式给数组元素赋值:
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
第二种
使用循环赋值:如果需要给数组中的多个元素赋相同的值或者根据某种规律赋值,可以使用循环结构来简化代码。例如,可以使用for循环来给整型数组arr赋值:
for (int i = 0; i < arr.length; i++) {
arr[i] = i + 1;
上述代码将数组元素赋值为索引值加1,即arr[0]赋值为1,arr[1]赋值为2,以此类推。
第三种
使用数组初始化器赋值:在声明数组时可以使用数组初始化器来给数组元素赋值。例如,可以使用以下方式给整型数组arr赋值:
int[] arr = {1, 2, 3};
上述代码将数组arr的元素分别赋值为1、2、3。
实例:
例题1:通过键盘输入n个数字,并保存到数组
import java.util.Arrays;
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
try(Scanner input = new Scanner(System.in)){
System.out.println("请输入数组长度:");
int n = input.nextInt();
System.out.println("请输入数:");
//创建数组
int[] numbers = new int[n];
//循环输入n个数字,并保存到数组numbers
for(int i = 0;i < n;i++) {
numbers[i] = input.nextInt();
System.out.println(Arrays.toString(numbers));
}
}
}
}
动态规划算法
通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划算法通过拆分问题,定义问题状态和状态之间的关系,使得问题能够以递推(或者说分治)的方式去解决。
动态规划对于子问题重叠的情况特别有效,因为它将子问题的解保存在表格中,当需要某个子问题的解时,直接取值即可,从而避免重复计算。
适用问题及求解步骤
适合用动态规划来解决的问题,都具有下面三个特点:最优化原理、无后效性、有重叠子问题。
(1)最优化原理:如果问题的最优解所包含的子问题的解也是最优的,就称该问题具有最优子结构,即满足最优化原理。
(2)无后效性:即某阶段状态一旦确定,就不受这个状态以后决策的影响。也就是说,某状态以后的过程不会影响以前的状态,只与当前状态有关。
(3)有重叠子问题:即子问题之间是不独立的,一个子问题在下一阶段决策中可能被多次使用到。该性质并不是动态规划适用的必要条件,但是如果没有这条性质,动态规划算法同其他算法相比就不具备优势。
求解步骤通常是:初始状态→│决策1│→│决策2│→…→│决策n│→结束状态。具体包括以下几步:
(1)划分:按照问题的特征,把问题分为若干阶段。注意:划分后的阶段一定是有序的或者可排序的。
(2)确定状态和状态变量:将问题发展到各个阶段时所处的各种不同的客观情况表现出来。状态的选择要满足无后续性。
(3)确定决策并写出状态转移方程:状态转移就是根据上一阶段的决策和状态来导出本阶段的状态。根据相邻两个阶段状态之间的联系来确定决策方法和状态转移方程。
(4)边界条件:状态转移方程是一个递推式,因此需要找到递推终止的条件。
实例:
例题1:
题目描述
使用动态规划算法求两个序列的最长公共子序列,需构造一条最长公共子序列。
输入
每组输入包括两行,每行包括一个字符串。
输出
两个字符序列的一条最长公共子序列。(输入已确保最长公共子序列的唯一性)
解
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
// 读取两个字符串
String a = sc.nextLine();
String b = sc.nextLine();
// 获取字符串长度
int m = a.length();
int n = b.length();
// 创建二维DP表
int[][] dp = new int[m + 1][n + 1];
// 填充DP表
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (a.charAt(i - 1) == b.charAt(j - 1)) {
// 如果字符相同,则长度+1
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
// 否则取两者中的较大值
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
// 从DP表回溯,构造最长公共子序列
StringBuilder lcs = new StringBuilder();
int i = m;
int j = n;
while (i > 0 && j > 0) {
if (a.charAt(i - 1) == b.charAt(j - 1)) {
// 如果字符相同,添加到结果中
lcs.append(a.charAt(i - 1));
i--;
j--;
} else if (dp[i - 1][j] > dp[i][j - 1]) {
// 选择dp[i-1][j]较大的值
i--;
} else {
// 选择dp[i][j-1]较大的值
j--;
}
}
// 反转lcs得到正确的顺序
lcs.reverse();
// 输出最长公共子序列
System.out.println(lcs.toString());
}
}
实例练习:
例题1:
题目描述
给定n个整数(可能是负数)组成的序列a[1], a[2], a[3], …, a[n],求该序列的子段和如a[i]+a[i+1]+…+a[j]的最大值。
输入
每组输入包括两行,第一行为序列长度n,第二行为序列。
输出
输出字段和的最大值。
解
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc = new Scanner(System.in);
//System.out.println("输入一个正整数:");
int n = sc.nextInt();
//System.out.println(n);
int[] a = new int [n];
Scanner in = new Scanner(System.in);
//System.out.println("输入n个整数:");
for(int i = 0;i < n;i++) {
a[i] = in.nextInt();
//System.out.println(a[i]);
}
if(n==1) {
System.out.println(a[0]);
}else {
int[] sum = new int [n];
sum[0] = a[0];
int maxSum = sum[0];
for(int i = 1;i < n;i++) {
sum[i] = Math.max(a[i], sum[i-1]+a[i]);
maxSum = Math.max(maxSum,sum[i]);
}
System.out.println (maxSum);
}
}
}
本文介绍了Java中数组的三种定义方式,包括初始化和不初始化,以及数组长度获取、元素访问和赋值的方法。随后探讨了动态规划算法的基本概念,以求解最长公共子序列和子段和问题为例,展示了动态规划的求解步骤。
持续更新ing&spm=1001.2101.3001.5002&articleId=137940714&d=1&t=3&u=e64bc5e571214471adf14f77cceb1a16)
13万+

被折叠的 条评论
为什么被折叠?



