Блог пользователя ladpro98

Автор ladpro98, 11 лет назад, По-английски

Here is the problem statement:

Given an array A[1..n]. Find the sub-array that it's sum is smallest and at least M. (all numbers in the input is 32bit integer)

Till now I cannot find a good solution. Can anyone help me with an O(n) or O(NlogN) algorithm?

  • Проголосовать: нравится
  • 0
  • Проголосовать: не нравится

»
11 лет назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Umm... pre-compute the partial sums in O(N) and bin-search in per query?

  • »
    »
    11 лет назад, # ^ |
    Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

    Can you give me more details. I try to sort the SUM array but then I am unable to Bin-Search since the positions has changed.

    • »
      »
      »
      11 лет назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      What? Why would you sort? That'd obviously completely mess up the results. Also, what are "positions"?

      Compute prefix sums (or partial sums as you call it): S[i] = S[i - 1] + A[i], S[0] = 0.

      Ok, I just realized that A[i] can be negative, so bin-search won't work (it requires the sums to be increasing/decreasing). But you can still try all S[i] and pick the one that fits your condition. There are just O(N) of them, so the time complexity is O(N).

      • »
        »
        »
        »
        11 лет назад, # ^ |
        Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

        So, for each i, we use an inner for loop to find the best S[j] such thạt S[j]+M <= S[i] (here partial sum means the sum of elements a[j..i]) I think the complexity is O(N^2)

        • »
          »
          »
          »
          »
          11 лет назад, # ^ |
            Проголосовать: нравится 0 Проголосовать: не нравится

          No, for each i, we use one line of code to check if S[i] ≥ M. The complexity is O(N).

          • »
            »
            »
            »
            »
            »
            11 лет назад, # ^ |
            Rev. 3   Проголосовать: нравится 0 Проголосовать: не нравится

            I think you have misunderstood my question, there are O(N^2) sums. I am not asking for prefix sums, but sums of consecutive elements. Sum[i..j] = PrefixSum[j] — PrefixSum[i-1]

            • »
              »
              »
              »
              »
              »
              »
              11 лет назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится

              you mean PrefixSum[j]-PrefixSum[i-1]

            • »
              »
              »
              »
              »
              »
              »
              11 лет назад, # ^ |
                Проголосовать: нравится +1 Проголосовать: не нравится

              In the OP, you were asking for partial sums. I suggest you read something about them, for example on Wikipedia

              • »
                »
                »
                »
                »
                »
                »
                »
                11 лет назад, # ^ |
                Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

                Thanks, I got it. Sorry for bad English. (I have already edited my post) Hope you can help me with my homework.

            • »
              »
              »
              »
              »
              »
              »
              11 лет назад, # ^ |
                Проголосовать: нравится +1 Проголосовать: не нравится

              I think you should store PrefixSums in a map and then look for smallest value in map which is at least PrefixSum[i]-M, but i dont know the complexity of this

              • »
                »
                »
                »
                »
                »
                »
                »
                11 лет назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится

                I have no idea about Map data structure. The problem is just a weekly homework and I think it can be solved using pure C (raw arrays).

            • »
              »
              »
              »
              »
              »
              »
              11 лет назад, # ^ |
                Проголосовать: нравится +1 Проголосовать: не нравится

              You should have a set which stores prefixSum[0], ..., prefixSum[i-1] at every iteration. Then use something like set.floor(prefixSums[i] — M). It will find the best candidate if the right index is i.

              • »
                »
                »
                »
                »
                »
                »
                »
                11 лет назад, # ^ |
                  Проголосовать: нравится 0 Проголосовать: не нравится

                I have just read basic information about Set. Thanks for your idea, it will work. But because I use PASCAL (not C++), implementing Set is such a challenging task.

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  11 лет назад, # ^ |
                  Rev. 3   Проголосовать: нравится +1 Проголосовать: не нравится

                  I know a solution with Fenwick tree and binary searches, it's Nlog^2N but it's very fast Nlog^2N.

                  You know what elements will be in the set in the end, so you can give them the indices in the increasing order (e.g by sorting pairs (prefixSums[i], i)):

                  Then you should have a Fenwick tree: tree[i] = 1 if the prefix sum with index i is in the set, otherwise it is 0.

                  How to add number in the set? Find its index (by binary search in sorted pairs (prefixSums[i], i)). Set tree[i] = 1.

                  How to process floor(x) operation? Find the index of the largest element in the sorted pairs array which is less or equal than x, let it be i. Then use another binary search, in the Fenwick tree, to find the smallest element j such that sum(0..j) == sum(0..i).

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  11 лет назад, # ^ |
                    Проголосовать: нравится 0 Проголосовать: не нравится

                  Your idea seems promising. I hope we can have a private chat to figure out some details. I can only use Fenwick tree with getSum or getMax operations, it will be cool if i can use Fenwick tree for getFloor method.