📌  相关文章
📜  两个相等总和段范围查询

📅  最后修改于: 2021-06-26 12:13:44             🧑  作者: Mango

给定一个由N个正整数组成的数组arr [] ,以及一些由范围[L,R]组成的查询,任务是查找给定索引范围内的子数组是否可以分为两个非连续的相邻部分。零长度和相等的总和。
例子:

一个简单的解决方案是遍历整个范围并计算范围的总和。然后,我们将再次遍历整个数组。我们将总结从索引“ L”开始的元素。如果在任何步骤上我们发现当前的总和是该范围的总和的一半,则该范围表示的子数组可以分为两个相等的一半。使用这种方法最多可能需要O(n)时间来回答查询。
更好的解决方案是使用前缀和数组。首先,我们创建arr的前缀和数组p_arr 。现在,使用’p_arr’,我们可以确定O(1)时间中’L’到’R’范围内所有元素的总和。有了总和后,我们需要确定是否存在从L到R-1的索引“ i”,使原始数组从L到i的所有数字的和为范围之和的一半。为此,我们可以简单地将所有值插入无序映射的前缀和数组’p_arr’中。

因此,回答查询的时间复杂度变为O(1)。
下面是上述方法的实现:

C++
// C++ implementation of the approach
#include 
using namespace std;
 
// Function to find the required prefix sum
void prefixSum(int* p_arr, int* arr, int n)
{
    p_arr[0] = arr[0];
    for (int i = 1; i < n; i++)
        p_arr[i] = arr[i] + p_arr[i - 1];
}
 
// Function to hash all the values of prefix
// sum array in an unordered map
void hashPrefixSum(int* p_arr, int n, unordered_set& q)
{
    for (int i = 0; i < n; i++)
        q.insert(p_arr[i]);
}
 
// Function to check if a range
// can be divided into two equal parts
void canDivide(int* p_arr, int n,
               unordered_set& q, int l, int r)
{
    // To store the value of sum
    // of entire range
    int sum;
 
    if (l == 0)
        sum = p_arr[r];
    else
        sum = p_arr[r] - p_arr[l - 1];
 
    // If value of sum is odd
    if (sum % 2 == 1) {
        cout << "No" << endl;
        return;
    }
 
    // To store p_arr[l-1]
    int beg = 0;
 
    if (l != 0)
        beg = p_arr[l - 1];
 
    // If the value exists in the map
    if (q.find(beg + sum / 2) != q.end())
        cout << "Yes" << endl;
    else
        cout << "No" << endl;
}
 
// Driver code
int main()
{
    int arr[] = { 1, 1, 2, 3 };
    int n = sizeof(arr) / sizeof(arr[0]);
 
    // prefix-sum array
    int p_arr[n];
 
    prefixSum(p_arr, arr, n);
 
    // Map to store the values of prefix-sum
    unordered_set q;
 
    hashPrefixSum(p_arr, n, q);
 
    // Perform queries
    canDivide(p_arr, n, q, 0, 1);
    canDivide(p_arr, n, q, 1, 3);
    canDivide(p_arr, n, q, 1, 2);
 
    return 0;
}


Java
// Java implementation of the approach
import java.util.*;
class GFG {
 
// Function to find the required prefix sum
static void prefixSum(int[] p_arr, int[] arr, int n)
{
    p_arr[0] = arr[0];
    for (int i = 1; i < n; i++)
        p_arr[i] = arr[i] + p_arr[i - 1];
}
  
// Function to q all the values of prefix
// sum array in an unordered map
static void qPrefixSum(int[]p_arr, int n, HashSetq)
{
    for (int i = 0; i < n; i++)
        q.add(p_arr[i]);
}
  
// Function to check if a range
// can be divided into two equal parts
static void canDivide(int[] p_arr, int n,
               HashSetq, int l, int r)
{
    // To store the value of sum
    // of entire range
    int sum;
  
    if (l == 0)
        sum = p_arr[r];
    else
        sum = p_arr[r] - p_arr[l - 1];
  
    // If value of sum is odd
    if (sum % 2 == 1) {
        System.out.println("No");
        return;
    }
  
    // To store p_arr[l-1]
    int beg = 0;
  
    if (l != 0)
        beg = p_arr[l - 1];
  
    // If the value exists in the map
    if(q.contains(beg + sum / 2) && (beg + sum / 2)!=(int)q.toArray()[ q.size()-1 ] )
        System.out.println("Yes");
    else
        System.out.println("No");
}
  
// Driver code
 public static void main(String[] args) {
   int arr[] = { 1, 1, 2, 3 };
    int n = arr.length;
  
    // prefix-sum array
    int p_arr[] = new int[n];
  
    prefixSum(p_arr, arr, n);
  
    // Map to store the values of prefix-sum
    HashSet q = new HashSet<>();
  
    qPrefixSum(p_arr, n, q);
  
    // Perform queries
    canDivide(p_arr, n, q, 0, 1);
    canDivide(p_arr, n, q, 1, 3);
    canDivide(p_arr, n, q, 1, 2);
    }
}
 
