我已经编写了找到两个linkedList的合并点的代码,但在大多数测试案例中,hackerlink会抛出运行时错误,我只想知道是什么原因造成的。下面是我的代码:
static int findMergeNode(SinglyLinkedListNode head1, SinglyLinkedListNode head2) {
SinglyLinkedListNode node1 = head1;
SinglyLinkedListNode node2 = head2;
if(node1.next == node2){
return node1.data;
}
else if(node2.next==node1){
return node2.data;
}
if(node1 ==node2){
return 0;
}
if(node1 ==null || node2==null){
return 0;
}
while(node1 !=null && node2 !=null){
node1=node1.next;
node2=node2.next;
if(node1==node2){
break;
}
}
return node1.data;
}
有几个问题:
if(node1.next == node2){
return node1.data;
}
如果上述条件确实成立,则合并点不是node1
,而是node2
,因此此处返回错误的数据。在随后的类似CCD_ 3块中也出现了相同的错误。
if(node1 ==node2){
return 0;
}
上面的if
清楚地标识了一个合并点,但返回0是错误的。它应该返回node1.data
。
if(node1 ==null || node2==null){
return 0;
}
上面的代码意味着没有合并点。考虑到这一挑战意味着有一个合并点,这种情况永远不会发生。
while(node1 !=null && node2 !=null){
node1=node1.next;
node2=node2.next;
if(node1==node2){
break;
}
}
上面的while
循环假设两个列表中到合并点的距离相同,但不能这样假设。可能是第一个列表的合并点在其第6个节点上,而该节点在第二个列表中仅为第3rd。因此while
循环将在没有注意到合并点的情况下通过合并点
然后在循环之后:
return node1.data;
但由于node1
变成null
,while
循环结束的概率大约为50%。如果发生这种情况,表达式node1.data
将触发一个异常,这就是您看到的情况。
作为一个结论,我们可以说你的算法不够好,不能胜任这项任务。
解决方案
有几种方法可以实现这一点,但其中一种方法是首先计算第一个列表和第二个列表中的节点数。如果其中一个比另一个长,那么您已经可以从最长的列表中删除前几个节点,这样您只剩下两个同样长的列表。在那个时刻,您的while
循环将完成这项工作,因此您可以确保在两个列表中到合并点的距离相同。
以下是建议的代码:
// Helper function to count the number of nodes in a given list:
static int size(SinglyLinkedListNode head) {
int size = 0;
while (head != null) {
head = head.next;
size++;
}
return size;
}
static int findMergeNode(SinglyLinkedListNode head1, SinglyLinkedListNode head2) {
// Get the difference in list's sizes
int sizeDiff = size(head1) - size(head2);
// Dismiss the first node(s) from the longest list until they have an equal size:
while (sizeDiff < 0) {
head2 = head2.next;
sizeDiff++;
}
while (sizeDiff > 0) {
head1 = head1.next;
sizeDiff--;
}
// compare the remaining nodes in tandem.
while (head1 != head2) {
head1 = head1.next;
head2 = head2.next;
}
return head1.data;
}