【问题标题】:Find minimum sum from given array从给定数组中找到最小和
【发布时间】:2022-06-12 16:42:21
【问题描述】:

我有一个数字数组[3,4,5,1,2,3,1] 找到3 pairs 子序列说sub[] 这样sub[0] < sub[1] > sub[2],将这三个元素相加并得到最小和。

示例:

对于[3,4,5,1,2,3,1],我可以在这里选择[1,2,1] 1<2>1 所以总和是1+2+1 = 4,这是最小值。

约束:

数组大小最大为 1,00,000 每个元素大小为 1 到 1,00,00,00,000

我的方法是使用 3 个嵌套的 for 循环并获得最小总和,这不是一种有效的方法。

public long process(List<Integer> list) {
   int n = list.size();
   long output = Long.MAX_VALUE;
   for(int i=0; i<n; i++) {
      for(int j=i+1; j<n; j++) {
       if(list.get(i) < list.get(j)) {
          for(int k=j+1; k<n; k++) {
            if(list.get(j) > list.get(k)) {
               output = Math.min(output, list.get(i)+list.get(j)+list.get(k));
             }
          }
       }
      }
   }
   return output;
}

如何以更少的时间复杂度有效地解决这个程序?

【问题讨论】:

  • 使用前缀数组存储从左到当前索引的最小元素;类似地使用后缀数组来存储从右到当前索引的最小元素。然后对于每个索引,确定是否 prefix[index] suffix[index]。如果是这样,计算他们的sum。对所有索引执行此操作并返回最小值。
  • 使用滑动窗口协议

标签: java algorithm time-complexity


【解决方案1】:

让我提供一个时间复杂度为O(n),空间复杂度为O(n)的解决方案。您必须对数组进行三次迭代,并为最小元素存储两个数组。我受到@Someone 的评论的启发。请记住,此解决方案假设对于任何 sub[i] &lt; sub[j] &gt; sub[k],它必须成立:i &lt; j &lt; k

可以轻松修改解决方案以涵盖i &lt;= j &lt;= k 的情况。如果这个等式不是必须成立的,那么问题就变得更加微不足道了。只要找到前三个最小元素,我们就知道sub[i] &lt; sub[j] &gt; sub[k] 成立。确保第三个(最大的)与其他的不同。尽管您没有指定我上面提到的规则,但我相信问题希望您遵守该规则 - 否则这将是非常微不足道的。

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Stackoverflow {
    public static void main(String[] args) {
        ArrayList<Integer> numbers = new ArrayList<>(Arrays.asList(3,4,5,1,2,3,1));
        System.out.println(process(numbers));
    }
    
    public static long process(List<Integer> list) {
        if(list.size() < 3) return -1; // not enough elements
        
        int n = list.size();
        
        int[] minLeft = new int[n];
        int[] minRight = new int[n];
        
        minLeft[0] = list.get(0);
        minRight[minRight.length - 1] = list.get(list.size() - 1);
        
        // store the minimum elements from left up to current index
        for(int i=1; i<n; i++) {
            minLeft[i] = Math.min(list.get(i), minLeft[i - 1]);
        }
        
        
        // store the maximum elements from right up to current index
        for(int i=n - 2; i>=0; i--) {
            minRight[i] = Math.min(list.get(i), minRight[i+1]);
        }
        
        
        long sum = Integer.MAX_VALUE;
        
        for(int i=1; i<n-1; i++) {
            sum = Math.min(sum, minLeft[i - 1] + list.get(i) + minRight[i + 1]);
        }
        
        return sum;
    }
}

输出:

4

【讨论】:

    猜你喜欢
    • 2012-12-29
    • 2013-10-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多