ARTS (23) 2019 03 24

68 篇文章 0 订阅
49 篇文章 0 订阅

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万美金的背后意味着什么?

其实这两者都能看出了最简单的道理,没啥中国美国的那个好的问题,大家其实都差不多。政策基本都是一样的,而且面对一些现实的问题,大家的解决方案也差不多。。。这就是政府殊途同归?

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值