📌  相关文章
📜  在给定范围的每个窗口中包含至少P个素数的最小窗口大小

📅  最后修改于: 2021-05-05 00:32:41             🧑  作者: Mango

给定三个整数XYP ,任务是找到最小窗口大小K ,以使该大小的[X,Y]范围内的每个窗口都具有至少P个质数。

例子:

天真的方法:遍历所有可能的窗口大小,对于每个窗口大小在[X,Y]范围内遍历,并检查每个窗口是否包含至少K个质数。这些窗口大小的最小值将是所需的值。

高效方法:此问题的主要观察结果是,如果窗口大小W是满足条件的最小窗口大小,则在[W,Y – X + 1]范围内的所有窗口大小都将满足条件。使用此方法,我们可以将每一步的搜索空间减少一半,而这正是Binary Search的想法。下面是步骤说明:

  • 搜索空间:此问题的搜索空间可以是窗口大小的最小长度为1,最大窗口大小可以是范围的结束值和范围的起始值之差。
    low = 1
    high = Y - X + 1
    
  • 下一个搜索空间:在每个步骤中,通常的想法是在滑动窗口技术的帮助下,检查给定窗口大小下每个窗口中的质数是否具有P个质数。鉴于以下决定,可以减少问题的搜索空间:
    • 情况1:当每个窗口中的质数至少包含P个质数时,可以减小窗口的大小以找到小于当前窗口的窗口大小。
      if (checkPPrimes(mid) == True)
          high = mid - 1
      
    • 情况2:当每个窗口中包含的素数没有时,则窗口大小必须大于当前窗口大小。然后,
      if (checkPPrimes(mid) == False)
          low = mid + 1
      

下面是上述方法的实现:

C++
// C++ implementation to find the
// minimum window size in the range
// such that each window of that size
// contains atleast P primes
  
#include 
  
using namespace std;
  
// Function to check that a number is 
// a prime or not in O(sqrt(N))
bool isPrime(int N)
{
    if (N < 2)
        return false;
    if (N < 4)
        return true;
    if ((N & 1) == 0)
        return false;
    if (N % 3 == 0)
        return false;
    int curr = 5, s = sqrt(N);
  
    // Loop to check if any number
    // number is divisible by any 
    // other number or not
    while (curr <= s) {
        if (N % curr == 0)
            return false;
        curr += 2;
        if (N % curr == 0)
            return false;
        curr += 4;
    }
    return true;
}
  
// Function to check whether window
// size satisfies condition or not
bool check(int s, int p, 
      int prefix_sum[], int n)
{
    bool satisfies = true;
      
    // Loop to check each window of 
    // size have atleast P primes
    for (int i = 0; i < n; i++) {
        if (i + s - 1 >= n)
            break;
          
        // Checking condition 
        // using prefix sum
        if (prefix_sum[i + s - 1] - 
          (i - 1 >= 0 ? 
          prefix_sum[i - 1] : 0) < p)
            satisfies = false;
    }
    return satisfies;
}
  
// Function to find the minimum 
// window size possible for the
// given range in X and Y
int minimumWindowSize(int x, int y,
                             int p)
{
    // Prefix array
    int prefix_sum[y - x + 1] = { 0 };
  
    // Mark those numbers 
    // which are primes as 1
    for (int i = x; i <= y; i++) {
        if (isPrime(i))
            prefix_sum[i - x] = 1;
    }
  
    // Convert to prefix sum
    for (int i = 1; i < y - x + 1; i++)
        prefix_sum[i] += 
              prefix_sum[i - 1];
  
    // Applying binary search 
    // over window size
    int low = 1, high = y - x + 1;
    int mid;
    while (high - low > 1) {
        mid = (low + high) / 2;
          
        // Check whether mid satisfies 
        // the condition or not
        if (check(mid, p, 
           prefix_sum, y - x + 1)) {
              
            // If satisfies search
            // in first half
            high = mid;
        }
          
        // Else search in second half
        else
            low = mid;
    }
    if (check(low, p, 
       prefix_sum, y - x + 1))
        return low;
    return high;
}
  
