ARTS - 2020.08.24 ~ 2020.08.30

ARTS打卡 - 12

1. Algorithm

19. Remove Nth Node From End of List

这道题题目比较明确,移除链表中倒数第n个节点。解法也应该有多种,例如:遍历一遍,将链表转化为一个数组,然后移除对应下标的元素即可。还有一种解法是先遍历链表,获取链表长度,然后翻转,移除对应的节点。我用的是另一种方法:

  1. 判断边界条件
  2. 两个指针,步长为n,即倒数第n个节点。
  3. 移动指针,当第一个指针与第二个指针相距步长为n的时候,移动第二个指针。
  4. 第一个指针移动到链表尾节点的时候,刚好第二个指针所在位置的下一个就是要移除的节点
  5. 将要被移除的节点的前置节点与后置节点相连,得到的就是移除对应节点后的新链表。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public ListNode removeNthFromEnd(ListNode head, int n) {
if(head == null || n == 0){
return head;
}
ListNode newHead = new ListNode();
ListNode temp = newHead;
ListNode current = head;
int i = 1, j = 1;
while (head.next != null){
i++;
head = head.next;
if(i - j >= n){
j++;
temp.next = new ListNode(current.val);
temp = temp.next;
current = current.next;
}
}
temp.next = current.next;

return newHead.next;
}

2. Review

Android Vitals - What time is it?

这是一个系列文章,作者是LeakCanary的作者。是关于如何监控Android生产环境的表现的文章。这是这一系列的第一篇,文章讲述了如何选择计算时间的方法。在Android中,提供了多种计算时间的方式:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Milliseconds since Unix epoch (00:00:00 UTC on 1 January 1970)
System.currentTimeMillis()
// Nanoseconds since the VM started.
System.nanoTime()

// (API 29) Clock that starts at Unix epoch.
// Synchronized using the device's location provider.
SystemClock.currentGnssTimeClock()
// Milliseconds running in the current thread.
SystemClock.currentThreadTimeMillis()
// Milliseconds since boot, including time spent in sleep.
SystemClock.elapsedRealtime()
// Nanoseconds since boot, including time spent in sleep.
SystemClock.elapsedRealtimeNanos()
// Milliseconds since boot, not co unting time spent in deep sleep.
SystemClock.uptimeMillis()

它们之间的主要区别是:

  • System.currentTimeMillis(): 这是比较常用的计算时间的方法,但是这个方法获取的事件可以被用户或手机网络改变,可能会出现较大的跳动,因此计算时间间隔应该使用其它的方法。
  • SystemClock.uptimeMillis():这个计算方式会在系统进入深度睡眠的时候停止,例如在 Thread.sleep() 或者 Object.wait(long) ,这个方法很适合计算事件当不需要计算睡眠时。
  • SystemClock.elapsedRealtime():与SystemClock.uptimeMillis()计算逻辑刚好相反,会包括睡眠时间。

在计算App的表现是,更推荐使用SystemClock.uptimeMillis()或者nanoTime()

此外,还比较了SystemClock.uptimeMillis()nanoTime()的性能差异,结论是使用uptimeMillis() 与nanoTime() 在新的Android系统上是一样的,而在旧版的Android系统上,uptimeMillis() 会表现更好。这是因为

在新的系统上刚对``nanoTime()`的实现方式做了修改,所以实现方式二者是一样的。具体的实现文章有详细说明。

所以结论时,当需要在生产环境计算消耗时间的间隔时,最好是使用SystemClock.uptimeMillis()

3. Tip

  • 可以使用top命令查看系统内存与CPU占用,例如:adb shell top -m 20 查看内存占用前20的应用,此外还可以加一些参数,例如 -i: 可以指定top输出的时间间隔, -p: 指定进程号。(获取进程号可以通过pidof xxxx, 或者 lsof -i :port),此外,也可以结合pgrep命令过滤出符合条件的信息: top -c -p $(pgrep -d',' -f string_to_match_in_cmd_line) ,其中 -d 表示使用 ‘,’ 分割,-f 表示匹配内容。
  • top输出的详细解读:https://juejin.im/post/6844903919588491278

4. Share

  • 浅谈Java中的TCP超时

    最近改bug发现了一些超时的错误,其中SocketTimeoutException是比较常见的一种网络超时错误,分为connect timed out 和 read time out。这篇文章比较i详细的讲了在建立Socket连接时从client到jvm到linux底层的一些调用链。