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:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章