📌  相关文章
📜  在 O(NlogN) 中的所有子数组上查找所有唯一的最大和第二最大元素对

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

在 O(NlogN) 中的所有子数组上查找所有唯一的最大和第二最大元素对

(a, b) 分别表示数组的第二个最大值和最大元素的有序对。我们需要在给定数组的整个连续子数组中找到所有这些唯一对。

例子:

蛮力方法

  • 解决此问题的一种简单方法是扫描每个子数组并找到该子数组中的最大和第二大元素
  • 这可以在O(N^2)          时间
  • 然后我们可以将每一对插入一个集合中以确保删除重复项,然后打印它们
  • 每次插入操作成本O(log(N)) ,将最终的复杂度推到O(N^2log(N))
C++14
// C++ implementation
#include 
using namespace std;
 
// Function to return the set of pairs
set > pairs(vector& arr)
{
    set > pairs;
 
    // find all subarrays
    for (int i = 0; i < arr.size() - 1; ++i) {
        int maximum = max(arr[i], arr[i + 1]),
            secondmax = min(arr[i], arr[i + 1]);
 
        for (int j = i + 1; j < arr.size(); ++j) {
            // update max and second max
            if (arr[j] > maximum) {
                secondmax = maximum;
                maximum = arr[j];
            }
            if (arr[j] < maximum && arr[j] > secondmax) {
                secondmax = arr[j];
            }
 
            // insert a pair in set
            pairs.insert(make_pair(secondmax, maximum));
        }
    }
    return pairs;
}
 
int main()
{
    vector vec = { 1, 2, 6, 4, 5 };
 
    set > st = pairs(vec);
    cout << "Total Number of valid pairs is :"
         << (int)st.size() << "\n";
    for (auto& x : st) {
        cout << "(" << x.first << ", " << x.second << ") ";
    }
    return 0;
}


Java
// Java implementation
import java.util.HashSet;
import java.util.Set;
 
class Pair implements Comparable {
    int first, second;
 
    public Pair(int first, int second)
    {
        this.first = first;
        this.second = second;
    }
 
    @Override public int hashCode()
    {
        return 31 * first + second;
    }
 
    public boolean equals(Object p)
    {
        Pair pair = (Pair)p;
 
        if (this.first != pair.first)
            return false;
 
        return this.second == pair.second;
    }
 
    @Override public int compareTo(Pair p)
    {
        if (this.first == p.first) {
            return this.second - p.second;
        }
        return this.first - p.first;
    }
}
 
class GFG {
 
    // Function to return the set of pairs
    static Set pairs(int[] arr)
    {
        Set pairs = new HashSet<>();
 
        // Find all subarrays
        for (int i = 0; i < arr.length - 1; ++i) {
            int maximum = Math.max(arr[i], arr[i + 1]),
                secondmax = Math.min(arr[i], arr[i + 1]);
 
            for (int j = i + 1; j < arr.length; ++j) {
 
                // Update max and second max
                if (arr[j] > maximum) {
                    secondmax = maximum;
                    maximum = arr[j];
                }
                if (arr[j] < maximum
                    && arr[j] > secondmax) {
                    secondmax = arr[j];
                }
 
                // Insert a pair in set
                pairs.add(new Pair(secondmax, maximum));
            }
        }
        return pairs;
    }
 
    // Driver Code
    public static void main(String[] args)
    {
        int[] vec = { 1, 2, 6, 4, 5 };
 
        Set st = pairs(vec);
        System.out.println("Total Number of "
                           + "valid pairs is :"
                           + st.size());
 
        for (Pair x : st) {
            System.out.printf("(%d, %d)\n", x.first,
                              x.second);
        }
    }
}
 
// This code is contributed by sanjeev2552


Python3
# python3 implementation
 
# Function to return the set of pairs
def SetofPairs(arr):
 
    pairs = set()
    n = len(arr)     # length of array
     
    # find all subarrays
    for i in range(n - 1):
        maximum = max(arr[i], arr[i + 1])
        secondmax = min(arr[i], arr[i + 1])
        for j in range(i + 1, n):
 
            # update max and second max
            if (arr[j] > maximum):
                secondmax = maximum
                maximum = arr[j]
            if (arr[j] < maximum and arr[j] > secondmax):
                secondmax = arr[j]
 
            # add a pair in set
            pairs.add((secondmax, maximum))
    return pairs
 
# Driver code
if __name__ == "__main__":
 
    vec = [1, 2, 6, 4, 5]
    st = SetofPairs(vec)
    print("Total Number of valid pairs is :", len(st))
 
    for x in st:
        print(x, end = " ")
 
        # This code is contributed by sunilsoni10220001022000.


Javascript


C++
// C++ implementation of the above approach
#include 
using namespace std;
 
