You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python检测等价类:给定两个数字列表的最优实现方法

Fast Equivalence Class Detection for Two Numeric Lists in Python

Alright, let's break down how to solve this equivalence class problem efficiently. The key insight here is that elements from both lists are in the same equivalence class if they're connected through their paired positions. For example, if list1[i] is paired with list2[i], those two elements belong to the same group—and any elements linked via these pairs join that group too.

Take your sample input:

  • list1 = [1,1,2,3,3,4]
  • list2 = [5,6,7,7,8,6]

Each index creates a pair: (1,5), (1,6), (2,7), (3,7), (3,8), (4,6). Mapping these connections gives us two connected components: {1,5,6,4} and {2,7,3,8}, which matches your expected eqClasses.

The Fastest Approach: Union-Find (Disjoint Set Union, DSU)

The Union-Find data structure is hands down the fastest way to solve this. It's optimized for merging sets and finding the root of an element, with nearly constant time operations thanks to path compression (we'll use that here for simplicity, which already delivers great performance).

Step-by-Step Implementation

First, let's code the Union-Find class:

class UnionFind:
    def __init__(self):
        self.parent = {}
    
    def find(self, x):
        # Path compression: flatten the structure to speed up future queries
        if self.parent[x] != x:
            self.parent[x] = self.find(self.parent[x])
        return self.parent[x]
    
    def union(self, x, y):
        # Add elements to the structure if they're not already present
        if x not in self.parent:
            self.parent[x] = x
        if y not in self.parent:
            self.parent[y] = y
        
        # Find roots of both elements
        x_root = self.find(x)
        y_root = self.find(y)
        
        # Merge the two sets if they're separate
        if x_root != y_root:
            self.parent[y_root] = x_root

Then, the main function to generate equivalence classes:

def get_equivalence_classes(list1, list2):
    if len(list1) != len(list2):
        raise ValueError("Both lists must be the same length!")
    
    uf = UnionFind()
    
    # Union each pair of elements from the two lists
    for a, b in zip(list1, list2):
        uf.union(a, b)
    
    # Group elements by their root parent
    equivalence_classes = {}
    for elem in uf.parent:
        root = uf.find(elem)
        if root not in equivalence_classes:
            equivalence_classes[root] = []
        equivalence_classes[root].append(elem)
    
    # Convert the dictionary values to a list of lists
    return list(equivalence_classes.values())

Test It Out

Let's run your sample input to verify:

list1 = [1,1,2,3,3,4]
list2 = [5,6,7,7,8,6]
print(get_equivalence_classes(list1, list2))
# Output: [[1,5,6,4], [2,7,3,8]] (order of classes or elements inside classes may vary, which is fine for equivalence classes)

Why This Is the Fastest Method

  • Time Complexity: O(n α(n)), where n is the length of the lists. The inverse Ackermann function α(n) grows so slowly that it's effectively a constant for all practical input sizes (it never exceeds 4 for n up to 10^600). This beats any hash-based approach that requires multiple passes or complex key generation.
  • Space Complexity: O(k), where k is the number of unique elements across both lists—super efficient for most use cases.

If you don't want to write a custom Union-Find class, you could use a dictionary with path compression directly, but the class makes the code cleaner and more maintainable.

内容的提问来源于stack exchange,提问作者Ahti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 09:10:58