📜  非常大的排序数组中唯一元素的计数

📅  最后修改于: 2022-05-13 01:56:09.236000             🧑  作者: Mango

非常大的排序数组中唯一元素的计数

给定一个大小为N排序数组arr[] ,任务是找出该数组中唯一元素的数量。

注意:数组非常大,唯一编号明显更少。即,(唯一元素<<数组的大小)。

例子:

朴素方法:当给定数组已排序时,一种简单的方法是遍历整个元素并将它们与之前的元素进行比较。如果不同,则计算该元素。

时间复杂度: 在)
辅助空间: O(1)。

基于二分搜索的方法:想法是使用二分搜索 因为数组是排序的。请按照以下步骤操作:

  • 取第一个数字,然后使用二进制搜索找到它的最后一次出现或上限。
  • 然后将其视为一个独特的元素。
  • 将指针指向下一个不同的元素并重复相同的步骤。

注意:此算法仅在唯一元素非常少时有效。

下面是上述方法的实现。

C++
// C++ code to implement above approach
#include 
using namespace std;
 
// Binary search to find the last occurrence
int nextIndex(int arr[], int N, int l,
              int target)
{
    int result = -1;
    int r = N - 1;
    while (l <= r) {
        int mid = l + (r - l) / 2;
        if (arr[mid] == target) {
            result = mid;
            l = mid + 1;
        }
        else if (arr[mid] > target)
            r = mid - 1;
        else
            l = mid + 1;
    }
 
    // Result will give the last occurrence &
    // adding one will return next element
    return result + 1;
}
 
// Function to find the number
// of unique elements
int unique(int arr[], int N)
{
    int i = 0;
    int count = 0;
    while (i < N) {
 
        // Returns the next element
        i = nextIndex(arr, N, i, arr[i]);
        count++;
    }
    return count;
}
 
// Driver Code
int main()
{
    int arr[] = { 1, 1, 1, 1, 1, 1, 2, 2, 2,
                  2, 3, 5, 5, 7, 7, 8, 8, 9,
                  9, 10, 11, 12 };
    int N = sizeof(arr) / sizeof(arr[0]);
    cout << unique(arr, N);
    return 0;
}


Java
// Java code to implement above approach
 
class GFG {
 
    // Binary search to find the last occurrence
    static int nextIndex(int arr[], int N, int l, int target) {
        int result = -1;
        int r = N - 1;
        while (l <= r) {
            int mid = l + (r - l) / 2;
            if (arr[mid] == target) {
                result = mid;
                l = mid + 1;
            } else if (arr[mid] > target)
                r = mid - 1;
            else
                l = mid + 1;
        }
 
        // Result will give the last occurrence &
        // adding one will return next element
        return result + 1;
    }
 
    // Function to find the number
    // of unique elements
    static int unique(int arr[], int N) {
        int i = 0;
        int count = 0;
        while (i < N) {
 
            // Returns the next element
            i = nextIndex(arr, N, i, arr[i]);
            count++;
        }
        return count;
    }
 
    // Driver Code
    public static void main(String args[]) {
        int arr[] = { 1, 1, 1, 1, 1, 1, 2, 2, 2,
                2, 3, 5, 5, 7, 7, 8, 8, 9,
                9, 10, 11, 12 };
        int N = arr.length;
        System.out.println(unique(arr, N));
    }
}


Python3
# Python code for the above approach
 
# Binary search to find the last occurrence
def nextIndex(arr, N, l, target):
    result = -1
    r = N - 1
    while (l <= r):
        mid = l + (r - l) // 2
        if (arr[mid] == target):
            result = mid
            l = mid + 1
        elif (arr[mid] > target):
            r = mid - 1
        else:
            l = mid + 1
             
    # Result will give the last occurrence &
    # adding one will return next element
    return result + 1
 
