算法进阶-动态规划

经典例题

在这里插入图片描述
大家肯定想用递归做
思路大概就是这样
递归到最后一行就是对应的D(i,j)
然后往上推

在这里插入图片描述
但是这样会超时,因为存在大量的重复计算
比如调用第一行MasSum(7)需要调用MaxSum(3)和MaxSum(8)
但是调用第二行MaxSum(3)还要调用3行的MaxSum(8)和3行的MaxSum(1)
第二行的MaxSum(8)也会调用第三行的MaxSum(1)
是不是第三行的MaxSum(1)就调用了两次
这就重复了
随着数据量增多,重复也会增多
在这里插入图片描述

改进前代码

import java.util.Scanner;


public class Main {

public static void main(String[] args) {

	Scanner sc = new Scanner(System.in);
	int n = sc.nextInt();
	int a[][]=new int[n][n];
	int b[][]=new int[n][n];
	for (int i = 0; i < b.length; i++) {
		for (int j = 0; j <=i; j++) {
			a[i][j]=sc.nextInt();
		}
	}
	System.out.println(Max(a, b, 0, 0));

}
public static int Max(int [][]a,int [][]b,int x,int y) {
	
	if(x==a.length-1)
		return a[x][y];
	else 
	return Math.max(Max(a, b, x+1, y), Max(a, b, x+1, y+1))+a[x][y];
}
}

改进

在这里插入图片描述
算出来的数存起来,再调用直接取就行,避免重复计算
程序代码
在这里插入图片描述
so:在算法中避免重复计算来提高算法效率就是动态规划

改进后代码

import java.util.Scanner;


public class Main {

public static void main(String[] args) {

	Scanner sc = new Scanner(System.in);
	int n = sc.nextInt();
	int a[][]=new int[n][n];
	int b[][]=new int[n][n];
	for (int i = 0; i < b.length; i++) {
		for (int j = 0; j <=i; j++) {
			a[i][j]=sc.nextInt();
		}
	}
	System.out.println(Max(a, b, 0, 0));

}
public static int Max(int [][]a,int [][]b,int x,int y) {
	if(b[x][y]!=0) {
		return b[x][y];//如果有对应的就不用算了,直接返回
	}
	
	if(x==a.length-1)
		b[x][y]=a[x][y];//就是把所有得到的结果不是直接返回了,先存起来
	else {
	b[x][y]=Math.max(Max(a, b, x+1, y), Max(a, b, x+1, y+1))+a[x][y];//这个也是赋值
	}
	return b[x][y];
}
}
  

递推解法

其实一般能用递归的也可以用循环
可能循环比较多
也可能是循环比较难推
这个就需要我们从下面往上推所以
你从上往下推不出来
在这里插入图片描述
递推解法
从最底层开始递推

i=a.length-2到0
j从0到i
一个个推可以用循环来
a[i][j]=Math.max(a[i][j]+a[i+1][j],a[i][j]+a[i+1][j+1])
最后的a[0][0]就是得数

一般思路

先讲答案枚举一些(或全部)
画出一个二叉树-尝试写一个递归函数来求解
如果发现有大量的重复计算
可以用动态规划-可以用数组或者哈希表进行存储
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

最终可以找规律写成迭代形式(循环)
(或者说把return的储存在一个数据结构中需要的时候取出来)

适用题型

在这里插入图片描述

上升序列

题目
题目描述
一个数的序列bi,当b1<b2<...<bS的时候,我们称这个序列是上升的。对于给定的一个序列(a1,a2,...,aN),我们可以得到一些上升的子序列(ai1,ai2,...,aiK),这里1≤i1<i2<...<iK≤N。比如,对于序列(1,7,3,5,9,4,8),有它的一些上升子序列,如(1,7),(3,4,8)等等。这些子序列中最长的长度是4,比如子序列(1,3,5,8)。
你的任务,就是对于给定的序列,求出最长上升子序列的长度。

输入
输入的第一行是序列的长度N(1≤N≤1000)。第二行给出序列中的N个整数,这些整数的取值范围都在010000。
输出
最长上升子序列的长度。
样例输入
7
1 7 3 5 9 4 8
样例输出
4

更改前代码

import java.util.ArrayList;
import java.util.Scanner;

@SuppressWarnings("all")
public class Main {

public static void main(String[] args) {

	Scanner sc = new Scanner(System.in);
	int n = sc.nextInt();
	int []a =new int[n];
	int []b =new int[n];
	for (int i = 0; i < a.length; i++) {
		a[i]=sc.nextInt();
	}
	for (int i = 0; i < b.length; i++) {
		b[i]=1;
	}
	ArrayList<Integer> arrayList = new ArrayList<Integer>();
	for (int i = 0; i < b.length; i++) {
		arrayList.add(l(a, i));
	}
	
	arrayList.sort(new Comparator<Integer>() {

		@Override
		public int compare(Integer o1, Integer o2) {
			// TODO Auto-generated method stub
			return o2-o1;
		}
	});
	System.out.println(arrayList.get(0));
}
public static int l(int []a,int i) {
	int Max=1;
	for (int j = i+1; j < a.length; j++) {
		if(a[j]>a[i])
			Max=Math.max(l(a,j)+1, Max);
		
	}
	return Max;
	
	
}
}

更改后的代码

import java.util.ArrayList;
import java.util.Comparator;
import java.util.Scanner;

