ARTS打卡第十周

Algorithm:61. Rotate List

https://leetcode-cn.com/problems/rotate-list/

Given a linked list, rotate the list to the right by k places, where k is non-negative.

Example 1:

Input: 1->2->3->4->5->NULL, k = 2
Output: 4->5->1->2->3->NULL

Explanation:

rotate 1 steps to the right: 5->1->2->3->4->NULL
rotate 2 steps to the right: 4->5->1->2->3->NULL

Example 2:

Input: 0->1->2->NULL, k = 4
Output: 2->0->1->NULL

Explanation:

rotate 1 steps to the right: 2->0->1->NULL
rotate 2 steps to the right: 1->2->0->NULL
rotate 3 steps to the right: 0->1->2->NULL
rotate 4 steps to the right: 2->0->1->NULL

分析:链表问题一般有两种思路,一是先求出链表长度,然后利用长度计算下标,类似于数组操作;另一种是用双指针,可以是快慢指针,也可以是滑动窗口,其思想是把下标关系转换成两个指针之间的距离,然后同时前进。
下面也用这两种思路来解答这一题。有点特别的是,当k大于数组长度时,双指针解法仍然要计算数组长度,否则,会很低效。
这两种解法时间复杂度都是O(n),空间复杂度都是O(1)。当k小于等于链表长度时,解法二应该是优于解法一的,因为只需要遍历一遍;当k大于链表长度时,两种解法是差不多的,甚至解法一可能更快一点,因为解法二中多了一个指针需要移动。从Leetcode的提交记录来看,解法一更快一点,且解法一思路更清晰一些,所以个人倾向于解法一。当然了,解法二也可以像解法一一样,先求出链表长度,然后取模,然后再利用双指针移动,但感觉有点多次一举了。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode(int x) { val = x; }
 * }
 */
class Solution {
    // 解法二:双指针。当k小于等于链表长度时,遍历一遍搞定;当k大于链表长度时,第一次遍历仍然要计算出链表长度然后将k取模运算,否则当k远远大于链表长度时,快指针会做很多次无效移动。
    public ListNode rotateRight(ListNode head, int k) {
        if(head == null || head.next == null || k == 0)
            return head;
        
        ListNode p = head;
        ListNode q = head;
        int i;
        for(i=1; i<= k && p.next != null; i++, p=p.next);
        
        if(i <= k) { // i+1 is length of list
            k %= i;
            p = head;
            for(i=0; i<k; i++, p=p.next);
        }
        
        if(p == q)
            return head;
        
        while(p.next != null) {
            p = p.next;
            q = q.next;
        }
        
        ListNode temp = q.next;
        q.next = null;
        p.next = head;
        head = temp;
        
        return head;
    }
    
    // 解法一:先求出长度,再计算需要断开的位置,将后半段插到前面去,返回新的链表头
    private ListNode solutaion_1(ListNode head, int k) {
        if(head == null || k == 0)
            return head;
        
        ListNode p = head;
        int size = 1;
        while(p.next != null) {
            p = p.next;
            size++;
        }
        // now p is point to the end
        
        k %= size;
        if(k == 0)
            return head;
        
        ListNode q = head;
        for(int i=1; i< size-k; i++, q=q.next);
        // now q is point to the k+1 from the end
        
        ListNode temp = q.next;
        q.next = null;
        p.next = head;
        head = temp;
        
        return head;        
    }
}

Review: Cloud Computing History

https://medium.com/pgs-software/cloud-computing-history-7c2c188a30a
文章介绍了云计算的历史和演进过程,主要分为如下几块内容:

  1. 时间共享主机。在19世纪50年代到80年代期间,计算机很昂贵,多个用户共用一台计算机很普遍,那时主要是通过时间片轮转的方式共享,类似于现在单核cpu对多线程的调度。https://en.wikipedia.org/wiki/Time-sharing
  2. 互联网。19世纪50年代末出现局域网,直到90年代,Internet才诞生。互联网的诞生催生了大量的网络应用,也激发了对服务器和数据中心的大量需求。
  3. 虚拟机。虚拟机的概念其实很早就出现了,1966年IBM就在操作系统中引入了虚拟机。2013年诞生的docker,是一种操作系统级别的虚拟化产品,它的出现使得微服务架构蓬勃发展。
  4. SaaS, PaaS, IaaS
  5. 真正的云。亚马逊EC2、微软Azure Virtual Machines、谷歌Google Compute Engine
  6. 超越。
  7. 商业视角。Businesses that are able to keep up with these changes stand to continually gain the most benefits compared to those who sit idly by.与无所事事的人相比,能够跟上变化的企业将持续获得最大收益。

Tip:使用MySQL的官方Docker镜像如何初始化数据库

我使用的是官方mariadb基础镜像mariadb:latest ,我们只要把初始化数据库的sql文件放到 /docker-entrypoint-initdb.d/ 目录下,容器在启动的时候就会执行这个sql。除了sql文件,同样也支持sh脚本和sql.gz文件。

有一点需要注意,这个初始化工作只会执行一次,一旦数据库中已经有数据了,就不会再次初始化。

上述初始化工作是在基础镜像的 docker-entrypoint.sh 脚本里做的,这里面会判断在mysql的数据目录下是否有 /mysql 子目录,如果有的话,就不执行初始化的逻辑:

        ...
        DATADIR="$(_get_config 'datadir' "$@")"
        if [ ! -d "$DATADIR/mysql" ]; then
        	...
            for f in /docker-entrypoint-initdb.d/*; do
                    case "$f" in
                            *.sh)     echo "$0: running $f"; . "$f" ;;
                            *.sql)    echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;;
                            *.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;;
                            *)        echo "$0: ignoring $f" ;;
                    esac
                    echo
            done        	

Share:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值