# Function to find the number
# of unique elements
def unique(arr, N):
    i = 0
    count = 0
    while (i < N):
 
        # Returns the next element
        i = nextIndex(arr, N, i, arr[i])
        count += 1
    return count
 
# Driver Code
arr = [1, 1, 1, 1, 1, 1, 2, 2, 2,
       2, 3, 5, 5, 7, 7, 8, 8, 9,
       9, 10, 11, 12]
N = len(arr)
print(unique(arr, N))
 
# This code is contributed by gfgking


C#
// C# program for above approach
using System;
using System.Collections.Generic;
 
public class GFG
{
   
  // Binary search to find the last occurrence
  static int nextIndex(int[] arr, int N, int l, int target) {
    int result = -1;
    int r = N - 1;
    while (l <= r) {
      int mid = l + (r - l) / 2;
      if (arr[mid] == target) {
        result = mid;
        l = mid + 1;
      } else if (arr[mid] > target)
        r = mid - 1;
      else
        l = mid + 1;
    }
 
    // Result will give the last occurrence &
    // adding one will return next element
    return result + 1;
  }
 
  // Function to find the number
  // of unique elements
  static int unique(int[] arr, int N) {
    int i = 0;
    int count = 0;
    while (i < N) {
 
      // Returns the next element
      i = nextIndex(arr, N, i, arr[i]);
      count++;
    }
    return count;
  }
 
  // Driver Code
  static public void Main (){
 
    int[] arr = { 1, 1, 1, 1, 1, 1, 2, 2, 2,
                 2, 3, 5, 5, 7, 7, 8, 8, 9,
                 9, 10, 11, 12 };
    int N = arr.Length;
    Console.WriteLine(unique(arr, N));
  }
}
 
// This code is contributed by hrithikgarg03188


Javascript


C++
// C++ code to implement the above approach
#include 
using namespace std;
 
// Variable to store the number
// of unique elements
int cnt = 0;
 
// Function to find the number
// of unique elements
void UniqueElements(int arr[], int s,
                    int e, bool isDuplicate)
{
    // Both start and end are same
    if (arr[s] == arr[e]) {
 
        // If the element is duplicate
        if (isDuplicate == false) {
            cnt++;
        }
    }
    else {
        int mid = s + (e - s) / 2;
        UniqueElements(arr, s, mid, isDuplicate);
        UniqueElements(arr, mid + 1, e,
                       arr[mid] == arr[mid + 1]);
    }
}
 
// Function to count the number
// of unique elements
int unique(int arr[], int N)
{
    UniqueElements(arr, 0, N - 1, 0);
    return cnt;
}
 
// Driver Code
int main()
{
    int arr[] = { 1, 1, 1, 1, 1, 1, 2, 2, 2,
                  2, 3, 5, 5, 7, 7, 8, 8, 9,
                  9, 10, 11, 12 };
    int N = sizeof(arr) / sizeof(arr[0]);
    cout << unique(arr, N);
    return 0;
}


Java
// Java code to implement the above approach
import java.util.*;
class GFG{
 
  // Variable to store the number
  // of unique elements
  static int cnt = 0;
 
  // Function to find the number
  // of unique elements
  static void UniqueElements(int arr[], int s,
                             int e, boolean isDuplicate)
  {
    // Both start and end are same
    if (arr[s] == arr[e]) {
 
      // If the element is duplicate
      if (isDuplicate == false) {
        cnt++;
      }
    }
    else {
      int mid = s + (e - s) / 2;
      UniqueElements(arr, s, mid, isDuplicate);
      UniqueElements(arr, mid + 1, e,
                     arr[mid] == arr[mid + 1]);
    }
  }
 
  // Function to count the number
  // of unique elements
  static int unique(int arr[], int N)
  {
    UniqueElements(arr, 0, N - 1, false);
    return cnt;
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    int arr[] = { 1, 1, 1, 1, 1, 1, 2, 2, 2,
                 2, 3, 5, 5, 7, 7, 8, 8, 9,
                 9, 10, 11, 12 };
    int N = arr.length;
    System.out.print(unique(arr, N));
  }
}
 
