当前位置: 首页 > 知识库问答 >
问题:

给定约束的数组中的最大和

关玄裳
2023-03-14

给定一个正整数数组,返回最大和。

只有一个限制:如果你选择两个连续的元素,你不允许在你的总数中添加任何后续的元素,你的总和是到那个点为止的累积量。你的目标是最大化你的总和。

输入:[1,4,2,10]

产出:14

输入:[1,4,5,3]

产出:9

  public static int solution(int[] boxes) {
    if(boxes.length == 0) {
      return 0; 
    }
    int tempMax = 0;
    
    for(int i = 0; i < 2; i++) {
      tempMax += boxes[i];
    }
    
    int max = tempMax;
    
    for(int i = 1; i < boxes.length - 1; i++) {
      int sub = tempMax - boxes[i - 1];
      tempMax = sub + boxes[i + 1];
      
      if(max < tempMax) {
        max = tempMax;
      }
    }
    
    return max;
  }

我在第一个测试案例中一直失败。我尝试了DP解决方案,但产生了相同的结果?任何帮助都将不胜感激。

共有2个答案

翁宏茂
2023-03-14

因为在考虑是否向分数添加特定框时有三种不同的可能性,所以在探索所有分支时,我会使用递归来保持简单(加上从最后开始工作并记忆这些分数,以更好地处理大量输入):

import java.util.Arrays;
import java.util.Random;

public class Demo {

    /** 
     * Find the maximum possible score of the given boxes
     *
     * @param boxes The boxes
     * @param i the index of the current box we're considering adding
     * to the score.
     * @param score the current score without the current box
     * @param cache already computed maximum scores starting with the
     * Nth box, or -1 if not already found.
     * @return the maximum possible score
     */
    private static int solve(int[] boxes, int i, int score, int[] cache) {
        if (i >= boxes.length) {
            // No more boxes to consider
            return score;
        } else if (cache[i] > -1) {
            // The maximum score for the current box to the end has
            // already been calculated; re-use it.
            return score + cache[i];
        } else if (i == boxes.length - 1) {
            // Last box; go ahead and add it to the score and we're done.
            return score + boxes[i];
        } else {
            /* Now there are three options with at least one more box
             * after this one: */

            // Add the current box and the next box, and then stop
            // (Two consecutive boxes).
            int s1 = score + boxes[i] + boxes[i + 1];

            // Add the current box and skip a box to keep calculating
            // a score
            int s2 = solve(boxes, i + 2, score + boxes[i], cache);

            // Skip the current box and keep calculating
            int s3 = solve(boxes, i + 1, score, cache);
            
            // Now return the largest of the three
            return Math.max(s1, Math.max(s2, s3));
        }
    }
    
    private static int solve(int[] boxes) {
        int[] cache = new int[boxes.length];
        Arrays.fill(cache, -1);
        // Solve from the end - calculate the maximum score of the
        // last N boxes of the array. Then when calculating the score
        // for the N-1th box, that value can be re-used.
        cache[boxes.length - 1] = boxes[boxes.length - 1];
        for (int i = boxes.length - 2; i >= 0; i--) {
            cache[i] = solve(boxes, i, 0, cache);
        }
        return cache[0];
    }

    private static void show(int[] boxes) {
        System.out.println("Input: " + Arrays.toString(boxes));
        System.out.println("Output: " + solve(boxes));
    }

    /** Generate an array of random numbers for testing large inputs */
    private static void show(Random rng, int size) {
        show(rng.ints(1, 21).limit(size).toArray());
    }
    
    public static void main(String[] args) {
        Random rng = new Random();      
        show(new int[]{1, 4, 2, 10});
        show(new int[]{1, 4, 5, 3});
        show(rng, 1000);
    }
}
梁浩涆
2023-03-14

你贪婪的方法是正确的,但是我发现你目前的解决方案有一些问题。

首先,对于大小为1的输入,您的程序将崩溃,因为您的第一个循环将假设输入至少为2。

接下来,你没有办法参考之前做出的决定。在temMax中,基本上存储了box[i]box[i 1],因为每次迭代都要从temMax中删除box[i-1]

一种方法是为每次迭代存储三个值:

  • 如果我们选择当前框而不是前一个框的最大值(max0
  • 最大值,如果我们没有选择当前框,并且没有连续选择之前的迭代(max0
  • 最大值,如果我们选择当前框,而前一个框也被选中(max11

编辑:添加解决方案

import java.lang.Math;

public class Game {
    public static int solution(int[] boxes) {
        int max0 = 0, max1 = 0, max11 = 0;
        for(int i = 0; i < boxes.length; i++) {
            int max0_new = Math.max(max0, max1);
            int max1_new = max0 + boxes[i];
            int max11_new = Math.max(max11, max1 + boxes[i]);
            max0 = max0_new;
            max1 = max1_new;
            max11 = max11_new;
        }
        return Math.max(max0, Math.max(max1, max11));
    }

    public static void main(String[] args) {
        System.out.println(solution(new int[]{1, 4, 2, 10}));
        System.out.println(solution(new int[]{1, 4, 5, 3}));
    }
}
 类似资料:
  • 如果某些数组索引不能配对,我将如何找到唯一正整数数组的最大和? 例如,我们有一个数组:[8,2,1,3,9,4] 索引(0,4)和(4,5)处的元素彼此不喜欢。 在这种情况下,最大和为:8 2 1 3 4=18 假设这是100个条目的规模和多达一半的约束,您将如何处理这个问题? 是否有一个像图形这样的数据结构是有用的还是有一些DP?我主要关心的是高效的运行时。

  • 最近在一次工作面试中,我被要求在给定约束条件下求两个数组的最大和。这个问题措辞不同,但归结起来就是我上面所说的。没有提到元素是不同的,或者数组是被排序的。 例子: 请注意,由于约束,这与在2个数组中查找第k个最大和的对不同。 一个蛮力解是取2个数组的笛卡尔积,计算每对的和,过滤掉大于7000的,排序,取相等的顶值,时间复杂度为O(n2),我们能做的更好吗?

  • 你可以做两个动作中的一个: 1.从x=L到x=R做一个水平切割,将建筑物的高度从x=L到x=R降低1。 2.在x=P处作垂直切割,完全摧毁x=P处的建筑物,从而使其高度为零 1≤n≤1000 0≤hi≤1000 采样输入0 2 我想不出解决这个问题的方法。我的代码对以下输入不起作用:1 1 1 2 4 5 7 7 8 9**在我的代码中,我减少了所有元素的最小值。然后找出零点之间的子数组,然后比较

  • 这个问题有多项式解吗?如果有,你能呈现吗?

  • 我试图解决的问题如下:我想在给定的数组中找到一个最大的数字跨度,该数组由正整数和负整数组成,返回最大值(a[j]-a[I]),这样1 求数组的n阶统计量的索引,使其为“i” 这个算法是O(nlogn),但我不知道它是否正确。