描述

小红拿到了一个数组。她想取一些不相邻的数,使得取出来的数之和尽可能大。你能帮帮她吗?

思路

这道题是让求数组不相邻的最大和,大家想一想,对于第一个元素肯定本身就是最大和了;第二个元素的最大和是 第一个元素和第二个元素中最大的那个;第三个元素的最大和则是 (第三个元素 + 第一个元素) 和 第二个元素 最大值;第四个元素最大和则是 第四个元素 + 第二个元素所在位置的最大和) 和 第三个元素所在位置的最大和 最大值;

说到这里是不是就能看出来点东西,从第三个元素开始,每个位置最大和是:Math.max(当前元素 + 前第二个元素所在位置最大和, 前第一个元素所在位置最大和),第一个和第二个元素最大和的求法也在上面说过了,这个公式则是 动态规划的【状态转移方程】

AC 代码

import java.util.Scanner;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        // 输入长度
        long n = Long.parseLong(sc.nextLine());
        // 输入数组
        String[] arrStr = sc.nextLine().split(" ");
        long[] arr = new long[arrStr.length];
        for (int i = 0; i < arrStr.length; i++) {
            arr[i] = Long.parseLong(arrStr[i]);
        }

        long run = run(arr.length, arr);
        System.out.println(run);
    }

    public static long run(int n, long[] arr) {
        if (arr == null || arr.length < 1) {
            return -1;
        }
        if (arr.length == 1) {
            return arr[0];
        }
        if (arr.length == 2) {
            return Math.max(arr[0], arr[1]);
        }

        // 创建 dp 数组
        long[] dp = new long[n];
        dp[0] = arr[0];
        dp[1] = Math.max(arr[0], arr[1]);
        // 状态转移
        for (int i = 2; i < arr.length; i++) {
            long a = dp[i - 2] + arr[i];
            long b = dp[i - 1];
            dp[i] = Math.max(a, b);
        }
        return dp[n - 1];
    }
}
  • 时间复杂度:O(N), N 为数组长度,需要每个元素遍历一遍
  • 空间复杂度:O(N), N 为数组长度,创建 dp 数组