【问题标题】:Find largest continuous interval such that all number between starting and ending are greater than starting and less than ending找到最大的连续间隔,使得开始和结束之间的所有数字都大于开始并且小于结束
【发布时间】:2021-01-08 05:25:38
【问题描述】:

你已经给出了整数数组

例如 5,3,4,3,9,4,4,6,8,6,5,7

你必须找到最大的区间 (i,j),使得 i 和 j 之间的所有数字都大于等于 i 处的数字但小于等于 j 处的数字。数字不需要按排序顺序。 i 处的数字也应小于 j 处的数字。

在上面的例子中有两个这样的间隔 3,4,3,9 和 4,4,6,8

在 3,4,3,9 - 中间两个数字 (4,3) 大于等于起始数字 (3) 但小于等于结束数字 (9) 。起始编号 (3) 也小于结束编号 (9)。

在 4,4,6,8 中 - 中间两个数字 (4,6) 大于等于起始数字 (4) 但小于等于结束数字 (8)。起始编号(4)也小于结束编号(8)。

解决这个问题的一种方法是检查所有大小为 n 的区间,然后是大小 n-1 ,依此类推,直到我们得到这样的区间。但我希望通过划分或征服/DP/或其他一些方法来实现高效的算法

【问题讨论】:

  • 对不起,3不大于3,等于它。与 4 和 4 相同。
  • 请说明确切要求。因为,根据你的例子,“大于”也可以是“等于”,也许 A[i] 也可以“等于”A[j]?
  • 输入[2, 2, 2, 2, 2]的解决方法是什么?
  • 非常感谢。是的,它可以大于等于和小于等于。上述输入的答案应该是 2,2,2,2,2

标签: algorithm


【解决方案1】:

我们可以在O(n log n) 中解决这个问题,将每个元素视为区间中潜在的最左侧元素。对于每个这样的候选者,(1)找到右边的第一个元素低于它 - 这是可能间隔的右侧边界,因为包含这样的元素会使约束无效; (2) 找到区间中最大元素的最左边实例(如果允许A[j] 等于其左边的元素,则找到最右边的实例) - 这是区间可以在不使约束无效的情况下扩展的最右边。

我们可以使用堆栈将所有元素的 (1) 答案存储在 O(n) 中。我们可以为 range-maximum-query 预处理一个结构,该结构将在O(log n) 时间回答 (2) 的第一部分。一旦找到区间的最大值,如果我们在数组中有其实例的有序列表(我们可以在O(n) 中使用哈希表对其进行预处理),我们可以在区间中找到它最右边或最左边的出现O(log n)时间。

【讨论】:

    【解决方案2】:

    DP的简单回答,希望对你有所帮助:

    public class Test {
    
        public static void main(String[] args){
    
            int[] input = {5,3,4,3,9,4,4,6,8,6,5,7};
    
            //
            // lenDp array to store the max possible interval sizes starting at every index.
            //
            int[] lenDp = new int[input.length];
            //
            // minNumIdxs array to store the indexes of minimum numbers in all sub arrays with the same length
            //
            int[] minNumIdxs = new int[input.length];
    
            //
            // for a start, every number is an interval with size of 1,
            // and there are as many sub arrays with length of 1 as input.length,
            // the minimum number in a sub array is the first number:
            //
            for(int i = 0; i < input.length; i++){
                lenDp[i] = 1;
                minNumIdxs[i] = i;
            }
    
            int maxLen = 1;
    
            //
            // check all possible intervals of size from 2 to input.length
            //
            for(int len = 2; len <= input.length; len++){
                //
                // for every possible interval with size of `len`, the starting index can be in range of [0, input.length - len]
                //
                for(int i = 0, end = input.length - len; i <= end ; i++ ){
    
                    //
                    // assume the interval of size `len` is possible for index i,then the number at input[i] has to be the minimum number,
                    // and the number at input[i + len - 1] has to be greater than or equal to
                    // the largest number ( at input[i + dp[i] - 1] ) of the current interval starting at index i.
                    // in the corner case where dp[i] == 1 and len > 2, it wouldn't be valid, for example:
                    // when len = 5, i = 0, dp[i] = dp[0] = 1, then input[i + len - 1] = input[0 + 5 - 1] = input[4] = 9;
                    // 9 is greater than 5 (input[0]), but it's invalid.
                    // So we also need to check (len == 2 || dp[i] > 1)
                    //
                    if(minNumIdxs[i] == i && input[i + len - 1] >= input[i + lenDp[i] - 1] &&
                            (len == 2 || lenDp[i] > 1)){
                        lenDp[i] = len;
                        maxLen = len;
                    }
    
                    //
                    // update the index of the minimum number in the sub array starting at i
                    //
                    if(input[i + len - 1] < input[minNumIdxs[i]])minNumIdxs[i] = i + len - 1;
                }
            }
    
    
    
            //
            // print out the final result
            //
            for(int i = 0 ; i < lenDp.length ; i++){
                if(lenDp[i] == maxLen){
                    System.out.println(Arrays.toString(Arrays.copyOfRange(input, i, i + maxLen)));
                }
            }
    
        }
    
    }
    

    输出:

     [3, 4, 3, 9]
     [4, 4, 6, 8]
    

    【讨论】:

    • 我是否正确理解这个解决方案的复杂性是O(n^2)
    猜你喜欢
    • 2020-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多