leetcode笔记之[1646. 获取生成数组中的最大值]

75 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第15天,点击查看活动详情

一、题目描述:

1646. 获取生成数组中的最大值 - 力扣(LeetCode)

给你一个整数 n 。按下述规则生成一个长度为 n + 1 的数组 nums :

  • nums[0] = 0
  • nums[1] = 1
  • 当 2 <= 2 * i <= n 时,nums[2 * i] = nums[i]
  • 当 2 <= 2 * i + 1 <= n 时,nums[2 * i + 1] = nums[i] + nums[i + 1] 返回生成数组 nums 中的 最大 值。

 

示例 1:

输入:n = 7
输出:3
解释:根据规则:
  nums[0] = 0
  nums[1] = 1
  nums[(1 * 2) = 2] = nums[1] = 1
  nums[(1 * 2) + 1 = 3] = nums[1] + nums[2] = 1 + 1 = 2
  nums[(2 * 2) = 4] = nums[2] = 1
  nums[(2 * 2) + 1 = 5] = nums[2] + nums[3] = 1 + 2 = 3
  nums[(3 * 2) = 6] = nums[3] = 2
  nums[(3 * 2) + 1 = 7] = nums[3] + nums[4] = 2 + 1 = 3
因此,nums = [0,1,1,2,1,3,2,3],最大值 3

示例 2:

输入:n = 2
输出:1
解释:根据规则,nums[0]、nums[1] 和 nums[2] 之中的最大值是 1

示例 3:

输入:n = 3
输出:2
解释:根据规则,nums[0]、nums[1]、nums[2] 和 nums[3] 之中的最大值是 2

提示:

  • 0 <= n <= 100

二、思路分析:

易知结论 : 最大值一定出在奇数位。但不一定出在最后一个奇数位

例如 n = 15时,最大值在 11 的位置(为5),而不是在 15 的位置(为4)

我们不需要把每个位置都计算出来,只需要 计算我们需要用到的位置 即可。

所以采用递归的方式,从结论开始往前推,计算每一个用到的位置。 做一点点预处理的步骤,如果n为偶数,直接 n-- ,让他变成一个奇数。

算法如下:

  • 如果 n 为偶, return dp[n/2]
  • 如果 n 为奇, return dp[n/2]+dp[n/2+1]
  • 递归终止条件,n==1 时 return 1, n==2 时 return 1
  • 采用一个ans数组来记忆化存储已经计算过的值,避免重复计算。

三、AC 代码:

class Solution {
    int[] ans;      //记忆化数组
    public int getMaximumGenerated(int n) {
        if(n==0) return 0;
        ans = new int[n+1];
        if(n%2==0) n--;
        //求取最大值
        int max = 0;
        for(int i=n;i>n/2;i-=2) {
        	max = Math.max(max, dp(i));
        }
        return max;
    }
    int dp(int n){
        if(n==1) return 1;
        if(n==2) return 1;
        //为偶数的情况
        if(n%2==0){
            //若已经计算过直接返回
            if(ans[n]!=0) return ans[n];
            //未计算过就递归计算一次,并将中间结果存入记忆化数组
            else{
                int temp = dp(n/2);
                ans[n] = temp;
            }
        }
        //为奇数的情况
        if(ans[n]!=0){
            return ans[n];
        }else{
                int a = dp(n/2);
                int b = dp(n/2+1);
                //中间结果存储。
                ans[n/2] = a;
                ans[n/2+1] = b;
                ans[n] = a+b;
                return ans[n];
            }
    }
}