一、求数组最大子数组和
子数组必须是连续的,数组中可能包含有:正整数,零,负整数三种中的一种或多种。
方法一:可以用普通的方法枚举所有的连续子数组,然后求出最大的子数组和,时间复杂度为O(n*n)。
方法二:动态规划!
方法一代码:
int MaxSubString(int[] A, int n)
{
int max = min; //初始值为负无穷大
int sum;
for(int i = 0; i < n; i++)
{
sum = 0;
for(int j = i; j < n; j++)
{
sum += A[j];
if(sum > max)
max = sum;
}
}
return max;
}
方法二代码:
import java.util.Scanner;
public class BigSubArraySum {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入n个整数");
int n = input.nextInt();
int[] arr = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = input.nextInt();
}
int max = arr[0];
int currentMax = arr[0];
for (int i = 1; i < arr.length; i++) {
//currentMax = (currentMax >= 0) ? arr[i] + currentMax : arr[i];
currentMax = Math.max(arr[i] + currentMax,arr[i]);
max = Math.max(max, currentMax);
}
System.out.println(max);
}
}
数组: {0, -2, 3, 5, -1, 2} 返回值为 9,因为连续子数组3+5-1+2=9>3+5=8;
二、硬币问题
(还是有问题,当货币中为2,3,4或者其他就会出现bug,待解决)
public class MinCoins {
public static void main(String[] args) {
int[] coins = {1,3,5}; //coins数组存放各个无重复面值
int value = 17; //value表示需要凑成的钱数
int[] jilu = new int[value]; //记录每一步的面值
int min = new MinCoins().solution(coins, value, jilu);
for (int i = value - 1; i >= 0;) {
System.out.print(jilu[i] + "->");
i = i - jilu[i];//倒序输出每一步用的哪种币
}
System.out.println();
System.out.println(min);
}
private int solution(int[] coins, int value, int[] jilu) {
int[] mins = new int[value + 1]; //数组mins表示凑成多少钱所需最小钱币数目,为了使索引能达到value,加1
mins[0] = 0; //凑成0元所需0个
for (int i = 1; i <= value; i++) //将数组中的数初始化为最大值
mins[i] = Integer.MAX_VALUE;
for (int i = 1; i <= value; i++) { //从凑1元钱开始,递增直至value
for (int j = 0; j < coins.length; j++) {//j表示第(j+1)种币
if (coins[j] <= i) {
//意思是比较所有种类的币是不是比所要凑的值小,
//如若比要凑得值还大就跳过比下一种币
mins[i] = Math.min(mins[i] , mins[i - coins[j]] + 1);
//将满足coins[j] <= i的coins[j]遍历一遍,则mins[i]存储的值就是几种情况中的最小值
jilu[i - 1] = coins[j];//记录每步所使用的币值
}
}
}
return mins[value];
}
}
三、背包问题
w[i] : 第i个物体的重量;
p[i] : 第i个物体的价值;
arr[i][m] : 前i个物体放入容量为m的背包的最大价值;
arr[i-1][m] : 前i-1个物体放入容量为m的背包的最大价值;
arr[i-1][m-w[i]] : 前i-1个物体放入容量为m-w[i]的背包的最大价值;
由此可得:
arr[i][m]=max{arr[i-1][m-w[i]]+p[i] , arr[i-1][m]}
public class BackPack {
public static void main(String[] args) {
int[] w = { 3, 4, 5 };//每个货物的重量
int[] p = { 4, 5, 6 };//每个货物的价值(与上面对应)
int m=10; //背包最大承重
int n=w.length;
int[][] arr=new int[n+1][m+1];//定义二维数组存储每种情况下背包里的物品价值
int i,j;
for(i=0;i<=n;i++){ //将前(i+1)个物品放入承重为0的包里价值为0
arr[i][0]=0;
}
for(j=0;j<=m;j++){ //将前0个物品放入承重为j的包里价值为0
arr[0][j]=0;
}
for(j=0;j<=m;j++){ //j表示背包承重(从0递增至m)
for(i=1;i<=n;i++){ //i表示第i个货物
if(j<w[i-1]){ //如果第i个货物的重量w[i-1]大于背包承重则舍弃这个货物
arr[i][j]=arr[i-1][j];
}else{ //如果第i个货物的重量w[i-1]小于背包承重则取两者之间最大值
arr[i][j]=Math.max(arr[i-1][j-w[i-1]]+p[i-1],arr[i-1][j]);
}//或许你会问为什么取最大,加入第i个肯定比不加大呀!你说的没错但是你必须考虑能不能加,至于能不能加交给它前面的去考虑,这也是动态规划的思想之一
}
}
System.out.println(arr[n][m]);
}
}
四、最长公共子序列
public class LCS {
public static void main(String[] args) {
String str1="ABCDABDC";
String str2="BBCDCADBCAD";
char[] ch1=str1.toCharArray();
char[] ch2=str2.toCharArray();
int m=ch1.length;
int n=ch2.length;
int[][] arr=new int[m+1][n+1];
int i,j;
for(i=0;i<=m;i++){
arr[i][0]=0;
}
for(j=0;j<=n;j++){
arr[0][j]=0;
}
for(i=1;i<=m;i++){
for(j=1;j<=n;j++){
if(ch1[i-1]==ch2[j-1]){
arr[i][j]=arr[i-1][j-1]+1;
}else{
arr[i][j]=Math.max(arr[i-1][j], arr[i][j-1]);
}
}
}
System.out.println(arr[m][n]);
}
}