为什么对象的值会发生变化,即使它具有不同的引用?
Why object's value changes even though it has different references?
我对这里的对象引用感到困惑。合并2个排序链表是LC问题
我知道在第一次迭代时 current.next
和 result
引用了同一个对象,所以当我将新值分配给 current.next
时,result
值也会发生变化。
在第二次迭代时,r1 和 r2 均为假,因此 result, current and current.next
指向不同的对象。
我不明白的是为什么为当前 (current = current.next
) 分配新值不会修改结果对象但 current.next = l1/l2
会?
有人可以给我解释一下吗?
public static ListNode MergeTwoLists(ListNode l1, ListNode l2)
{
if (l1 == null) return l2;
if (l2 == null) return l1;
if (l2 == null && l1 == null) return null;
ListNode result = new ListNode(0);
ListNode current = result;
while (l1 != null && l2 != null)
{
var r1 = Object.ReferenceEquals(result, current);
var r2 = Object.ReferenceEquals(result, current.next);
if (l1.val < l2.val)
{
current.next = l1;
l1 = l1.next;
}
else
{
current.next = l2;
l2 = l2.next;
}
current = current.next;
}
// l1 is lognger than l2
if(l1 != null)
{
current.next = l1;
l1 = l1.next;
}
// l2 is lognger than l1
if (l2 != null)
{
current.next = l2;
l2 = l2.next;
}
return result.next;
}
public class ListNode
{
public int val;
public ListNode next;
public ListNode(int x = 0, ListNode next = null)
{
val = x;
next = null;
}
}
编辑
假设我们有这些:
Input: l1 = [1,2,4], l2 = [1,3,4] Output: [1,1,2,3,4,4]
第一次迭代:
r1 = true
,结果和当前都指向同一个对象。
r2 = false
l1.val == l2.val
所以我们执行
else
{
current.next = l2;
l2 = l2.next;
}
此刻我们有:
result = [0,1,3,4]
、current = [0,1,3,4], l2 = [3,4]
接下来我们执行 current = current.next
,所以 current = [1,3,4]
它不再指向结果。
第二次迭代
r1 = false
,结果和当前指向不同的对象。
r2 = false
,
l1.val < l2.val
所以我们执行
if (l1.val < l2.val)
{
current.next = l1;
l1 = l1.next;
}
此刻我们有:
result = [0,1,1,2,4], current = [1,1,2,4], l2 = [3,4], l1 = [2,4]
这是我不明白的部分:结果和当前指向不同的对象,但当前更改结果也是如此。结果如何保持对当前的引用??
接下来我们执行current = current.next
,所以current = [1,2,4]
,所以我们修改current但是这次结果没有改变。
您永远不应将 current.next
分配给 l1
或 l2
中的节点。相反,您必须创建一个与 l1
或 l2
具有相同值的新 ListNode
,并使 current.next
指向您的新 ListNode
。否则,你正试图拉直一碗意大利面,这是一项不可能完成的任务。你需要制作你自己的新意大利面条。
Result and current point to diffrent objects, still when current changes result does as well. How result keeps reference to current?
看看你问题的这一部分:
so current = [1,3,4]
and it doesn't point to result anymore.
重要的是,该列表 中的 1
与 result = [0,1,3,4]
中的 1
是相同的元素 。如果您修改 1
节点的 next
字段,您将修改该节点所属的任何列表。包括 result
正在引用的列表。
稍后您写:
At this moment we have:
result = [0,1,1,2,4], current = [1,1,2,4], l2 = [3,4], l1 = [2,4]
请注意 result
指向的列表 与 current
指向的列表 不同。但是在第一个节点之后, 是一样的。
第一次迭代后,result.next
引用了与 current
相同的对象。这是因为 result
和 current
开始引用同一个对象,然后作为第一次迭代的最后一步, current
被更改为引用 current.next
。因为 current
和 result
在那个点上是一样的,所以 current.next
和 result.next
也是一样的。所以把current
改成current.next
后,就和设置成result.next
一样了。
所以在第二次迭代中,result.next
和 current
是相同的。这意味着当您修改 current.next
时,这与修改 result.next.next
相同,其效果是用新链替换 result
列表中前两个元素之外的内容l2
引用的元素。
同样:这里的关键是每个变量都简单地指向一个节点。可以将其概念化为指向节点列表,但前提是您要记住,如果您修改该列表中任何节点的 next
字段,即使变量未引用,您也会修改整个列表引用列表根的变量。
我对这里的对象引用感到困惑。合并2个排序链表是LC问题
我知道在第一次迭代时 current.next
和 result
引用了同一个对象,所以当我将新值分配给 current.next
时,result
值也会发生变化。
在第二次迭代时,r1 和 r2 均为假,因此 result, current and current.next
指向不同的对象。
我不明白的是为什么为当前 (current = current.next
) 分配新值不会修改结果对象但 current.next = l1/l2
会?
有人可以给我解释一下吗?
public static ListNode MergeTwoLists(ListNode l1, ListNode l2)
{
if (l1 == null) return l2;
if (l2 == null) return l1;
if (l2 == null && l1 == null) return null;
ListNode result = new ListNode(0);
ListNode current = result;
while (l1 != null && l2 != null)
{
var r1 = Object.ReferenceEquals(result, current);
var r2 = Object.ReferenceEquals(result, current.next);
if (l1.val < l2.val)
{
current.next = l1;
l1 = l1.next;
}
else
{
current.next = l2;
l2 = l2.next;
}
current = current.next;
}
// l1 is lognger than l2
if(l1 != null)
{
current.next = l1;
l1 = l1.next;
}
// l2 is lognger than l1
if (l2 != null)
{
current.next = l2;
l2 = l2.next;
}
return result.next;
}
public class ListNode
{
public int val;
public ListNode next;
public ListNode(int x = 0, ListNode next = null)
{
val = x;
next = null;
}
}
编辑
假设我们有这些:
Input: l1 = [1,2,4], l2 = [1,3,4] Output: [1,1,2,3,4,4]
第一次迭代:
r1 = true
,结果和当前都指向同一个对象。
r2 = false
l1.val == l2.val
所以我们执行
else
{
current.next = l2;
l2 = l2.next;
}
此刻我们有:
result = [0,1,3,4]
、current = [0,1,3,4], l2 = [3,4]
接下来我们执行 current = current.next
,所以 current = [1,3,4]
它不再指向结果。
第二次迭代
r1 = false
,结果和当前指向不同的对象。
r2 = false
,
l1.val < l2.val
所以我们执行
if (l1.val < l2.val)
{
current.next = l1;
l1 = l1.next;
}
此刻我们有:
result = [0,1,1,2,4], current = [1,1,2,4], l2 = [3,4], l1 = [2,4]
这是我不明白的部分:结果和当前指向不同的对象,但当前更改结果也是如此。结果如何保持对当前的引用??
接下来我们执行current = current.next
,所以current = [1,2,4]
,所以我们修改current但是这次结果没有改变。
您永远不应将 current.next
分配给 l1
或 l2
中的节点。相反,您必须创建一个与 l1
或 l2
具有相同值的新 ListNode
,并使 current.next
指向您的新 ListNode
。否则,你正试图拉直一碗意大利面,这是一项不可能完成的任务。你需要制作你自己的新意大利面条。
Result and current point to diffrent objects, still when current changes result does as well. How result keeps reference to current?
看看你问题的这一部分:
so
current = [1,3,4]
and it doesn't point to result anymore.
重要的是,该列表 中的 1
与 result = [0,1,3,4]
中的 1
是相同的元素 。如果您修改 1
节点的 next
字段,您将修改该节点所属的任何列表。包括 result
正在引用的列表。
稍后您写:
At this moment we have:
result = [0,1,1,2,4], current = [1,1,2,4], l2 = [3,4], l1 = [2,4]
请注意 result
指向的列表 与 current
指向的列表 不同。但是在第一个节点之后, 是一样的。
第一次迭代后,result.next
引用了与 current
相同的对象。这是因为 result
和 current
开始引用同一个对象,然后作为第一次迭代的最后一步, current
被更改为引用 current.next
。因为 current
和 result
在那个点上是一样的,所以 current.next
和 result.next
也是一样的。所以把current
改成current.next
后,就和设置成result.next
一样了。
所以在第二次迭代中,result.next
和 current
是相同的。这意味着当您修改 current.next
时,这与修改 result.next.next
相同,其效果是用新链替换 result
列表中前两个元素之外的内容l2
引用的元素。
同样:这里的关键是每个变量都简单地指向一个节点。可以将其概念化为指向节点列表,但前提是您要记住,如果您修改该列表中任何节点的 next
字段,即使变量未引用,您也会修改整个列表引用列表根的变量。