【问题标题】:Count of strictly increasing sequence of integers严格递增的整数序列的计数
【发布时间】:2021-06-12 08:15:22
【问题描述】:

给定两个相同长度为 n 的整数 a 和 b 的列表,找出严格递增的整数序列的计数 I[0]

a = [6,3,4,4]
b = [1,5,1,6]
Four possible solutions are possible
[1 3 4 5],
[1 3 4 6],
[2 3 4 5],
[2 3 4 6].
The length of both arrays will not exceed 100. 
Each element is between 1 and 10000.```

Can someone provide a hint for this question? I am not able to figure out

【问题讨论】:

    标签: arrays algorithm computer-science


    【解决方案1】:

    您可以在此处使用动态编程方法。您的 DP 的状态将是当前索引和最后一个值,如 count_sequence(int index, int last_value),循环通过 min(a[index], b[index])max(a[index], b[index]),如果有一个值大于最后一个值,则转到具有当前值的下一个索引,如 count_sequence(index+1, current_value),如果你到达基本情况index>=n,这意味着你找到一个序列然后返回1。使用它,您可以找到所有可能的序列。

    通过记忆,复杂度将是 O(n*m),
    n = 数组大小m = 最大元素

    【讨论】:

      【解决方案2】:

      JavaScript/node.js 解决方案:

          const a = [6, 3, 4, 4]
          const b = [1, 5, 1, 6]
          const n = a.length
      
          let min = []
          let max = []
      
          for (let i = n - 1; i >= 0; i--) {
            let itemMin = (min[i] = Math.min(a[i], b[i]))
            let itemMax = (max[i] = Math.max(a[i], b[i]))
      
            if (i > 0) {
              const maxBefore = Math.max(a[i - 1], b[i - 1])
      
              // max of before index, >= current min
              if (maxBefore >= min[i]) {
                itemMin = Math.min(maxBefore + 1, max[i])
              }
            }
      
            if (i < n - 1) {
              const minAfter = min[i + 1]
      
              // min of after index, <= current or calculated min
              if (itemMin >= minAfter) {
                itemMin = Math.min(minAfter - 1, min[i])
              }
      
              // max correction
              itemMax = Math.min(max[i], minAfter - 1)
            }
      
            // Test is solution possible, if not do something
            if (itemMin < min[i] || itemMin > max[i]) {
              throw new Error('Impossible to solve...')
            }
            if (itemMax < min[i] || itemMax > max[i]) {
              throw new Error('Impossible to solve...')
            }
      
            // Set min and max values
            min[i] = itemMin
            max[i] = itemMax
          }
      
          // ***** Printing results
          function printResult(min, max, str = '', item = 0) {
            const n = min.length
      
            for (let j = min[item]; j <= max[item]; j++) {
              if (item < n - 1) {
                printResult(min, max, `${item !== 0 ? str : ''}${j},`, item + 1)
              } else {
                console.log(`[${str}${j}]`)
              }
            }
          }
      
          printResult(min, max)

      【讨论】:

        【解决方案3】:

        给定两个数组,一个保存min 值,另一个保存每个索引的max 值,您可以定义一个简单的递归函数来导出每个可能的递增序列,每个位置的起始值都是最大值当前min 值和之前选择的值加1。

        这里有一些 Java 代码来说明:

        static void incSeq(int[] min, int[] max, int[] res, int pos, int prev)
        {
            if(pos == min.length)
            {
                System.out.println("seq: " + Arrays.toString(res));
                return;
            }
            
            for(int j = Math.max(prev+1, min[pos]); j <= max[pos]; j++)
            {
                res[pos] = j;
                incSeq(min, max, res, pos+1, j);
            }
        }
        

        但是,如果我们考虑如下输入:

        min = {1,   1,   1,   1}
        max = {100, 100, 100, 5}
        

        我们可以看到,我们的函数将做很多无用的工作,遍历前三个位置的值,这些值不会是递增序列的一部分。

        我们可以通过认识到我们需要考虑的位置i 的最大值比位置i+1 的最大值小一来解决这个问题。如果我们从最后一个位置开始并使用此规则向后工作,我们可以将上面的 max 数组更新为:

        max = {2, 3, 4, 5}
        

        这意味着我们的递归函数的工作量会少很多。

        这是完整的代码:

        public static void main(String[] args)
        {
            int n = 4;
            int[] a = {6,3,4,4};
            int[] b = {1,5,1,6};
        
            int[] min = new int[n];
            int[] max = new int[n];
            
            System.out.println("a:   " + Arrays.toString(a));
            System.out.println("b:   " + Arrays.toString(b));
            
            for(int i=0; i<n; i++)
            {
                min[i] = Math.min(a[i], b[i]);
                max[i] = Math.max(a[i], b[i]);
            }
            
            System.out.println("min: " + Arrays.toString(min));
            System.out.println("max: " + Arrays.toString(max));
            
            // cap max values
            for(int i=n-1; i>0; i--)
            {
                max[i-1] = Math.min(max[i-1], max[i]-1);
            }
            
            System.out.println("max: " + Arrays.toString(max) + "\n");
            
            incSeq(min, max, new int[n], 0, 0);
        }
        
        static void incSeq(int[] min, int[] max, int[] res, int pos, int prev)
        {
            if(pos == min.length)
            {
                System.out.println("seq: " + Arrays.toString(res));
                return;
            }
            
            for(int j = Math.max(prev+1, min[pos]); j <= max[pos]; j++)
            {
                res[pos] = j;
                incSeq(min, max, res, pos+1, j);
            }
        }
        

        输出:

        a:   [6, 3, 4, 4]
        b:   [1, 5, 1, 6]
        min: [1, 3, 1, 4]
        max: [6, 5, 4, 6]
        max: [2, 3, 4, 6]
        
        seq: [1, 3, 4, 5]
        seq: [1, 3, 4, 6]
        seq: [2, 3, 4, 5]
        seq: [2, 3, 4, 6]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-12-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-04-01
          • 1970-01-01
          • 2021-05-29
          • 1970-01-01
          相关资源
          最近更新 更多