在做力扣上一道反转链表的题(从尾到头打印链表)时,发现提交上去的代码内存效率只超越了8%左右的提交,优化后内存效率超过了99%左右的提交,觉得优化的过程蛮有意义的,就记录一下。以下是我优化的过程,事先声明,本人水平一般,只是将优化过程展示出来,具体原理我无法详细解释。
这是我提交的原始代码:
class Solution {
public ListNode reverseList(ListNode head) {
ListNode ans = null;
while (head != null) {
ListNode next = head.next;
head.next = ans;
ans = head;
head = next;
}
return ans;
}
}
这段代码的运行时间超过了100%的提交,之后优化的版本也是,所以就不展示运行时间的截图了。然而运行时间虽短,但是内存消耗却比较大。通过分析代码,我认为可以将循环语句里面的
ListNode next = head.next;
进行优化,将创建next节点的语句放到循环之外,代码如下:
class Solution {
public ListNode reverseList(ListNode head) {
ListNode ans = null;
ListNode next = new ListNode();
while (head != null) {
next = head.next;
head.next = ans;
ans = head;
head = next;
}
return ans;
}
}
优化后的效果如下:
通过对比内存消耗小的提交,我发现
ListNode next = new ListNode();
可以直接用现有的节点head初始化(这句话可能不严谨,但我也想不出更好的描述了),如下:
class Solution {
public ListNode reverseList(ListNode head) {
ListNode ans = null;
ListNode next = head;
while (head != null) {
next = head.next;
head.next = ans;
ans = head;
head = next;
}
return ans;
}
}
优化后的效果:
继续借鉴其它内存消耗小的提交,发现执行完循环语句后可以调用系统的内存回收函数System.gc(),内存消耗进一步降低:
class Solution {
public ListNode reverseList(ListNode head) {
ListNode ans = null;
ListNode next = head;
while (head != null) {
next = head.next;
head.next = ans;
ans = head;
head = next;
}
System.gc();
return ans;
}
}
最终优化的结果:
这内存回收的函数简直无敌,优化效果太好了!至于原理我并不清楚,如果有热心的大佬不妨科普一下?