📜  在O(Log n)时间中找到出现的奇数元素

📅  最后修改于: 2021-04-27 21:06:44             🧑  作者: Mango

给定一个数组,其中除一个元素外,所有元素均出现偶数次。所有重复出现的元素均成对出现,并且这些对不相邻(任何元素不能连续出现两次以上)。查找出现奇数次的元素。
请注意,像{2,2,1,2,2,1,1,1}这样的输入是有效的,因为所有重复出现都是成对发生的,并且这些对不相邻。像{2,1,2}这样的输入无效,因为重复元素不会成对出现。同样,由于{2,2,2,2,2}之类的输入是无效的,因为两对2相邻。像{2,2,2,1}这样的输入也是无效的,因为连续出现了3个2。
例子 :

Input: arr[] = {1, 1, 2, 2, 1, 1, 2, 2, 13, 1, 1, 40, 40, 13, 13}
Output: 13

Input: arr[] = {1, 1, 2, 2, 3, 3, 4, 4, 3, 600, 600, 4, 4}
Output: 3

强烈建议您最小化浏览器,然后自己尝试。
一个简单的解决方案是对数组进行排序,然后从左到右遍历该数组。由于数组已排序,因此我们可以轻松找出所需的元素。该解决方案的时间复杂度为O(n Log n)
更好的解决方案是对所有元素进行XOR,XOR结果将给出出现的奇数元素。该解决方案的时间复杂度为O(n)。有关更多详细信息,请参见基于XOR的解决方案以添加终止。
一个有效的解决方案可以在O(Log n)时间中找到所需的元素。这个想法是使用二进制搜索。下面是对输入数组的观察。
由于该元素出现奇数次,因此该元素必须存在一次。例如,在{2,1,1,2,2)中,前2个为奇数出现。因此,想法是使用二进制搜索找到这种奇怪的情况。
奇数出现之前的所有元素的第一个出现在偶数索引(0,2,..),下一个出现在奇数索引(1,3,…)。并且所有元素在奇数索引处先出现后在偶数索引处后发生。
1)找到中间索引,说’mid’。
2)如果“ mid”是偶数,则比较arr [mid]和arr [mid + 1]。如果两者相同,则在“ mid”之后出现元素的奇数,否则在mid之前出现。
3)如果’mid’为奇数,则比较arr [mid]和arr [mid – 1]。如果两者相同,则在“ mid”之后出现一个奇数出现,否则在mid之前出现。
下面是基于以上思想的实现。

C++
// C program to find the element that appears odd number of time
#include
 
// A Binary Search based function to find the element
// that appears odd times
void search(int *arr, int low, int high)
{
    // Base cases
    if (low > high)
    return;
    if (low==high)
    {
        printf("The required element is %d ", arr[low]);
        return;
    }
 
    // Find the middle point
    int mid = (low+high)/2;
 
    // If mid is even and element next to mid is
    // same as mid, then output element lies on
    // right side, else on left side
    if (mid%2 == 0)
    {
        if (arr[mid] == arr[mid+1])
            search(arr, mid+2, high);
        else
            search(arr, low, mid);
    }
    else // If mid is odd
    {
        if (arr[mid] == arr[mid-1])
            search(arr, mid+1, high);
        else
            search(arr, low, mid-1);
    }
}
 
// Driver program
int main()
{
    int arr[] = {1, 1, 2, 2, 1, 1, 2, 2, 13, 1, 1, 40, 40};
    int len = sizeof(arr)/sizeof(arr[0]);
    search(arr, 0, len-1);
    return 0;
}


Java
// Java program to find the element
// that appears odd number of time
 
class GFG
{
    // A Binary Search based function to find
    // the element that appears odd times
    static void search(int arr[], int low, int high)
    {
        // Base cases
        if (low > high)
        return;
        if (low == high)
        {
            System.out.printf("The required element is %d "
                              , arr[low]);
            return;
        }
     
        // Find the middle point
        int mid = (low + high)/2;
     
        // If mid is even and element next to mid is
        // same as mid, then output element lies on
        // right side, else on left side
        if (mid % 2 == 0)
        {
            if (arr[mid] == arr[mid + 1])
                search(arr, mid + 2, high);
            else
                search(arr, low, mid);
        }
         
        // If mid is odd
        else
        {
            if (arr[mid] == arr[mid - 1])
                search(arr, mid + 1, high);
            else
                search(arr, low, mid - 1);
        }
    }
     