// Driver Code
int main()
{
    int x = 12;
    int y = 42;
    int p = 3;
  
    cout << minimumWindowSize(x, y, p);
  
    return 0;
}


Java
// Java implementation to find the
// minimum window size in the range
// such that each window of that size
// contains atleast P primes
import java.util.*;
  
class GFG{
   
// Function to check that a number is 
// a prime or not in O(Math.sqrt(N))
static boolean isPrime(int N)
{
    if (N < 2)
        return false;
    if (N < 4)
        return true;
    if ((N & 1) == 0)
        return false;
    if (N % 3 == 0)
        return false;
    int curr = 5, s = (int) Math.sqrt(N);
   
    // Loop to check if any number
    // number is divisible by any 
    // other number or not
    while (curr <= s) {
        if (N % curr == 0)
            return false;
        curr += 2;
        if (N % curr == 0)
            return false;
        curr += 4;
    }
    return true;
}
   
// Function to check whether window
// size satisfies condition or not
static boolean check(int s, int p, 
      int prefix_sum[], int n)
{
    boolean satisfies = true;
       
    // Loop to check each window of 
    // size have atleast P primes
    for (int i = 0; i < n; i++) {
        if (i + s - 1 >= n)
            break;
           
        // Checking condition 
        // using prefix sum
        if (prefix_sum[i + s - 1] - 
          (i - 1 >= 0 ? 
          prefix_sum[i - 1] : 0) < p)
            satisfies = false;
    }
    return satisfies;
}
   
// Function to find the minimum 
// window size possible for the
// given range in X and Y
static int minimumWindowSize(int x, int y,
                             int p)
{
    // Prefix array
    int []prefix_sum = new int[y - x + 1];
   
    // Mark those numbers 
    // which are primes as 1
    for (int i = x; i <= y; i++) {
        if (isPrime(i))
            prefix_sum[i - x] = 1;
    }
   
    // Convert to prefix sum
    for (int i = 1; i < y - x + 1; i++)
        prefix_sum[i] += 
              prefix_sum[i - 1];
   
    // Applying binary search 
    // over window size
    int low = 1, high = y - x + 1;
    int mid;
    while (high - low > 1) {
        mid = (low + high) / 2;
           
        // Check whether mid satisfies 
        // the condition or not
        if (check(mid, p, 
           prefix_sum, y - x + 1)) {
               
            // If satisfies search
            // in first half
            high = mid;
        }
           
        // Else search in second half
        else
            low = mid;
    }
    if (check(low, p, 
       prefix_sum, y - x + 1))
        return low;
    return high;
}
   
// Driver Code
public static void main(String[] args)
{
    int x = 12;
    int y = 42;
    int p = 3;
   
    System.out.print(minimumWindowSize(x, y, p));
}
}
  
// This code is contributed by sapnasingh4991


Python3
# Python3 implementation to find the
# minimum window size in the range
# such that each window of that size
# contains atleast P primes
  
from math import sqrt
  
# Function to check that a number is 
# a prime or not in O(sqrt(N))
def isPrime(N):
    if (N < 2):
        return False
    if (N < 4):
        return True
    if ((N & 1) == 0):
        return False
    if (N % 3 == 0):
        return False
      
    curr = 5
    s = sqrt(N)
      
    # Loop to check if any number
    # number is divisible by any 
    # other number or not
    while (curr <= s):
        if (N % curr == 0):
            return False
        curr += 2
        if (N % curr == 0):
            return False
          
        curr += 4
      
    return True
  
# Function to check whether window
# size satisfies condition or not
def check(s, p, prefix_sum, n):
      
    satisfies = True
    # Loop to check each window of 
    # size have atleast P primes
    for i in range(n):
        if (i + s - 1 >= n):
            break
        # Checking condition 
        # using prefix sum
        if (i - 1 >= 0):
            x = prefix_sum[i - 1]
        else:
            x = 0
        if (prefix_sum[i + s - 1] - x < p):
            satisfies = False
          
    return satisfies
  
