Algorithm
回文链表
/**
* Definition for singly-linked list.
* public class ListNode {
* int val;
* ListNode next;
* ListNode(int x) { val = x; }
* }
*/
class Solution {
public boolean isPalindrome(ListNode head) {
if (head == null || head.next == null) {
return true;
}
ListNode n1 = head;
ListNode n2 = head;
while (n2.next != null && n2.next.next != null) {
n1 = n1.next;
n2 = n2.next.next;
}
n2 = n1.next;
n1.next = null;
ListNode n3 = null;
while (n2 != null) {
n3 = n2.next;
n2.next = n1;
n1 = n2;
n2 = n3;
}
n3 = n1;
n2 = head;
boolean res = true;
while (n1 != null && n2 != null) {
if (n1.val != n2.val) {
res = false;
break;
}
n1 = n1.next;
n2 = n2.next;
}
n1 = n3.next;
n3.next = null;
while (n1 != null) {
n2 = n1.next;
n1.next = n3;
n3 = n1;
n1 = n2;
}
return res;
}
}
Review
Tip
Kotlin中,为什么 by lazy修饰的对象必须是val类型的,Lateinit 修饰的对象必须是var类型的?
-
by lazy修饰的对象必须是val类型的,因为它只会被初始化一次,之后就不会改变。如果我们将其定义为var类型的,那么就可以对它们进行重新赋值,这显然违背了lazy的初衷。
-
Lateinit修饰的对象必须是var类型的,因为该属性不会被立即初始化,而是在对象被实例化之后进行初始化。如果我们将其定义为val类型的,那么该属性就只能被赋值一次,在后续的运行中就无法修改,这与lateinit的初衷也是相悖的。
为什么不能对 Int 等基本类型 lateinit 修饰,而 by lazy 可以?
-
lateinit:它主要是为了解决在Kotlin中使用依赖注入框架时,需要在类的成员变量中先声明,在构造函数中初始化的问题。因此这个特性只能用在类的属性中,需要用var表示可变,并且只能用于类对象类型,而不能用于基本数据类型。
-
lazy:它主要是为了延迟初始化,在需要使用到变量时再进行初始化,以提高程序的性能。因此可以使用在任何变量中,包括基本数据类型,它的特性是只计算一次,之后可重复使用,相当于一种“缓存”机制,所以可以使用val表示为不可变变量。
综合来看,lateinit主要是为了解决类属性的初始化问题,而lazy是为了延迟初始化和提高程序性能。因此,在设计上lateinit只能用于类对象类型的属性中,而不能用于基本数据类型,而lazy则没有这个限制。