ARTS
Algorithm:每周至少做一个leetcode的算法题;
Review:阅读并点评至少一篇英文技术文章;
Tip/Tech:学习至少一个技术技巧;
Share:分享一篇有观点和思考的技术文章;
Algorithm
19. 删除链表的倒数第N个节点
https://leetcode-cn.com/problems/remove-nth-node-from-end-of-list/
这道题看着想做出来其实不难,就是第一次遍历然后得到一个链表的整体的大小,然后在再进行一次遍历。当然这种的时间复杂度就是O(2n)。虽然级别是O(n),但是依然有优化的空间,有没有一次就遍历到底的方法,答案是有的,那就是用双指针来解决这问题。
(1)先让一个指针走K个指针。这个指针,我们称之为快指针
(2)在快指针走完K个指针之后,我们让另一个指针(这个我们称为慢指针)开始和快指针一起移动。
(3)当快指针到达链表的最后一个节点的时候,慢指针也就到达了链表的倒数第N个节点。
“Talk is cheap. Show me the code.” ― Linus Torvalds
public ListNode removeNthFromEnd(ListNode head, int n) {
if (head == null || head.next == null) {
return null;
}
ListNode fast = head;
ListNode low = head;
ListNode sentinel = new ListNode(0);
sentinel.next = head;
ListNode lowPre = sentinel;
for (int i = 0; i < n; ++i) {
fast = fast.next;
}
while (fast != null) {
lowPre = lowPre.next;
low = low.next;
fast = fast.next;
}
lowPre.next = low.next;
low.next = null;
return sentinel.next;
}
83. 删除排序链表中的重复元素
https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list/
这到题其实是我写的复杂了,其实真正的代码很简单,这题的原理也很简单,就是你找到一个节点,然后确认这个节点的下一个节点是不是和这节点一样,如果一样就删除下一个节点,也就是指针的next指向一样的节点的下一个;如果不一样,那就继续往下走。其实我的代码是真的写复杂了:
public ListNode deleteDuplicates(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode low = head;
ListNode fast = head.next;
while (fast != null) {
if (low.val == fast.val) {
ListNode fastNext = fast.next;
low.next = fastNext;
if (fastNext != null) {
fast = fastNext;
} else {
break;
}
} else {
if (low.next == fast){
low = low.next;
fast = fast.next;
} else {
low = low.next;
}
}
}
return head;
}
更好更简洁代码我在提交里面看到了
public ListNode deleteDuplicates(ListNode head) {
ListNode current = head;
while (current != null && current.next != null) {
if (current.next.val == current.val) {
current.next = current.next.next;
} else {
current = current.next;
}
}
return head;
}
以上的代码就是很简洁吧,遇到一样的把next的引用指向一样的节点的下一个节点。然后如果不一样,那就继续遍历下一个。
82. 删除排序链表中的重复元素 II
https://leetcode-cn.com/problems/remove-duplicates-from-sorted-list-ii/
这题和上一题比起来多了一个条件就是不留下任何的重复元素,只要有重复的元素,那数组中这些重复的元素就全部删除。其实和上面的 也没啥差别,双指针的做法其实已经很简单了,就是用个循环一直找到那个不重复的元素,然后把上一个的节点的next指针指向最后一个重复的元素的下一个节点。
public ListNode deleteDuplicates(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode sentinel = new ListNode(0);
sentinel.next = head;
ListNode pre = sentinel;
ListNode low = head;
ListNode fast = head.next;
while (fast != null) {
if (low.val == fast.val) {
while (fast.val == low.val) {
fast = fast.next;
if (fast == null) {
break;
}
}
pre.next = fast;
if (fast != null) {
low = fast;
fast = fast.next;
}
} else {
if (low.next == fast) {
pre = pre.next;
low = low.next;
fast = fast.next;
} else {
pre = pre.next;
low = low.next;
}
}
}
return sentinel.next;
}
当然了,肯定还是有更加简单的写法的,虽然思想都是相同的,但是代码写出来就更有百态了。
public ListNode deleteDuplicates(ListNode head) {
if(head==null||head.next==null)return head;
ListNode dummyHead=new ListNode(0);
dummyHead.next=head;
ListNode pre=dummyHead;
ListNode cur=head;
while (cur.next!=null) {
if (cur.val == cur.next.val) {
cur=cur.next;
} else {
if (pre.next!=cur) {
pre.next=cur.next;
cur=cur.next;
} else {
pre=cur;
cur=cur.next;
}
}
}
if(pre.next!=cur)pre.next=null;
return dummyHead.next;
}
Review
Code Tells You How, Comments Tell You Why
https://blog.codinghorror.com/code-tells-you-how-comments-tell-you-why/
这篇文章就是告诉一个最简单道理,就是代码会告诉你实现的细节,注释会告诉你这段代码为了什么而存在。
文章还引用了一段很经典的道理:
程序必须要写给人看,并且要给机器运行。
首先就是需要人可以读明白。所以我们编写代码的时候需要注意人的理解。
Tip/Tech
在Linux上打开端口
1.systemctl start firewalld 开启防火墙
2.firewall-cmd --zone=public --add-port=3306/tcp --permanent
命令含义:
--zone #作用域
--add-port=80/tcp #添加端口,格式为:端口/通讯协议
--permanent #永久生效,没有此参数重启后失效
3.firewall-cmd --reload
以上命令亲测有效。
Share
https://www.zhihu.com/question/269506059
如何评价程序员月薪 7 万可落户北京?
http://scholarsupdate.hi2net.com/news.asp?NewsID=21616
H1B 工资标准涨到13万美金的背后意味着什么?
其实这两者都能看出了最简单的道理,没啥中国美国的那个好的问题,大家其实都差不多。政策基本都是一样的,而且面对一些现实的问题,大家的解决方案也差不多。。。这就是政府殊途同归?