// This code contributed by Rajput-Ji


Python3
# Python3 implementation of the approach
 
# Function to find the required prefix Sum
def prefixSum(p_arr, arr, n):
 
    p_arr[0] = arr[0]
    for i in range(1, n):
        p_arr[i] = arr[i] + p_arr[i - 1]
 
# Function to hash all the values of
# prefix Sum array in an unordered map
def hashPrefixSum(p_arr, n, q):
 
    for i in range(n):
        q[p_arr[i]] = 1
 
# Function to check if a range
# can be divided into two equal parts
def canDivide(p_arr, n, q, l, r):
     
    # To store the value of Sum
    # of entire range
    Sum = 0
 
    if (l == 0):
        Sum = p_arr[r]
    else:
        Sum = p_arr[r] - p_arr[l - 1]
 
    # If value of Sum is odd
    if (Sum % 2 == 1):
        print("No")
        return
     
    # To store p_arr[l-1]
    beg = 0
 
    if (l != 0):
        beg = p_arr[l - 1]
 
    # If the value exists in the map
    if (beg + Sum // 2 in q.keys()):
        print("Yes")
    else:
        print("No")
 
# Driver code
arr = [1, 1, 2, 3]
n = len(arr)
 
# prefix-Sum array
p_arr = [0 for i in range(n)]
 
prefixSum(p_arr, arr, n)
 
# Map to store the values
# of prefix-Sum
q = dict()
 
hashPrefixSum(p_arr, n, q)
 
# Perform queries
canDivide(p_arr, n, q, 0, 1)
canDivide(p_arr, n, q, 1, 3)
canDivide(p_arr, n, q, 1, 2)
 
# This code is contributed
# by mohit kumar


C#
// C# implementation of the approach
using System;
using System.Collections.Generic;
 
class GFG
{
 
// Function to find the required prefix sum
static void prefixSum(int[] p_arr, int[] arr, int n)
{
    p_arr[0] = arr[0];
    for (int i = 1; i < n; i++)
        p_arr[i] = arr[i] + p_arr[i - 1];
}
 
// Function to q all the values of prefix
// sum array in an unordered map
static void qPrefixSum(int[]p_arr, int n, HashSetq)
{
    for (int i = 0; i < n; i++)
        q.Add(p_arr[i]);
}
 
// Function to check if a range
// can be divided into two equal parts
static void canDivide(int[] p_arr, int n,
            HashSetq, int l, int r)
{
    // To store the value of sum
    // of entire range
    int sum;
 
    if (l == 0)
        sum = p_arr[r];
    else
        sum = p_arr[r] - p_arr[l - 1];
 
    // If value of sum is odd
    if (sum % 2 == 1)
    {
        Console.WriteLine("No");
        return;
    }
 
    // To store p_arr[l-1]
    int beg = 0;
 
    if (l != 0)
        beg = p_arr[l - 1];
 
    // If the value exists in the map
    if(q.Contains(beg + sum / 2) )
        Console.WriteLine("Yes");
    else
        Console.WriteLine("No");
}
 
// Driver code
public static void Main(String[] args)
{
    int []arr = { 1, 1, 2, 3 };
    int n = arr.Length;
 
    // prefix-sum array
    int []p_arr = new int[n];
 
    prefixSum(p_arr, arr, n);
 
    // Map to store the values of prefix-sum
    HashSet q = new HashSet ();
 
    qPrefixSum(p_arr, n, q);
 
    // Perform queries
    canDivide(p_arr, n, q, 0, 1);
    canDivide(p_arr, n, q, 1, 3);
    canDivide(p_arr, n, q, 1, 2);
}
}
 
// This code has been contributed by 29AjayKumar


Javascript


输出:
Yes
Yes
No

如果您希望与行业专家一起参加现场课程,请参阅《 Geeks现场课程》和《 Geeks现场课程美国》。