// Function to return the set of pairs
set>
     pairs(vector& arr)
{
    stack st;
    set> pairs;
 
    // Push first element into stack
    st.push(arr[0]);
 
    // For each element 'X' in arr,
    // pop the stack while top Element
    // is smaller than 'X' and form a pair.
    // If the stack is not empty after
    // the previous operation, create
    // a pair. Push X into the stack.
 
    for (int i = 1; i < arr.size(); ++i) {
        while (!st.empty() &&
                arr[i] > st.top()) {
            pairs.insert(make_pair(st.top(),
                                    arr[i]));
            st.pop();
        }
        if (!st.empty()) {
            pairs.insert(make_pair(min(st.top(),
                                       arr[i]),
                                   max(st.top(),
                                      arr[i])));
        }
        st.push(arr[i]);
    }
    return pairs;
}
 
int main()
{
    vector vec = { 1, 2, 6, 4, 5 };
 
    set > st = pairs(vec);
    cout << "Total Number of valid pairs is :"
                   << (int)st.size() << "\n";
    for (auto& x : st) {
        cout << "(" << x.first << ", "
                       << x.second << ") ";
    }
    return 0;
}


Java
// Java implementation of the above approach
import java.util.*;
 
class GFG{
     
static class pair
{
    int first, second;
     
    public pair(int first, int second) 
    {
        this.first = first;
        this.second = second;
    }
     
    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + first;
        result = prime * result + second;
        return result;
    }
     
    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
             
        pair other = (pair) obj;
        if (first != other.first)
            return false;
        if (second != other.second)
            return false;
        return true;
    } 
}
 
// Function to return the set of pairs
static HashSet pairs(int[] arr)
{
    Stack st = new Stack();
    HashSet pairs = new HashSet();
     
    // Push first element into stack
    st.add(arr[0]);
     
    // For each element 'X' in arr,
    // pop the stack while top Element
    // is smaller than 'X' and form a pair.
    // If the stack is not empty after
    // the previous operation, create
    // a pair. Push X into the stack.
    for(int i = 1; i < arr.length; ++i)
    {
        while (!st.isEmpty() && arr[i] > st.peek())
        {
            pairs.add(new pair(st.peek(),
                               arr[i]));
            st.pop();
        }
        if (!st.isEmpty())
        {
            pairs.add(new pair(Math.min(st.peek(),
                                        arr[i]),
                               Math.max(st.peek(),
                                        arr[i])));
        }
        st.add(arr[i]);
    }
    return pairs;
}
 
// Driver code
public static void main(String[] args)
{
    int [] vec = { 1, 2, 6, 4, 5 };
 
    HashSet st = pairs(vec);
    System.out.print("Total Number of valid pairs is :"  +
                     (int)st.size() + "\n");
    for(pair x : st)
    {
        System.out.print("(" +  x.first+ ", " +
                                x.second + ") ");
    }
}
}
 
// This code is contributed by 29AjayKumar


Python3
# Python3 implementation of the above approach
 
# Function to return the set of pairs
def pairs(arr) :
 
    st = [];
    pairs = [];
 
    # Push first element into stack
    st.append(arr[0]);
 
    # For each element 'X' in arr,
    # pop the stack while top Element
    # is smaller than 'X' and form a pair.
    # If the stack is not empty after
    # the previous operation, create
    # a pair. Push X into the stack.
    for i in range(1, len(arr) ) :
        while len(st) != 0 and arr[i] > st[-1] :
            pairs.append((st[-1], arr[i]));
            st.pop();
     
        if len(st) != 0 :
            pairs.append((min(st[-1], arr[i]),
                        max(st[-1], arr[i])));
         
        st.append(arr[i]);
     
    return pairs;
 
# Driver code
if __name__ == "__main__" :
 
    vec = [ 1, 2, 6, 4, 5 ];
    st = pairs(vec);
    print("Total Number of valid pairs is :",len(st));
     
    for x in st :
        print("(" ,x[0], ", ",x[1], ")",end=" ");
 
# This code is contributed by AnkitRai01


输出:

Total Number of valid pairs is :5
(1, 2) (2, 6) (4, 5) (4, 6) (5, 6)

复杂性分析:

  • 时间复杂度: O(N^2 log(N))。
    在集合中插入需要 log N 时间。最多可以有 N^2 个子数组。所以时间复杂度是 O(N^2 log N)。
  • 辅助空间: O(n^2)。
    因为需要额外的空间来存储集合中的元素。

有效的方法

  • 它可以降低寻找配对的复杂性O(N) 通过观察一个元素X只能与元素形成对,直到最右边的元素大于X          .
  • 要了解为什么会这样,请考虑X = 4在下一个示例中。
Arr = {1, 4, 5, 3, 2, 1}
  • 它可以看到5 > 4 是离右边最近的大于4 . (4, 5)考虑子阵列形成一对[4, 5]          .
  • 其他子数组,以4 必须包括5 .考虑其中一个,如果另一个元素Y >=5 存在于子数组中,则(5, Y)   将是该子阵列的对。
  • 否则(4, 5)将形成或(Z, 5) 将形成,其中Z是右边的最大元素5 在子阵中。
  • 在任何情况下, 4 不能与右边的任何元素形成对5          .
  • 使用这个观察,我们可以使用堆栈来实现逻辑,这将生成对的复杂度降低到O(N)          .
  • 每对都可以插入到一个集合中以消除重复,最终的时间复杂度为O(Nlog(N))

