【问题标题】:Need more Efficient way to read subarrays需要更有效的方式来读取子数组
【发布时间】:2018-06-18 12:36:40
【问题描述】:

问题陈述询问i

我做了什么:

我从 i=0 到 n-2 运行了一个循环: 我使用的基本逻辑是,如果排序子数组中的前两个元素大于或等于最大值,那么所有对都将大于任何元素。每次获得子数组时,我都会将下一个元素添加到其中并再次设置这三个变量。正在通过 15/20 TC,其他人正在获得 TLE:
约束:
1 1

for(int i=0;i<n-2;i++)
{
    int r=i+2;
    vector<int> temp(inp.begin()+i,inp.begin()+r+1);
    sort(temp.begin(),temp.end());
    max_elem=temp[1];min_elem=temp[0];
    int maximum=temp[temp.size()-1];


    //cout<<max_elem<<" "<<min_elem<<"\n";

    while(r<n && max_elem+min_elem >= maximum)
    {   
        //cout<<max_elem<<" "<<min_elem<<" "<<inp[r]<<"\n";
        cnt++;
        r++;

        if(inp[r]<min_elem) {max_elem=min_elem;min_elem=inp[r];}
        else if(inp[r]<max_elem) max_elem=inp[r];
        else if(inp[r]>maximum) maximum=inp[r];

    }

}
cout<<cnt<<"\n";

示例 TC:

I1
5
7 6 5 3 4
O1:
6
说明:
6 个子数组满足条件:(7,6,5),(7,6,5,3),(7,6,5,3,4),(6,5,3) ,(6,5,3,4),(5,3,4)。

I2
5
1 2 3 5 6
O2:
3
说明:
(1,2,3),(2,3,5),(3,5,6) --(注意:1,2,3,5 不是答案,因为 1+2

【问题讨论】:

  • 如果有问题的链接或屏幕截图将使问题更清晰。
  • 你能告诉我我的问题中有什么不清楚的地方吗?我会添加它以澄清?
  • 我添加了示例TC,现在清楚了吗?

标签: arrays algorithm loops coding-efficiency time-limiting


【解决方案1】:

执行此操作的一种天真的方法如下。你的逻辑是正确的,这就是我实现的。我用单遍(N)改变了排序(NlogN),只找到了2个最小和最大的数字。我还没有编译代码,不确定它是否按预期工作。它的整体复杂度为 (N*N*N)。

执行一些额外的检查可以改善执行时间:

  • min1 + min2 &gt;= maxcondition 可以在每个内部 (k) 循环之后检查,如果它违反单个案例则中断。
  • 如果子数组 4-7 的条件不满足,则不需要检查包括 4-7 在内的任何其他子字符串。通过存储违规案例并在每次循环之前对其进行检查,可以提高整体执行时间。

    int min1;
    int min2;
    int max;
    int count = 0;
    for(int i = 2; i < n; i++){
        for(int j = 0; j < i - 2; j++){
            max = -1;
            min1 = min2 = 1000000000;
            for(int k = j; k <= i; k++){
                if(inp[k] > max)
                    max = inp[k];
                if(inp[k] < min1){
                    min1 = inp[k];
                    continue;
                }
                if(inp[k] < min2){
                    min2 = inp[k];
                }
            }
            if(min1 + min2 >= max)
                count++;
        }
    } 
    

【讨论】:

    【解决方案2】:

    可能存在一些错误,但这里是 O(n log n) 解决方案的总体思路:

    我们保留从 startIdx 到 endIdx 的元素窗口。如果它是一个有效的子数组,这意味着我们可以扩展它,我们可以向它添加另一个元素,所以我们增加 endIdx。如果它不成立,那么无论我们如何扩大它都不成立,所以我们需要通过增加startIdx来减少它。

    伪代码:

    multiset<int> nums;
    
    int startIdx = 0, endIdx = 0;
    int sol = 0;
    
    while(endIdx != inp.size()) {
        if (endIdx - startIdx < 3) {
           nums.add(inp[endIdx]);  
           endIdx++;
        } else  {
           if (nums.lowestElement() + nums.secondLowestElement() < nums.highestElement()) {
              nums.remove(nums.find(inp[startIdx]));
              startIdx++;
           } else { 
                sol += endIdx - startIdx - 2; // amount of valid subarrays ending in inp[endIdx - 1]
                nums.add(inp[endIdx]);  
                endIdx++;
           }
        }
    }
    

    【讨论】:

    • 但这就是我所做的,它仍然在给 TLE。
    • @Behl 不完全相同。考虑到所有元素都是 1,因此每个至少包含 3 个元素的子数组都是有效的。然后用 10^5 个元素,就有 1 + 2 + 3 + 4... + n - 2 个解,也就是 10^10 的数量级。您的代码将计算其中的每一个(cnt++),给出 TLE。我的会一起计算其中的一个,我的 sol += 部分只运行 10^5 次
    猜你喜欢
    • 1970-01-01
    • 2012-05-26
    • 2011-04-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多