// This code is contributed by 29AjayKumar


Python3
# Python code to implement the above approach
 
# Variable to store the number
# of unique elements
cnt = 0;
 
# Function to find the number
# of unique elements
def UniqueElements(arr, s, e, isDuplicate):
    global cnt
     
    # Both start and end are same
    if (arr[s] == arr[e]):
         
        # If the element is duplicate
        if (isDuplicate == False):
            cnt += 1;
         
    else:
        mid = s + (e - s) // 2;
        UniqueElements(arr, s, mid, isDuplicate);
        UniqueElements(arr, mid + 1, e, arr[mid] == arr[mid + 1]);
     
# Function to count the number
# of unique elements
def unique(arr, N):
    UniqueElements(arr, 0, N - 1, False);
    return cnt;
 
# Driver Code
if __name__ == '__main__':
    arr = [ 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 5, 5, 7, 7, 8, 8, 9, 9, 10, 11, 12 ];
    N = len(arr);
    print(unique(arr, N));
 
# This code is contributed by Rajput-Ji


C#
// C# code to implement the above approach
using System;
public class GFG{
 
  // Variable to store the number
  // of unique elements
  static int cnt = 0;
 
  // Function to find the number
  // of unique elements
  static void UniqueElements(int []arr, int s,
                             int e, bool isDuplicate)
  {
     
    // Both start and end are same
    if (arr[s] == arr[e]) {
 
      // If the element is duplicate
      if (isDuplicate == false) {
        cnt++;
      }
    }
    else {
      int mid = s + (e - s) / 2;
      UniqueElements(arr, s, mid, isDuplicate);
      UniqueElements(arr, mid + 1, e,
                     arr[mid] == arr[mid + 1]);
    }
  }
 
  // Function to count the number
  // of unique elements
  static int unique(int []arr, int N)
  {
    UniqueElements(arr, 0, N - 1, false);
    return cnt;
  }
 
  // Driver Code
  public static void Main(String[] args)
  {
    int []arr = { 1, 1, 1, 1, 1, 1, 2, 2, 2,
                 2, 3, 5, 5, 7, 7, 8, 8, 9,
                 9, 10, 11, 12 };
    int N = arr.Length;
    Console.Write(unique(arr, N));
  }
}
 
// This code is contributed by shikhasingrajput


Javascript



输出
10

时间复杂度: K * logO(N)。其中 K = 否。的独特元素。
辅助空间: O(1)。

基于分而治之的方法:这个问题可以通过分而治之来解决。想法是:

  • 由于重复元素很大,请查看此排序数组的第一个和最后一个元素。
    • 如果两者相等,则表示整个数组中仅存在该元素,并将其计为一个。
    • 如果它们不同,则将数组分成两半,并对每个数组重复上述步骤。
  • 最终计数是唯一元素的数量。

下面是上述方法的实现:

C++

// C++ code to implement the above approach
#include 
using namespace std;
 
// Variable to store the number
// of unique elements
int cnt = 0;
 
// Function to find the number
// of unique elements
void UniqueElements(int arr[], int s,
                    int e, bool isDuplicate)
{
    // Both start and end are same
    if (arr[s] == arr[e]) {
 
        // If the element is duplicate
        if (isDuplicate == false) {
            cnt++;
        }
    }
    else {
        int mid = s + (e - s) / 2;
        UniqueElements(arr, s, mid, isDuplicate);
        UniqueElements(arr, mid + 1, e,
                       arr[mid] == arr[mid + 1]);
    }
}
 
// Function to count the number
// of unique elements
int unique(int arr[], int N)
{
    UniqueElements(arr, 0, N - 1, 0);
    return cnt;
}
 
