我正在尝试编写一个算法来查找单链表的交集。对于这个问题,交集的节点实际上不必是相同的节点对象(即它不必是相同的内存位置),列表只需要从交叉点的节点具有完全相同的值。列表的结尾。我已经在立方时间内为此编写了一个非常低效的算法。我确信有一个更好的,可能是递归的方式来做到这一点,但我无法弄明白。有什么想法吗?
对于此问题,两个列表的交集是两个列表中所有后续值完全相同的值。例如,给定: 清单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;
}
答案 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)
现在遍历两个列表并继续比较元素值
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;
}
}