如何找到单链表的交集

时间:2015-09-23 23:14:07

标签: algorithm linked-list

我正在尝试编写一个算法来查找单链表的交集。对于这个问题,交集的节点实际上不必是相同的节点对象(即它不必是相同的内存位置),列表只需要从交叉点的节点具有完全相同的值。列表的结尾。我已经在立方时间内为此编写了一个非常低效的算法。我确信有一个更好的,可能是递归的方式来做到这一点,但我无法弄明白。有什么想法吗?

对于此问题,两个列表的交集是两个列表中所有后续值完全相同的值。例如,给定: 清单1 = {1,3,5,6,4,12} 清单2 = {8,9,6,4,12} 该算法应返回6.

这是我当前的解决方案:我查看每个列表中的常用元素,当我找到一个时,我会检查列表是否与该元素相同。

public static boolean compareFrom(Node a, Node b) {
    Node current1 = a, current2 = b;
    while (current1 != null) {
        if (current2 == null
                || !(current1.getElem().equals(current2.getElem()))) {
            return false;
        }
        current1 = current1.getNext();
        current2 = current2.getNext();
    }
    if (current2 == null)
        return true;
    return false;
}

public static Node intersection(SinglyLinkedList list1,
        SinglyLinkedList list2) {
    Node current1 = list1.head, current2 = list2.head;
    while (current1 != null) {
        while (current2 != null) {
            if (current1.getElem().equals(current2.getElem())
                    && compareFrom(current1, current2))
                return current1;
            else
                current2 = current2.getNext();
        }
        current2 = list2.head;
        current1 = current1.getNext();
    }
    return null;
}

2 个答案:

答案 0 :(得分:4)

  

我确信有更好的,可能是递归的方式来做到这一点,但我无法弄明白。有什么想法吗?

我在O(n)时间构建一个反向列表,然后再次在O(n)时间检查两个列表中的成对元素。

(或者如果您将列表存储在两个向量中,则可以首先将[m-i]和b [n​​-i]与i从1比较到m和n之间的最小值):

 {1, 3, 5, 6, 4, 12} and {8, 9, 6, 4, 12}
 x := -1
 a[5] = b[4] = 12 so x := 12
 a[4] = b[3] = 4 so x := 4
 a[3] = b[2] = 6 so x := 6
 a[2] != b[1] so break

交叉口是6。

没有其他结构

我们可以扫描两个列表。

首先,我们需要“同步”两个列表,即O(n),然后我们获得A和B的列表深度。

有了这个号码,我们会根据适当数量的位置推进更长的列表。如果我们有A 7个元素,B有4个,我们将A推进3。我们知道在第三个之前A的任何元素都不可能是一个交集,因为A子链将比整个B更长。

i = 0。

现在我们比较A'的第一个可用元素,让我们将它称为A'(i),使用B,B(i)的第一个可用元素。

如果他们是平等的,那么A'(i)是候选人成为一个交集,但我们还不能确定。

我们推进A'和B并获取A'(i + 1)和B(i + 1)。

如果我们得到另一场相同的比赛,我们什么都不做:我们的第一位候选人仍然很强大。

如果我们得到匹配,那么我们的候选人就无法生效,我们将其丢弃,将cand设置为NULL。

循环。

最后,我们将进行比反向列表方法更多的比较,但是我们要么是NULL,要么是最新元素,它是公共链的头部

答案 1 :(得分:0)

  1. 查找两个列表的长度 - 0(n)
  2. 遍历较长的列表,直到这些长度的差异
  3. 现在遍历两个列表并继续比较元素值

    public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    
    int first = 0, second = 0;
    if (headA == null || headB == null) return null;
    ListNode temp = headA;
    first  = findLen(headA);
    second  = findLen(headB);
    
    if (first > second){
        return findIntersection(headA, headB, first-second);
    }
    return findIntersection(headB, headA, second-first);
    
    }
    
    public ListNode findIntersection(ListNode longerList, ListNode shorterList, int diff){
    
    while(diff != 0){
        longerList = longerList.next;
        diff--;
    }
    
    while (longerList != null){
        if (longerList == shorterList) return longerList;
        longerList = longerList.next;
        shorterList = shorterList.next;
    }
    return null;
    }
    
    public int findLen(ListNode a){
    int len = 0;
    while (a != null){
        len++;
        a = a.next;
    }
    return len;
    }
    

    }

相关问题