// Driver Code
int main()
{
    int arr[] = { 1, 1, 1, 1, 1, 1, 2, 2, 2,
                  2, 3, 5, 5, 7, 7, 8, 8, 9,
                  9, 10, 11, 12 };
    int N = sizeof(arr) / sizeof(arr[0]);
    cout << unique(arr, N);
    return 0;
}

Java

// Java code to implement the above approach
import java.util.*;
class GFG{
 
  // Variable to store the number
  // of unique elements
  static int cnt = 0;
 
  // Function to find the number
  // of unique elements
  static void UniqueElements(int arr[], int s,
                             int e, boolean isDuplicate)
  {
    // Both start and end are same
    if (arr[s] == arr[e]) {
 
      // If the element is duplicate
      if (isDuplicate == false) {
        cnt++;
      }
    }
    else {
      int mid = s + (e - s) / 2;
      UniqueElements(arr, s, mid, isDuplicate);
      UniqueElements(arr, mid + 1, e,
                     arr[mid] == arr[mid + 1]);
    }
  }
 
  // Function to count the number
  // of unique elements
  static int unique(int arr[], int N)
  {
    UniqueElements(arr, 0, N - 1, false);
    return cnt;
  }
 
  // Driver Code
  public static void main(String[] args)
  {
    int arr[] = { 1, 1, 1, 1, 1, 1, 2, 2, 2,
                 2, 3, 5, 5, 7, 7, 8, 8, 9,
                 9, 10, 11, 12 };
    int N = arr.length;
    System.out.print(unique(arr, N));
  }
}
 
// This code is contributed by 29AjayKumar

Python3

# Python code to implement the above approach
 
# Variable to store the number
# of unique elements
cnt = 0;
 
# Function to find the number
# of unique elements
def UniqueElements(arr, s, e, isDuplicate):
    global cnt
     
    # Both start and end are same
    if (arr[s] == arr[e]):
         
        # If the element is duplicate
        if (isDuplicate == False):
            cnt += 1;
         
    else:
        mid = s + (e - s) // 2;
        UniqueElements(arr, s, mid, isDuplicate);
        UniqueElements(arr, mid + 1, e, arr[mid] == arr[mid + 1]);
     
# Function to count the number
# of unique elements
def unique(arr, N):
    UniqueElements(arr, 0, N - 1, False);
    return cnt;
 
# Driver Code
if __name__ == '__main__':
    arr = [ 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 3, 5, 5, 7, 7, 8, 8, 9, 9, 10, 11, 12 ];
    N = len(arr);
    print(unique(arr, N));
 
# This code is contributed by Rajput-Ji

C#

// C# code to implement the above approach
using System;
public class GFG{
 
  // Variable to store the number
  // of unique elements
  static int cnt = 0;
 
  // Function to find the number
  // of unique elements
  static void UniqueElements(int []arr, int s,
                             int e, bool isDuplicate)
  {
     
    // Both start and end are same
    if (arr[s] == arr[e]) {
 
      // If the element is duplicate
      if (isDuplicate == false) {
        cnt++;
      }
    }
    else {
      int mid = s + (e - s) / 2;
      UniqueElements(arr, s, mid, isDuplicate);
      UniqueElements(arr, mid + 1, e,
                     arr[mid] == arr[mid + 1]);
    }
  }
 
  // Function to count the number
  // of unique elements
  static int unique(int []arr, int N)
  {
    UniqueElements(arr, 0, N - 1, false);
    return cnt;
  }
 
  // Driver Code
  public static void Main(String[] args)
  {
    int []arr = { 1, 1, 1, 1, 1, 1, 2, 2, 2,
                 2, 3, 5, 5, 7, 7, 8, 8, 9,
                 9, 10, 11, 12 };
    int N = arr.Length;
    Console.Write(unique(arr, N));
  }
}
 
// This code is contributed by shikhasingrajput

Javascript


输出
10


时间复杂度: 平均情况为 O(log(N))。最坏的情况为 O(N)。
辅助空间:   O(1)