内存限制超出子数组问题

huangapple go评论52阅读模式
英文:

Memory limit exceeding in sub array problem

问题

我正在尝试解决一个问题,但我超出了内存限制。

问题描述

给定一个整数数组 A 和两个整数 B 和 C。

你需要找到子数组的数量,其中 B 的出现次数等于 C 的出现次数。

注意:不要计算空的子数组。

输入格式
第一个参数是整数数组 A。

第二个参数是整数 B。

第三个参数是整数 C。

输出格式
返回一个整数,表示 B 出现次数等于 C 出现次数的子数组数量。

英文:

I'm trying to solve a problem, but I'm exceeding the memory limit.

Problem Description

Given an integer array A and two integers B and C.

You need to find the number of subarrays in which the number of occurrences of B is equal to number of occurrences of C.

NOTE: Don't count empty subarrays.

Input Format
First argument is an integer array A.

Second argument is an integer B.

Third argument is an integer C.

Output Format
Return an integer denoting the number of subarrays in which the number of occurrences of B is equal to number of occurrences of C.

/**
 * @input A : Integer array
 * @input n1 : Integer array's ( A ) length
 * @input B : Integer
 * @input C : Integer
 * 
 * @Output Integer
 */
int SubArrays(int* arr, int start, int end, int size, int B, int C)
{
   
    int countB = 0,countC = 0;
    // Stop if we have reached the end of the array
    if (end == size)
        return 0;
    
    // Increment the end point and start from 0
    else if (start > end)
        SubArrays(arr, 0, end + 1, size, B, C);
   
    // Print the subarray and increment the starting point
    else {
        int A[end-start+1];
        int i, j;
        for ( i = start; i < end; i++){
            for(j =0; j<(end-start+1);j++){
                A[j] = arr[i];
            }
        }
        for(j =0; j<(end-start+1);j++){
            if(A[j]==B) countB ++;
            if(A[j]==C) countC ++;
        }
        // cout << arr[end] << "]" << endl;
        SubArrays(arr, start + 1, end, size, B, C);
    }
    if(countB == countC)
        return 1;
    else
        return 0;
}
int solve(int* A, int n1, int B, int C) {
    int count = 0;
    count = count + SubArrays(A,0,0,n1,B,C);
    return count;
}

答案1

得分: 1

在一般情况下,你的例程创建一个数组 int A[end-start+1],然后递归调用自身。这会占用大量空间,而且没有必要。

许多挑战或在线评测问题旨在创造性地解决,使用对问题的“更广泛”视角,而不是“蛮力”,例如检查所有可能的组合。

在这种情况下,一种解决方案是:

  • 创建一个辅助数组 T,并将每个元素 Ti 设置为 B 出现在 A 中的元素(从 A0 到 Ai,包括 i)的次数减去 C 出现在 A 中的元素(从 A0 到 Ai,包括 i)的次数。例如,假设 B = 3 和 C = 4,A 如下所示:
i 0 1 2 3 4 5 6 7 8
A 1 3 3 5 4 0 4 4 4
T 0 +1 +2 +2 +1 +1 0 −1 −2
  • 然后使用 T 来找到子数组。对于任何 ij,使得 Ti = Tj,A 中从 Ai 到 Aj 的子数组将包含相等数量的 B 值和 C 值。
  • 你可以通过简单地遍历所有 ij 值,其中 ij,来计算这些子数组。

例如,对于上面的例子,(0, 6)(意味着 i=0,j=6)形成一个包含相等数量的 B 值和 C 值的子数组,(1, 4),(1, 5),(2, 3) 和 (4, 5) 也是如此。所以所需的子数组数量是 5。

(如果允许修改原始数组,这些辅助信息可以在原始数组中就地计算,替换其原始内容。)

这将给你一个时间复杂度大约为 n^2 的解决方案,其中 n 是 A 中的元素数量。然而,还有一个更好的解决方案:

  • T 进行排序。这会将所有相同的值放在一起。然后,你可以遍历 T 并轻松地计算每个值出现的次数。对于出现 m 次的值,可以从中形成 m•(m−1)/2 对 ij 值,因此将 m•(m−1)/2 添加到一个运行总数中。在遍历 T 结束时,总数就是所需的子数组数量。

这将给你一个时间复杂度大约为 n log n 的解决方案。

可以在一个函数中实现这个解决方案,包括七行 C 代码(利用一些经验丰富的程序员可能使用的 C 符号),以及一个辅助函数(用于排序比较),该函数只需一两行。

关于计算对的提示:你不需要等到一系列重复结束后才将其添加到运行总数中。如果当前值在 T 中已经出现了 m 次,那么将 m−1 添加到运行总数中。当该值已经出现 m 次时,将为它们添加 m•(m−1),例如,如果一个值出现了四次,我们将在第一次看到它时添加 0,然后添加 1,然后添加 2,然后添加 3,1+2+3 = 4•(4−1)/2。

英文:

In the general case, your routine creates an array int A[end-start+1] and then calls itself recursively. This uses a lot of space, and there is no need for it.

Many of the challenge or online judge problems are intended to be solved creatively, using a “greater” view of the problem and not “brute force” such as examining all possible combinations.

In this case, a solution is:

  • Create an auxiliary array T and set each element T<sub>i</sub> to the number of times that B appears in the elements of A from A<sub>0</sub> to A<sub>i</sub> minus the number of times that C appears in the elements of A from A<sub>0</sub> to A<sub>i</sub>, inclusive. For example, with B = 3 and C = 4 and A as shown below:
i 0 1 2 3 4 5 6 7 8
A 1 3 3 5 4 0 4 4 4
T 0 +1 +2 +2 +1 +1 0 −1 −2
  • Then use T to find subarrays. For any i and j such that T<sub>i</sub> = T<sub>j</sub>, the subarray of A from A<sub>i</sub> to A<sub>j</sub>, inclusive, will contain equal numbers of B values and C values.
  • You can count these by simply iterating through all i and j values in bounds with ij.

For example, with the above, (0, 6) (meaning i=0, j=6) forms a subarray with equal numbers of B values and C values, and so do (1, 4), (1, 5), (2, 3), and (4, 5). So the desired number of subarrays is 5.

(If it modifying the original array is allowed, this auxiliary information can be computed in-place in the array, replacing its original contents.)

That will give you a solution that takes time roughly proportional to n<sup>2</sup>, where n is the number of elements in A. However, there is a better solution:

  • Sort T. This puts all identical values together. Then you can iterate through T and easily count how many times each value occurs. For a value that occurs m times, m•(m−1)/2 pairs of i and j values can be formed from it, so add m•(m−1)/2 to a running total. At the end of iterating through T, the total is the desired number of subarrays.

That gives you an solution with a running time roughly proportional to n log n.

It can be implemented in one function with seven lines of C code (taking advantage of some C notations that an experienced programmer might use, but reasonable) and an auxiliary function (for the sort comparison) that is one or two lines.

Hint for counting the pairs: You do not need to wait until the end of a sequence of repetitions to add to the running total. If the current value in T has been seen m times so far, add m−1 to the running total. When the value has been seen m times, m•(m−1) will have been added for them. For example, if a value is seen four times, we will add 0 the first time it is seen, then 1, then 2, then 3, and 1+2+3 = 4•(4−1)/2.

huangapple
  • 本文由 发表于 2023年5月28日 16:36:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/76350610.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定