c# - 为什么对象的值会发生变化,即使它有不同的引用?
问题描述
我对这里的对象引用感到困惑。合并 2 个已排序的链表是 LC 问题。
我知道在第一次迭代current.next
时引用了同一个对象,所以当我为值更改result
分配新值时。current.next
result
在第二次迭代中 r1 和 r2 都是假的,所以result, current and current.next
指向不同的对象。
我不明白为什么为 current ( 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
, so current = [1,2,4]
,所以我们修改 current 但这次结果没有改变。
解决方案
结果和当前指向不同的对象,当当前更改结果时仍然如此。结果如何保持对当前的参考?
看看你问题的这一部分:
所以
current = [1,3,4]
,它不再指向结果。
重要的是1
,该列表的 in与in的元素相同。如果您修改该节点的字段,您将修改该节点所属的任何列表。包括引用的列表。1
result = [0,1,3,4]
next
1
result
稍后当你写:
此时我们有:
result = [0,1,1,2,4], current = [1,1,2,4], l2 = [3,4], l1 = [2,4]
请注意,列表result
指向与列表current
指向不同。但是在第一个节点之后,它是相同的。
在第一次迭代之后,result.next
引用相同的对象current
。这是因为result
andcurrent
开始于引用同一个对象,然后作为第一次迭代的最后一步,current
更改为 reference current.next
。因为current
和result
当时是一样的,current.next
而且result.next
也是一样的。所以改成 之后current
,current.next
就和设置成一样了result.next
。
所以在第二次迭代中,result.next
和current
都是一样的。这意味着当您修改时current.next
,这与修改相同result.next.next
,其效果是将result
列表中前两个元素之外的内容替换为l2
引用的新元素链。
再说一遍:这里的关键是每个变量都只指向一个节点。可以将其概念化为指向节点列表,但前提是您要记住,如果您修改该next
列表中任何节点的字段,那么您就是在修改整个列表,即使该变量没有引用引用的变量列表的根。
推荐阅读
- java - 为什么我的“Set-Cookie”响应标头没有被翻译成实际的 cookie?
- javascript - 使用原生 JavaScript 操作 CSS 类
- php - Mysql 使用 MATCH() AGAINST() 搜索字符串和数字不起作用
- java - 如何显示来自需要两个 URL 的 API 的信息?
- mysql - Woocommerce - 自定义 MySQL 查询 - 获取具有多个分类值的产品
- jsp - 春季启动jsp:java.lang.NoClassDefFoundError:org/apache/tomcat/util/security/Escape
- r - 平行坐标图
- jquery - Select2 - 自动选择动态相关下拉框
- sql-server - SQL Server 包含部分
- python - Tensorflow Print 修复形状问题?