    // Driver program
    public static void main(String[] args)
    {
        int arr[] = {1, 1, 2, 2, 1, 1, 2, 2, 13,
                                    1, 1, 40, 40};
        int len = arr.length;
        search(arr, 0, len-1);
    }
}
// This code is contributed by
// Smitha DInesh Semwal


Python
# Python program to find the element that appears odd number of times
# O(log n) approach
 
# Binary search based function
# Returns the element that appears odd number of times
def search(arr, low, high):
     
    # Base case
    if low > high:
        return None
    if low == high:
        return arr[low]
 
    # Find the middle point
    mid = (low + high)/2;
 
    # If mid is even
    if mid%2 == 0:
         
        # If the element next to mid is same as mid,
        # then output element lies on right side,
        # else on left side
        if arr[mid] == arr[mid+1]:
            return search(arr, mid+2, high)
        else:
            return search(arr, low, mid)
 
    else:
        # else if mid is odd
 
        if arr[mid] == arr[mid-1]:
            return search(arr, mid+1, high)
        else:
            # (mid-1) because target element can only exist at even place
            return search(arr, low, mid-1)
 
 
# Test array
arr = [ 1, 1, 2, 2, 1, 1, 2, 2, 13, 1, 1, 40, 40 ]
 
result = search(arr, 0, len(arr)-1 )
 
if result is not None:
    print "The required element is %d " % result
else:
    print "Invalid array"


C#
// C# program to find the element
// that appears odd number of time
using System;
 
class GFG  {
     
    // A Binary Search based function to find
    // the element that appears odd times
    static void search(int []arr, int low, int high)
    {
        // Base cases
        if (low > high)
        return;
        if (low == high)
        {
            Console.WriteLine("The required element is "+
                                               arr[low]);
            return;
        }
     
        // Find the middle point
        int mid = (low + high)/2;
     
        // If mid is even and element next to mid is
        // same as mid, then output element lies on
        // right side, else on left side
        if (mid % 2 == 0)
        {
            if (arr[mid] == arr[mid + 1])
                search(arr, mid + 2, high);
            else
                search(arr, low, mid);
        }
         
        // If mid is odd
        else
        {
            if (arr[mid] == arr[mid - 1])
                search(arr, mid + 1, high);
            else
                search(arr, low, mid - 1);
        }
    }
     
    // Driver program
    public static void Main()
    {
        int []arr = {1, 1, 2, 2, 1, 1, 2, 2, 13,
                                  1, 1, 40, 40};
        int len = arr.Length;
        search(arr, 0, len-1);
    }
}
 
// This code is contributed by Sam007


PHP
 $high)
    return;
    if ($low == $high)
    {
        echo "The required element is ",
                             $arr[$low];
        return;
    }
 
    // Find the middle point
    $mid = ($low + $high) / 2;
 
    // If mid is even and element
    // next to mid is same as mid,
    // then output element lies on
    // right side, else on left side
    if ($mid % 2 == 0)
    {
        if ($arr[$mid] == $arr[$mid + 1])
            search($arr, $mid + 2, $high);
        else
            search($arr, $low, $mid);
    }
     
    // If mid is odd
    else
    {
        if ($arr[$mid] == $arr[$mid - 1])
            search($arr, $mid + 1, $high);
        else
            search($arr, $low, $mid - 1);
    }
}
 
// Driver Code
$arr = array(1, 1, 2, 2, 1, 1, 2,
             2, 13, 1, 1, 40, 40);
$len = count($arr);;
search($arr, 0, $len - 1);
 
// This code is contributed by anuj_67.
?>


Javascript


输出 :

The required element is 13

时间复杂度: O(Log n)