# Function to find the minimum 
# window size possible for the
# given range in X and Y
def minimumWindowSize(x, y, p):
      
    # Prefix array
    prefix_sum = [0]*(y - x + 1)
      
    # Mark those numbers 
    # which are primes as 1    
    for i in range(x ,y+1):
        if (isPrime(i)):
            prefix_sum[i - x] = 1
      
    # Convert to prefix sum
    for i in range(1 ,y - x + 1):
        prefix_sum[i] += prefix_sum[i - 1]
          
    # Applying binary search 
    # over window size
    low = 1
    high = y - x + 1
      
    while (high - low > 1):
        mid = (low + high) // 2
          
        # Check whether mid satisfies 
        # the condition or not
        if (check(mid, p ,prefix_sum, y - x + 1)):
              
            # If satisfies search
            # in first half
            high = mid
          
        # Else search in second half
        else:
            low = mid
    if (check(low, p, prefix_sum, y - x + 1)):
        return low
    return high
  
# Driver Code
x = 12
y = 42
p = 3
  
print(minimumWindowSize(x, y, p))
  
# This code is contributed by shubhamsingh10


C#
// C# implementation to find the
// minimum window size in the range
// such that each window of that size
// contains atleast P primes
using System;
  
class GFG{
    
// Function to check that a number is 
// a prime or not in O(Math.Sqrt(N))
static bool isPrime(int N)
{
    if (N < 2)
        return false;
    if (N < 4)
        return true;
    if ((N & 1) == 0)
        return false;
    if (N % 3 == 0)
        return false;
    int curr = 5, s = (int) Math.Sqrt(N);
    
    // Loop to check if any number
    // number is divisible by any 
    // other number or not
    while (curr <= s) {
        if (N % curr == 0)
            return false;
        curr += 2;
        if (N % curr == 0)
            return false;
        curr += 4;
    }
    return true;
}
    
// Function to check whether window
// size satisfies condition or not
static bool check(int s, int p, 
      int []prefix_sum, int n)
{
    bool satisfies = true;
        
    // Loop to check each window of 
    // size have atleast P primes
    for (int i = 0; i < n; i++) {
        if (i + s - 1 >= n)
            break;
            
        // Checking condition 
        // using prefix sum
        if (prefix_sum[i + s - 1] - 
          (i - 1 >= 0 ? 
          prefix_sum[i - 1] : 0) < p)
            satisfies = false;
    }
    return satisfies;
}
    
// Function to find the minimum 
// window size possible for the
// given range in X and Y
static int minimumWindowSize(int x, int y,
                             int p)
{
    // Prefix array
    int []prefix_sum = new int[y - x + 1];
    
    // Mark those numbers 
    // which are primes as 1
    for (int i = x; i <= y; i++) {
        if (isPrime(i))
            prefix_sum[i - x] = 1;
    }
    
    // Convert to prefix sum
    for (int i = 1; i < y - x + 1; i++)
        prefix_sum[i] += 
              prefix_sum[i - 1];
    
    // Applying binary search 
    // over window size
    int low = 1, high = y - x + 1;
    int mid;
    while (high - low > 1) {
        mid = (low + high) / 2;
            
        // Check whether mid satisfies 
        // the condition or not
        if (check(mid, p, 
           prefix_sum, y - x + 1)) {
                
            // If satisfies search
            // in first half
            high = mid;
        }
            
        // Else search in second half
        else
            low = mid;
    }
    if (check(low, p, 
       prefix_sum, y - x + 1))
        return low;
    return high;
}
    
// Driver Code
public static void Main(String[] args)
{
    int x = 12;
    int y = 42;
    int p = 3;
    
    Console.Write(minimumWindowSize(x, y, p));
}
}
   
// This code is contributed by 29AjayKumar


输出:
14

时间复杂度: O(N * log(N))
辅助空间: O(N)