【问题标题】:Problem with Inversion Count Algorithm Implementation反转计数算法实现的问题
【发布时间】:2021-11-02 18:03:32
【问题描述】:

问题陈述

我正在尝试解决this 问题。

问题的简短摘要: 给定一个未排序的数组,求反转对的总数。 反转的定义: 如果 i arr[j]

,索引 i 和 j 形成一个有效的反转对

我的做法:

  1. 我试图用分而治之来解决这个问题。 我将数组分成两部分,并递归求解每一部分。
  2. 递归调用完成后,每一半都应该排序,并且应该返回反转计数的个数。
    当前数组的答案将是两半的答案之和 + 两半之间的反转对数。
    请参阅此图以更好地了解此步骤:

图片来源:geeks for geeks

  1. 为了找到交叉反转的数量,我循环了第一个数组,对于每个元素,我在后半部分进行了二进制搜索,以获得确切元素的位置或第一个更大元素的位置(@987654324 @)。

虽然这种方法对我来说似乎是正确的并且通过了很少的测试用例,但它对一些隐藏的测试用例给出了错误的答案。

我需要帮助了解我的算法或实现是否存在任何缺陷。

我的实现:

    static long inversionCount(long arr[], long N){
        return solve(0, (int)N-1, arr);
    }
    
    static long solve(int l, int r, long[] arr){
        if(l >= r) return 0;
        
        int mid = l+(r-l)/2;
        
        long countL = solve(l, mid, arr); //solve left half
        long countR = solve(mid+1, r, arr); //solve right half
        
        long countM = 0;
        
        //count crossing inversions
        for(int idx = l; idx <= mid; idx++){
            int position = Arrays.binarySearch(arr, mid+1, r+1, arr[idx]);
            if(position<0) position = -(position+1);
            
            countM += position-mid-1;
        }
        
        Arrays.sort(arr, l, r);
        
        return countM+countL+countR;
    }

【问题讨论】:

    标签: java arrays algorithm binary-search divide-and-conquer


    【解决方案1】:

    我需要帮助了解我的算法或实现是否存在任何缺陷。

    您的实施中至少存在两个缺陷。这是一个测试应用程序,可帮助您找到失败的测试用例。

    public class InversionCountTest {
      /**
       * Fixed array length to be used for the test cases.
       *
       * <p>A failing test case with a short array is simpler to understand than a
       * failing test case with a long array, so check small array lengths first.
       */
      static final int ARR_LENGTH = 4;
    
      /**
       * Maximum long value to be used as array element.
       *
       * <p>Note that a smaller value of {@link #MAX_VALUE} increases the chance of
       * duplicate entries. Should {@link InversionCount#inversionCount} work for
       * duplicate entries? Then we should test those cases.
       */
      static final long MAX_VALUE = 10L;
    
      /** Random-number seed for the test-case generator. */
      static final long SEED = 42L;
    
      /** Number of randomized test cases. */
      static final int NUMBER_OF_RANDOMIZED_TEST_CASES = 100_000;
    
      public static void main(String[] args) {
        Random rnd = new Random(SEED);
    
        LongSupplier getNextLong = () -> {
          long randomLongValue = rnd.nextLong() + rnd.nextLong();
          long minValue = 1L;
          long range = MAX_VALUE - minValue;
          if (range == 0L) {
            return minValue;
          }
          if (range < 0L) {
            throw new AssertionError("invalid range");
          }
          return minValue + Math.abs(randomLongValue % range);
        };
    
        int testCaseCount = NUMBER_OF_RANDOMIZED_TEST_CASES;
        for (int testCaseIdx = 0; testCaseIdx < testCaseCount; ++testCaseIdx) {
          long[] arr = LongStream.generate(getNextLong).limit(ARR_LENGTH).toArray();
    
          long reference = inversionCountReference(arr, arr.length);
          long computed = InversionCount.inversionCount(arr, arr.length);
          if (reference != computed) {
            System.out.println("failing test case: " + Arrays.toString(arr));
            System.out.println("  expected: " + reference);
            System.out.println("  actual: " + computed);
          }
        }
      }
    
      static long inversionCountReference(long arr[], int N) {
        long inversionCount = 0L;
        for (int i = 0; i < N; ++i) {
          for (int j = i + 1; j < N; ++j) {
            // TODO: implement this
            throw new UnsupportedOperationException("not implemented yet");
          }
        }
        return inversionCount;
      }
    }
    

    提示:

    • 实施中的一个缺陷是一个错误。通常,范围由 inclusive 下索引和 exclusive 上索引给出。你打破了这个约定引入了一个错误(仔细检查变量r)。
    • 重新考虑递归中断可能会有所帮助:如何计算长度为 1 的数组的反转计数?这可以简化您的递归吗?

    【讨论】:

      猜你喜欢
      • 2015-12-30
      • 2021-04-21
      • 2022-08-19
      • 1970-01-01
      • 1970-01-01
      • 2020-03-29
      • 2014-07-21
      • 2021-08-09
      • 2012-11-24
      相关资源
      最近更新 更多