【问题标题】:Make sums of left and right sides of array equal by removing subarray通过删除子数组使数组左侧和右侧的总和相等
【发布时间】:2019-05-22 20:40:00
【问题描述】:

找到要删除的子数组的开始和结束索引以使给定数组具有相等的左侧和右侧总和的 C 程序。如果它不可能打印-1。我需要它适用于任何阵列,这只是为了测试。这是找到平衡的代码。

#include <stdio.h> 

int equilibrium(int arr[], int n) 
{ 
int i, j; 
int leftsum, rightsum; 

/* Check for indexes one by one until 
an equilibrium index is found */
for (i = 0; i < n; ++i) {    

    /* get left sum */
    leftsum = 0; 
    for (j = 0; j < i; j++) 
        leftsum += arr[j]; 

    /* get right sum */
    rightsum = 0; 
    for (j = i + 1; j < n; j++) 
        rightsum += arr[j]; 

    /* if leftsum and rightsum are same, 
    then we are done */
    if (leftsum == rightsum) 
        return i; 
} 

/* return -1 if no equilibrium index is found */
return -1; 
} 

// Driver code 
int main() 
{ 
int arr[] = { -7, 1, 5, 2, -4, 3, 0 }; 
int arr_size = sizeof(arr) / sizeof(arr[0]); 
printf("%d", equilibrium(arr, arr_size)); 

getchar(); 
return 0; 
}

【问题讨论】:

  • 听起来是个有趣的问题。到目前为止你尝试过什么?
  • 要移除一个元素,需要让它移除子数组。
  • 所以简单的 O(n^2) 答案是两个嵌套的 for 循环。外循环迭代起始索引,内循环迭代结束索引(必须等于或大于开始)。
  • 我想我应该提到总和应该逐步更新。例如,leftSumarr[0] 开头。每次起始索引增加时,leftSum 都会更新为 leftSum += arr[start]。为了在内循环中工作,内循环必须反向运行(从数组的末尾开始,向后遍历数组,直到到达起始索引)。
  • 你能用C++stdlib吗?

标签: c arrays optimization big-o sub-array


【解决方案1】:

您可以在O(NlogN)O(N)(一般情况下)解决这个问题。

首先,您需要进行预处理,将所有和从右到左保存在数据结构中,特别是平衡二叉搜索树(例如Red Black tree、AVL 树、Splay 树等,如果可以的话使用stdlib,只需使用std::multiset) 或HashTable(在stdlib 中是std::unordered_multiset):

void preProcessing(dataStructure & ds, int * arr, int n){
    int sum = 0;
    int * toDelete = (int) malloc(n)
    for(int i = n-1; i >= 0; --i){
        sum += arr[i];
        toDelete[i] = sum; // Save items to delete later.
        tree.insert(sum);
    }

所以要解决问题,你只需要遍历数组一次:

// It considers that the deleted subarray could be empty
bool Solve(dataStructure & ds, int * arr, int n, int * toDelete){
    int sum = 0;
    bool solved = false; // true if a solution is found
    for(int i = 0 ; i < n; ++i){ 
        ds.erase(toDelete[i]); // deletes the actual sum up to i-th element from data structure, as it couldn't be part of the solution.
                               // It costs O(logN)(BBST) or O(1)(Hashtable)
        sum += arr[i];
        if(ds.find(sum)){// If sum is in ds, then there's a leftsum == rightsum
                         // It costs O(logN)(BBST) or O(1)(HashTable)
            solved = true;
            break;
        }
    }
    return solved;
}

然后,如果您使用 BBST(平衡二叉搜索树),您的解决方案将是 O(NlogN),但是,如果您使用 HashTable,您的解决方案平均会是 O(N)。我不会实现它,所以也许有一个错误,但我试图解释主要思想。

【讨论】:

  • 用 C++ 回答 C 问题通常没那么有用。 C 中没有 std::xxxx 可用作为标记中的问题。 (您的一般建议是合理的,但必须在 C 中从头开始实施)
  • 数据结构可以是标准库,也可以用 C 实现。
猜你喜欢
  • 1970-01-01
  • 2011-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多