@SuppressWarnings("all")
public class Main {

public static void main(String[] args) {

	Scanner sc = new Scanner(System.in);
	int n = sc.nextInt();
	int []a =new int[n];
	int []b =new int[n];
	for (int i = 0; i < a.length; i++) {
		a[i]=sc.nextInt();
	}
	for (int i = 0; i < b.length; i++) {
		b[i]=-1;
	}
	ArrayList<Integer> arrayList = new ArrayList<Integer>();
	for (int i = 0; i < b.length; i++) {
		arrayList.add(l(a, i, b));
	}
	
	arrayList.sort(new Comparator<Integer>() {

		@Override
		public int compare(Integer o1, Integer o2) {
			// TODO Auto-generated method stub
			return o2-o1;
		}
	});
	System.out.println(arrayList.get(0));
}
public static int l(int []a,int i,int b[]) {//加一个参数b[i]存储Max
	if(b[i]!=-1)//刚开始就判断,如果有就不要重复计算直接返回
		return b[i];
	int Max=1;
	for (int j = i+1; j < a.length; j++) {
		if(a[j]>a[i])
			Max=Math.max(l(a,j,b)+1, Max);
		
	}
	b[i]=Max;
	return Max;
	
	
}
}
   

递推

在这里插入图片描述
这个也算从末位来递推可以找规律
只要是不从头的递推基本上都可以从尾部递推
代码差不多是这样
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: comparator是Java中的一个接口,用于比较两个对象的大小。它可以用于对集合中的元素进行排序,也可以用于自定义排序规则。实现comparator接口需要重写compare方法,该方法返回一个整数值,表示两个对象的大小关系。如果返回负数,则表示第一个对象小于第二个对象;如果返回正数,则表示第一个对象大于第二个对象;如果返回,则表示两个对象相等。comparator接口可以与Java中的排序算法一起使用,例如Collections.sort()方法。 ### 回答2: jmu-java-04面向对象进阶--02-接口-comparator讲述了Java中的接口以及比较器的使用。接口是一种约束,它规定了某个类必须要实现哪些方法,但不需要具体的实现方式。比较器则是一种接口,它规定了两个对象之间的排序方式。 在Java中,接口的定义方式为interface,其中的方法默认为public abstract形式。定义接口时,需要注意接口只能继承接口,并且可以有常量,但不能有成员变量。另外,接口中所有的方法都没有方法体,必须由实现它的类去具体实现。举例来说,如果我们定义一个接口Animal,可以定义一个方法move(),而实现这个接口的类必须实现move()方法,并且可以自由决定具体的实现方式,如Dog类可以实现为跑步,Bird类可以实现为飞行。 在讨论了接口的使用之后,jmu-java-04面向对象进阶--02-接口-comparator着重介绍了比较器的使用。比较器类似于一个工具箱,可以定义多种比较方式供其他类使用。比较器的核心类是Comparator,其定义的方法为compare(),用于比较两个对象并返回结果(0、1或-1)。比较器可以用于对对象进行排序或查找指定的对象。 在使用比较器时,需要实现Comparator接口,并覆盖compare()方法。比如,我们可以定义一个Person类,并在其中实现Comparator接口,然后在compare()方法中指定按照年龄从小到大排序。当我们使用Collections.sort()对Person列表进行排序时,就会按照我们定义的比较方式进行排序。 总的来说,jmu-java-04面向对象进阶--02-接口-comparator讲述了Java中的接口和比较器的使用,这是Java中优秀的编程方式之一,也是开发者必备的基本知识。掌握了接口和比较器的使用,我们就可以更好地实现面向对象编程,并对Java中的集合框架有更深刻的理解。 ### 回答3: Comparator是Java中一个非常重要的接口,它主要用于定义对象之间的比较规则。在Java中,比较规则是由比较器来实现的。比较器可以用于排序、查找和其他需要比较的场景。 Comparator接口有一个方法compare(Object o1, Object o2),用于比较两个对象的大小。如果o1大于o2,则该方法返回一个正整数;如果o1小于o2,则该方法返回一个负整数;如果o1等于o2,则该方法返回0。 我们可以使用Comparator接口来实现自定义的比较规则。比如,我们可以定义一个Student类,包含姓名和年龄两个属性,然后实现一个比较器,按照年龄从小到大的顺序对Student对象进行排序。 可以通过使用Collections.sort()方法对Student对象进行排序,提供一个实现Comparator接口的比较器作为参数进行排序。 实现一个比较器还可以实现多种排序方式。例如,按照姓名从小到大排序,实现如下: ``` public class NameComparator implements Comparator<Student> { public int compare(Student s1, Student s2) { return s1.getName().compareTo(s2.getName()); } } ``` 在使用时,我们可以将NameComparator对象作为参数传递给sort()方法,进行姓名排序。 Comparator接口的使用不仅仅局限于对象的比较排序,还可以用于其他需要比较的场景,比如查找、筛选等。例如,我们可以按照年龄筛选出年龄大于20岁的Student对象,并将它们存储在一个新的List中,实现如下: ``` List<Student> ageGreaterThan20 = students.stream() .filter(s -> s.getAge() > 20) .sorted(new AgeComparator()) .collect(Collectors.toList()); ``` 以上的代码使用了Java 8的新特性,使用流将年龄大于20岁的Student对象筛选出来,并按照年龄进行排序,最后存储在一个新的List中。 总之,Comparator是一个非常重要的接口,在Java中有着广泛的应用。掌握Comparator的使用可以帮助我们快速地实现对象比较、排序、筛选等操作,提高我们的编程效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小袁拒绝摆烂

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值