查找两个 LinkedLists 的合并点:运行 时间错误
Find the merge point of two LinkedLists : Run time error
我写了找到两个链表的合并点的代码,但是在大多数测试用例中,hackerrank 抛出 运行 时间错误,我只是想知道是什么原因造成的。下面是我的代码:
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
,所以这里return输入了错误的数据。在后面类似的 if
块中也犯了同样的错误。
if(node1 ==node2){
return 0;
}
上面的if
明明是一个合并点,但是错误的是return0.应该returnnode1.data
.
if(node1 ==null || node2==null){
return 0;
}
以上代码意味着没有合并点。鉴于挑战承诺存在合并点,这种情况永远不会发生。
while(node1 !=null && node2 !=null){
node1=node1.next;
node2=node2.next;
if(node1==node2){
break;
}
}
上面的while
循环假定到合并点的距离在两个列表中是相同的,但你不能这样假定。可能是第一个列表在其第 6th 个节点处具有合并点,而该节点只是第二个列表中的第 3rd 个。所以 while
循环会在不知不觉中越过合并点。
然后在循环之后你有:
return node1.data;
但是 while
循环结束的可能性大约为 50%,因为 node1
变成了 null
。如果发生这种情况,表达式 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;
}
我写了找到两个链表的合并点的代码,但是在大多数测试用例中,hackerrank 抛出 运行 时间错误,我只是想知道是什么原因造成的。下面是我的代码:
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
,所以这里return输入了错误的数据。在后面类似的 if
块中也犯了同样的错误。
if(node1 ==node2){
return 0;
}
上面的if
明明是一个合并点,但是错误的是return0.应该returnnode1.data
.
if(node1 ==null || node2==null){
return 0;
}
以上代码意味着没有合并点。鉴于挑战承诺存在合并点,这种情况永远不会发生。
while(node1 !=null && node2 !=null){
node1=node1.next;
node2=node2.next;
if(node1==node2){
break;
}
}
上面的while
循环假定到合并点的距离在两个列表中是相同的,但你不能这样假定。可能是第一个列表在其第 6th 个节点处具有合并点,而该节点只是第二个列表中的第 3rd 个。所以 while
循环会在不知不觉中越过合并点。
然后在循环之后你有:
return node1.data;
但是 while
循环结束的可能性大约为 50%,因为 node1
变成了 null
。如果发生这种情况,表达式 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;
}