动态规划
剑指offer
7. 斐波那契数列
public class Solution {
public int Fibonacci(int n) {
if(n == 0){
return 0;
}
if(n==1){
return 1;
}
int[] dp = new int[n+1];
dp[0] = 0;
dp[1] = 1;
for (int k=2; k<=n; k++){
dp[k] = dp[k-1]+dp[k-2];
}
return dp[n];
}
}
8. 跳台阶
public class Solution {
public int JumpFloor(int target) {
if(target == 0){
return 0;
}
if(target == 1){
return 1;
}
//定义状态:dp[i] 为跳上第i阶阶梯的调法
int[] dp = new int[target+1];
dp[1] = 1;
dp[2] = 2;
for(int k = 3; k<=target; k++){
dp[k] = dp[k-1] + dp[k-2];
}
return dp[target];
}
}
9.变态跳台阶
public class Solution {
public int JumpFloorII(int target) {
if(target == 0){
return 0;
}
if(target == 1){
return 1;
}
//确定状态,dp[i] 表示跳到第i阶台阶的跳发
int[] dp = new int[target+1];
dp[1] = 1;
dp[2] = 2;
for(int k=3; k<=target; k++){
dp[k] = 1; //直接跳到第k阶台阶,属于一种跳发
for(int n=1; n<k; n++){
dp[k] = dp[k]+dp[n];
}
}
return dp[target];
}
}
10.矩形覆盖
public class Solution {
public int RectCover(int target) {
if(target == 0){
return 0;
}
if(target == 1){
return 1;
}
int[] dp = new int[target+1];
dp[1] = 1;
dp[2] = 2;
for(int k=3; k<=target; k++){
dp[k] = dp[k-1] + dp[k-2];
}
return dp[target];
}
}
30.连续子数组的最大和
public class Solution {
public int FindGreatestSumOfSubArray(int[] array) {
if(array.length == 0){
return 0;
}
int[] dp = new int[array.length];
dp[0] = array[0];
int max = array[0];
for(int k=1; k<array.length; k++){
dp[k] = Math.max(array[k], dp[k-1]+array[k]);
max = Math.max(max, dp[k]);
}
return max;
}
}
33.丑数
思路:
丑数 N = k2 * 2 + k3 * 3 + k5 * 5 (k2, k3 , k5 个数不定)
public class Solution {
public int GetUglyNumber_Solution(int index) {
if(index == 0){
return 0;
}
int[] dp = new int[index+1];
dp[1] = 1; // dp[k]表示从小到大的第k个丑数
int k2 = 1, k3 = 1, k5 = 1; // 丑数 N = k2 *2 + k3 * 3 + k5 *5
for(int k=2; k<=index; k++){
dp[k] = Math.min(dp[k2]*2, Math.min(dp[k3]*3, dp[k5]*5));
if(dp[k] == dp[k2]*2){
k2++;
}
if(dp[k] == dp[k3]*3){
k3++;
}
if(dp[k] == dp[k5]*5){
k5++;
}
}
return dp[index];
}
}
67. 剪绳子
public class Solution {
public int cutRope(int target) {
int[] dp = new int[target+1];
dp[1] = 1;
// i*(k-i) 表示把k分成两个数,
// i*dp[k-i]把k至少分成三个数,因为dp[k-i]的结果是把k-i至少分成了两个数
for(int k=2; k<=target; k++){
for(int i=1; i<k; i++){
dp[k] = Math.max(dp[k], Math.max(i*(k-i), i*dp[k-i]));
}
}
return dp[target];
}
}
leetcode
53.最大子序和
class Solution {
//动态规划
public int maxSubArray(int[] nums) {
int n = nums.length;
if(n==0){
return 0;
}
//定义状态,dp[i]表示以第i个元素为结尾的连续子序列的最大和
int[] dp = new int[n];
//状态初始化
dp[0] = nums[0];
int max = nums[0];
//以第k个元素结尾的连续子序列的最大和要么是第k个元素本身,要么是第k个元素与以第k-1个元素结尾的子序列和的和
//状态转移方程:dp[k] = Math.max(nums[k], nums[k]+dp[k-1]);
for(int k=1; k<n; k++){
dp[k] = Math.max(nums[k], nums[k]+dp[k-1]);
max = Math.max(dp[k], max);
}
return max;
}
}
121.买卖股票的最佳时机
class Solution {
public int maxProfit(int[] prices) {
int n = prices.length;
if(n == 0){
return 0;
}
//定义状态,dp[k]表示第k天可以获得的最大利润
int[] dp = new int[n];
dp[0] = 0;
int min = prices[0]; //记录前k-1天中,股票的最低价
int max = dp[0]; //记录k天中可获得的最大利润
//状态转移方程:第k天可以获得的最大利润 = max(第k-1天可以获得的最大利润, 第k天价格 -前k-1天中价格最小值)
for(int k=1; k<n; k++){
dp[k] = Math.max(dp[k-1], prices[k]-min);
min = Math.min(min, prices[k]);
max = Math.max(max, dp[k]);
}
return max;
}
}
343.整数拆分
class Solution {
public int integerBreak(int n) {
//确定状态:dp[k] 表示拆分正整数k后可获得的最大积 k>=2
int[] dp = new int[n+1];
dp[1] = 1;
dp[2] = 1; //2=1+1; 1*1=1
//状态转移方程:dp[k] = max( i*(k-i), i*dp[k-i] ) , 其中 1<=i<k
for(int k=3; k<=n; k++){
dp[k] = 0;
for(int i=1; i<k; i++){
int temp = Math.max(i*(k-i), i*dp[k-i]);
dp[k] = Math.max(temp, dp[k]);
}
}
return dp[n];
}
}
198.打家劫舍
class Solution {
public int rob(int[] nums) {
int n = nums.length;
if(n == 0){
return 0;
}
//定义状态,dp[k] 为考虑盗取第[0,k]号房子所取得的最大收益
int[] dp = new int[n];
dp[0] = nums[0];
//状态转移方程,求解dp[k], dp[k] = max( nums[k]+dp[k-2], nums[k-1]+dp[k-3]... )
for(int k=1; k<n; k++){
dp[k] = 0;
for(int i = k; i>=0; i--){
dp[k] = Math.max((nums[i]+(i>=2 ? dp[i-2]:0)), dp[k]);
}
}
return dp[n-1];
}
}
链表
剑指offer
3.从尾到头打印链表
/**
* public class ListNode {
* int val;
* ListNode next = null;
*
* ListNode(int val) {
* this.val = val;
* }
* }
*
*/
import java.util.*;
public class Solution {
public ArrayList<Integer> printListFromTailToHead(ListNode listNode) {
ArrayList<Integer> res = new ArrayList<>();
if (listNode == null){
return res;
}
Stack<Integer> stack = new Stack<>();
while(listNode != null){
stack.push(listNode.val);
listNode = listNode.next;