下面是上述方法的实现:

C++

// C++ implementation of the above approach
#include 
using namespace std;
 
// Function to return the set of pairs
set>
     pairs(vector& arr)
{
    stack st;
    set> pairs;
 
    // Push first element into stack
    st.push(arr[0]);
 
    // For each element 'X' in arr,
    // pop the stack while top Element
    // is smaller than 'X' and form a pair.
    // If the stack is not empty after
    // the previous operation, create
    // a pair. Push X into the stack.
 
    for (int i = 1; i < arr.size(); ++i) {
        while (!st.empty() &&
                arr[i] > st.top()) {
            pairs.insert(make_pair(st.top(),
                                    arr[i]));
            st.pop();
        }
        if (!st.empty()) {
            pairs.insert(make_pair(min(st.top(),
                                       arr[i]),
                                   max(st.top(),
                                      arr[i])));
        }
        st.push(arr[i]);
    }
    return pairs;
}
 
int main()
{
    vector vec = { 1, 2, 6, 4, 5 };
 
    set > st = pairs(vec);
    cout << "Total Number of valid pairs is :"
                   << (int)st.size() << "\n";
    for (auto& x : st) {
        cout << "(" << x.first << ", "
                       << x.second << ") ";
    }
    return 0;
}

Java

// Java implementation of the above approach
import java.util.*;
 
class GFG{
     
static class pair
{
    int first, second;
     
    public pair(int first, int second) 
    {
        this.first = first;
        this.second = second;
    }
     
    @Override
    public int hashCode()
    {
        final int prime = 31;
        int result = 1;
        result = prime * result + first;
        result = prime * result + second;
        return result;
    }
     
    @Override
    public boolean equals(Object obj)
    {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
             
        pair other = (pair) obj;
        if (first != other.first)
            return false;
        if (second != other.second)
            return false;
        return true;
    } 
}
 
// Function to return the set of pairs
static HashSet pairs(int[] arr)
{
    Stack st = new Stack();
    HashSet pairs = new HashSet();
     
    // Push first element into stack
    st.add(arr[0]);
     
    // For each element 'X' in arr,
    // pop the stack while top Element
    // is smaller than 'X' and form a pair.
    // If the stack is not empty after
    // the previous operation, create
    // a pair. Push X into the stack.
    for(int i = 1; i < arr.length; ++i)
    {
        while (!st.isEmpty() && arr[i] > st.peek())
        {
            pairs.add(new pair(st.peek(),
                               arr[i]));
            st.pop();
        }
        if (!st.isEmpty())
        {
            pairs.add(new pair(Math.min(st.peek(),
                                        arr[i]),
                               Math.max(st.peek(),
                                        arr[i])));
        }
        st.add(arr[i]);
    }
    return pairs;
}
 
// Driver code
public static void main(String[] args)
{
    int [] vec = { 1, 2, 6, 4, 5 };
 
    HashSet st = pairs(vec);
    System.out.print("Total Number of valid pairs is :"  +
                     (int)st.size() + "\n");
    for(pair x : st)
    {
        System.out.print("(" +  x.first+ ", " +
                                x.second + ") ");
    }
}
}
 
// This code is contributed by 29AjayKumar

Python3

# Python3 implementation of the above approach
 
# Function to return the set of pairs
def pairs(arr) :
 
    st = [];
    pairs = [];
 
    # Push first element into stack
    st.append(arr[0]);
 
    # For each element 'X' in arr,
    # pop the stack while top Element
    # is smaller than 'X' and form a pair.
    # If the stack is not empty after
    # the previous operation, create
    # a pair. Push X into the stack.
    for i in range(1, len(arr) ) :
        while len(st) != 0 and arr[i] > st[-1] :
            pairs.append((st[-1], arr[i]));
            st.pop();
     
        if len(st) != 0 :
            pairs.append((min(st[-1], arr[i]),
                        max(st[-1], arr[i])));
         
        st.append(arr[i]);
     
    return pairs;
 
# Driver code
if __name__ == "__main__" :
 
    vec = [ 1, 2, 6, 4, 5 ];
    st = pairs(vec);
    print("Total Number of valid pairs is :",len(st));
     
    for x in st :
        print("(" ,x[0], ", ",x[1], ")",end=" ");
 
# This code is contributed by AnkitRai01
输出:
Total Number of valid pairs is :5
(1, 2) (2, 6) (4, 5) (4, 6) (5, 6)

复杂性分析:

  • 时间复杂度: O(N log(N))。
    每对都可以插入到一个集合中以消除重复,最终时间复杂度为 O(N log N)
  • 辅助空间: O(N)。
    因为需要额外的空间来存储集合中的元素。