面試精選之鏈表問(wèn)題集錦

鏈表問(wèn)題是面試過(guò)程中經(jīng)常被問(wèn)到的一部分,很考查編程功底。最近刷了 LeetCode 上鏈表部分的面試題,我總結(jié)了一些有代表性的鏈表問(wèn)題。

本文使用的是 Java 語(yǔ)言,下面是所用到的鏈表節(jié)點(diǎn)的定義:

public class ListNode {
    int val;
    ListNode next;

    ListNode(int x) {
        val = x;
    }
}

1. 在 O(1) 時(shí)間刪除鏈表節(jié)點(diǎn)

Leetcode 237. Delete Node in a Linked List

題目描述:給定單鏈表中需要?jiǎng)h除的節(jié)點(diǎn)(不是尾節(jié)點(diǎn)),在 O(1) 時(shí)間刪除該節(jié)點(diǎn)。

分析:本題與《編程之美》上的「從無(wú)頭單鏈表中刪除節(jié)點(diǎn)」類似。主要思想都是「貍貓換太子」,即用下一個(gè)節(jié)點(diǎn)數(shù)據(jù)覆蓋要?jiǎng)h除的節(jié)點(diǎn),然后刪除下一個(gè)節(jié)點(diǎn)。但是如果節(jié)點(diǎn)是尾節(jié)點(diǎn)時(shí),該方法就行不通了。

代碼如下:

// 在 O(1) 時(shí)間從無(wú)頭單鏈表中刪除節(jié)點(diǎn)
public void deleteNode(ListNode node) {
    // 不能為空,不能為尾節(jié)點(diǎn)
    if (null == node || null == node.next) {
        return;
    }
    node.val = node.next.val;
    node.next = node.next.next;
}

2. 逆轉(zhuǎn)單鏈表

LeetCode 206. Reverse Linked List

題目描述:輸出一個(gè)單鏈表的逆序反轉(zhuǎn)后的鏈表。

分析:非遞歸的算法很簡(jiǎn)單,用三個(gè)臨時(shí)指針 prev、cur、next 在鏈表上循環(huán)一遍即可。遞歸算法是先逆轉(zhuǎn)下一個(gè)節(jié)點(diǎn),再逆轉(zhuǎn)當(dāng)前節(jié)點(diǎn)。

下面是兩種算法的代碼:

// 逆轉(zhuǎn)單鏈表,循環(huán)方法
public ListNode reverseByLoop(ListNode head) {
    if (null == head || null == head.next) {
        return head;
    }
    ListNode prev = null;
    ListNode next = null;
    // 用 head 作為 cur 指針
    while (null != head) {
        next = head.next;

        head.next = prev;
        prev = head;
        head = next;
    }
    return prev;
}

// 逆轉(zhuǎn)單鏈表,遞歸方法
public ListNode reverseByRecursion(ListNode head) {
    // 第一個(gè)條件判斷異常,第二個(gè)條件是結(jié)束遞歸
    if (null == head || null == head.next) {
        return head;
    }

    ListNode newHead = reverseByRecursion(head.next);

    head.next.next = head;
    head.next = null;

    return newHead;
}

3. 刪除單鏈表倒數(shù)第 n 個(gè)節(jié)點(diǎn)

LeetCode 19. Remove Nth Node From End of List

題目描述:刪除單鏈表倒數(shù)第 n 個(gè)節(jié)點(diǎn),1 <= n <= length,盡量在一次遍歷中完成。

分析:看到題目時(shí)的第一想法是先遍歷一次計(jì)算出單鏈表的長(zhǎng)度 length,然后在遍歷第二次刪除第 length - n + 1 個(gè)節(jié)點(diǎn),但是這需要遍歷兩次。正常的刪除第 n 個(gè)節(jié)點(diǎn)只需要遍歷一次就可以,如何只遍歷一次找到倒數(shù)第 n 個(gè)節(jié)點(diǎn)呢?可以設(shè)置兩個(gè)指針 p1、p2,首先 p1 和 p2 都指向 head,p2 移動(dòng)到第 n 個(gè)節(jié)點(diǎn),然后 p1 和 p2 同時(shí)向后移動(dòng),當(dāng) p2 移動(dòng)到末尾時(shí),p1 剛好指向倒數(shù)第 n 個(gè)節(jié)點(diǎn)。因?yàn)樽詈笠獎(jiǎng)h除倒數(shù)第 n 個(gè)節(jié)點(diǎn),所以可以找到倒數(shù)第 n + 1 個(gè)節(jié)點(diǎn),方便刪除節(jié)點(diǎn)。

代碼如下:

// 遍歷一次,刪除單鏈表倒數(shù)第 n 個(gè)節(jié)點(diǎn)
public ListNode removeNthFromEnd(ListNode head, int n) {
    if (null == head) {
        return head;
    }
    ListNode p1 = head;
    ListNode p2 = head;
    // 1. p2 移動(dòng)到第 n + 1 個(gè)節(jié)點(diǎn)
    for (int i = 0; i < n; i ++>) {
        p2 = p2.next;
    }
    // n == 鏈表長(zhǎng)度時(shí),p2 指向第 n + 1 節(jié)點(diǎn)為空,倒數(shù)第 n 個(gè)節(jié)點(diǎn)就是頭節(jié)點(diǎn)
    if (null == p2) {
        p1 = head.next;
        return p1;
    }
    // p1 和 p2 同時(shí)向后移動(dòng),直到 p2 到達(dá)尾節(jié)點(diǎn)
    while (null != p2.next) {
        p1 = p1.next;
        p2 = p2.next;
    }
    // 此時(shí) p1 指向倒數(shù)第 n + 1 個(gè)節(jié)點(diǎn),刪除它的下一個(gè)節(jié)點(diǎn)
    p1.next = p1.next.next;
    return head;
}

4. 求單鏈表的中間節(jié)點(diǎn)

題目描述:求單鏈表的中間節(jié)點(diǎn),如果鏈表的長(zhǎng)度為偶數(shù),返回中間兩個(gè)節(jié)點(diǎn)的任意一個(gè),若為奇數(shù),則返回中間節(jié)點(diǎn)。

分析:這道題的思路和第 3 題「刪除單鏈表倒數(shù)第 n 個(gè)節(jié)點(diǎn)」很相似。如果要求只能遍歷一遍鏈表的花,也通過(guò)兩個(gè)指針來(lái)完成。兩個(gè)指針從頭節(jié)點(diǎn)開(kāi)始,慢指針每次向后移動(dòng)一步,快指針每次向后移動(dòng)兩步,直到快指針移動(dòng)到尾節(jié)點(diǎn)時(shí),慢指針移動(dòng)到中間節(jié)點(diǎn)。

// 遍歷一次,找出單鏈表的中間節(jié)點(diǎn)
public ListNode findMiddleNode(ListNode head) {
    if (null == head) {
        return;
    }
    ListNode slow = head;
    ListNode fast = head;
    //如果要求在單鏈表長(zhǎng)度為偶數(shù)的情況下,返回中間兩個(gè)節(jié)點(diǎn)的第一個(gè),可以用下面的循環(huán)條件
    //while(null != fast.next && null != fast.next.next)
    while (null != fast && null != fast.next) {
        fast = fast.next.next;
        slow = slow.next;
    }
    return slow;
}

5. 判斷單鏈表是否存在環(huán)

LeetCode 141. Linked List Cycle

題目描述:判斷一個(gè)單鏈表是否有環(huán)

分析:還是通過(guò)快慢指針來(lái)解決,兩個(gè)指針從頭節(jié)點(diǎn)開(kāi)始,慢指針每次向后移動(dòng)一步,快指針每次向后移動(dòng)兩步,如果存在環(huán),那么兩個(gè)指針一定會(huì)在環(huán)內(nèi)相遇。

代碼如下:

// 判斷單鏈表是否有環(huán)
public boolean hasCycle(ListNode head) {
    if (null == head) {
        return false;
    }
    ListNode slow = head;
    ListNode fast = head;
    while (null != fast.next && null != fast.next.next) {
        fast = fast.next.next;
        slow = slow.next;
        if (fast == slow) {
            return true;
        }
    }
    return false;
}

6. 單鏈表是否有環(huán)擴(kuò)展:找到環(huán)的入口點(diǎn)

LeetCode 142. Linked List Cycle II

題目描述:判斷單鏈表是否有環(huán),如果有,找到環(huán)的入口點(diǎn)

分析:由上題可知,按照 p2 每次兩步,p1 每次一步的方式走,發(fā)現(xiàn) p2 和 p1 重合,確定了單向鏈表有環(huán)路了。接下來(lái),讓 p2 回到鏈表的頭部,重新走,每次步長(zhǎng)不是走 2 了,而是走 1,那么當(dāng) p1 和 p2 再次相遇的時(shí)候,就是在環(huán)路的入口點(diǎn)。

假設(shè)起點(diǎn)到環(huán)入口的距離尾 a,p1 和 p2 第一次相遇的相交點(diǎn) M 與環(huán)入口的距離為 b,環(huán)的周長(zhǎng)為 L,當(dāng) p1 和 p2 第一次相遇時(shí),假設(shè) p1 走了 n 步。其中 p1 和 p2 第一次相遇時(shí),p1 在環(huán)內(nèi)走過(guò)的步數(shù)為 b,因?yàn)楫?dāng) p1 走到環(huán)入口時(shí),p2 已經(jīng)在環(huán)內(nèi)了,假設(shè)此時(shí) p2 走到環(huán)入口的步數(shù)為 c,那么 p1 再走 c 步 p2 剛好追上來(lái)和 p1 相遇,c < L,所以此時(shí) p1 肯定還沒(méi)走完一圈。那么根據(jù)上面的假設(shè),有下面的關(guān)系:

p1 走的路徑:a + b = n
p2 走的路徑:a + b + k * L = 2n,假設(shè)此時(shí) p2 比 p1 多走了 k 圈環(huán)路,k >= 1

根據(jù)上面的兩個(gè)等式可以得出k * L = n = a + b,那么從相交點(diǎn) M 開(kāi)始,p1 再走 a(a = k * L - b) 步,就相當(dāng)于走了 k 圈,然后回退 b 步,注意環(huán)入口到相交點(diǎn)的距離剛好為 b,所以 p1 再走 a 步時(shí)到達(dá)環(huán)入口;而 p2 從頭開(kāi)始走 a 的話也到達(dá)了環(huán)入口,與 p1 相遇。

而在后面這個(gè)步驟中,p1 和 p2 前 a 步走的路徑不同,再次相遇時(shí)必然在環(huán)的入口點(diǎn)。

代碼如下:

// 找到環(huán)的入口點(diǎn)
public ListNode findLoopPort(ListNode head) {
    if (null == head) {
        return null;
    }
    ListNode p1 = head;
    ListNode p2 = head;
    boolean hasCycle = false;
    // 1. 判斷是否有環(huán)
    while (null != p2.next && null != p2.next.next) {
        p1 = p1.next;
        p2 = p2.next.next;
        if (p1 == p2) {
            hasCycle = true;
            break;
        }
    }
    if (!hasCycle) {
        return null;
    }

    // p2 從頭開(kāi)始走,步長(zhǎng)變?yōu)?1
    p2 = head;
    while (p1 != p2) {
        p1 = p1.next;
        p2 = p2.next;
    }
    return p1;
}

7. 判斷兩個(gè)無(wú)環(huán)單鏈表是否相交

題目描述:給出兩個(gè)無(wú)環(huán)單鏈表

A:       a1 → a2
                 ↘
                    c1 → c2 → c3 → null
                 ↗            
B:  b1 → b2 → b3

判斷 A 和 B 是否相交。

分析:

1.最直接的方法是判斷 A 鏈表的每個(gè)節(jié)點(diǎn)是否在 B 鏈表中,但是這種方法的時(shí)間復(fù)雜度為 O(Length(A) * Length(B))。

2.轉(zhuǎn)化為環(huán)的問(wèn)題。把 B 鏈表接在 A 鏈表后面,如果得到的鏈表有環(huán),則說(shuō)明兩個(gè)鏈表相交。可以之前討論過(guò)的快慢指針來(lái)判斷是否有環(huán),但是這里還有更簡(jiǎn)單的方法。如果 B 鏈表和 A 鏈表相交,把 B 鏈表接在 A 鏈表后面時(shí),B 鏈表的所有節(jié)點(diǎn)都在環(huán)內(nèi),所以此時(shí)只需要遍歷 B 鏈表,看是否會(huì)回到起點(diǎn)就可以判斷是否相交。這個(gè)方法需要先遍歷一次 A 鏈表,找到尾節(jié)點(diǎn),然后還要遍歷一次 B 鏈表,判斷是否形成環(huán),時(shí)間復(fù)雜度為 O(Length(A) + Length(B))。

3.除了轉(zhuǎn)化為環(huán)的問(wèn)題,還可以利用“如果兩個(gè)鏈表相交于某一節(jié)點(diǎn),那么之后的節(jié)點(diǎn)都是共有的”這個(gè)特點(diǎn),如果兩個(gè)鏈表相交,那么最后一個(gè)節(jié)點(diǎn)一定是共有的。所以可以得出另外一種解法,先遍歷 A 鏈表,記住尾節(jié)點(diǎn),然后遍歷 B 鏈表,比較兩個(gè)鏈表的尾節(jié)點(diǎn),如果相同則相交,不同則不相交。時(shí)間復(fù)雜度為 O(Length(A) + Length(B)),空間復(fù)雜度為 O(1),思路比解法 2 更簡(jiǎn)單。

解法 3 的代碼如下:

// 判斷兩個(gè)無(wú)環(huán)單鏈表是否相交
public boolean isIntersect(ListNode headA, ListNode headB) {
    if (null == headA || null == headB) {
        return false;
    }
    if (headA == headB) {
        return true;
    }
    while (null != headA.next) {
        headA = headA.next;
    }
    while (null != headB.next) {
        headB = headB.next;
    }
    return headA == headB;
}

8. 兩個(gè)鏈表相交擴(kuò)展:判斷兩個(gè)有環(huán)單鏈表是否相交

題目描述:上面的問(wèn)題是針對(duì)無(wú)環(huán)鏈表的,如果是鏈表有環(huán)呢?

分析:如果兩個(gè)有環(huán)單鏈表相交,那么它們一定共有一個(gè)環(huán)。因此可以先用之前快慢指針的方式找到兩個(gè)鏈表中位于環(huán)內(nèi)的兩個(gè)節(jié)點(diǎn),如果相交的話,兩個(gè)節(jié)點(diǎn)在一個(gè)環(huán)內(nèi),那么移動(dòng)其中一個(gè)節(jié)點(diǎn),在一次循環(huán)內(nèi)肯定可以與另外一個(gè)節(jié)點(diǎn)相遇。

代碼如下:

// 判斷兩個(gè)有環(huán)單鏈表是否相交
public boolean isisIntersectWithLoop(ListNode headA, ListNode headB) {
    if (null == headA || null == headB) {
        return false;
    }
    if (headA == headB) {
        return true;
    }
    headA = hasCycle(headA);
    headB = hasCycle(headB);
    // 沒(méi)有環(huán),則退出
    if (null == headA || headB) {
        return false;
    }

    ListNode p = headB.next;
    // p 在環(huán)內(nèi)循環(huán)一次,直到與 headA 相遇
    while (p != headB) {
        if (p == headA) {
            return true;
        }
        p = p.next;
    }
    return false;
}

// 判斷單鏈表是否有環(huán),并返回環(huán)內(nèi)的某一節(jié)點(diǎn)
public ListNode hasCycle(ListNode head) {
    if (null == head) {
        return null;
    }
    ListNode slow = head;
    ListNode fast = head;
    while (null != fast.next && null != fast.next.next) {
        fast = fast.next.next;
        slow = slow.next;
        if (fast == slow) {
            return slow;
        }
    }
    return null;
}

9. 兩個(gè)鏈表相交擴(kuò)展:求兩個(gè)無(wú)環(huán)單鏈表的第一個(gè)相交點(diǎn)

LeetCode 160. Intersection of Two Linked Lists

題目描述:找到兩個(gè)無(wú)環(huán)單鏈表第一個(gè)相交點(diǎn),如果不相交返回空,要求在線性時(shí)間復(fù)雜度和常量空間復(fù)雜度內(nèi)完成。

分析:

下面所說(shuō)的對(duì)齊:表示指針到鏈表末尾的距離相同。

  1. 分為先判斷是否有環(huán),再求第一個(gè)相交點(diǎn)的方式。分別遍歷 A 鏈表和 B 鏈表,判斷它們的最后一個(gè)節(jié)點(diǎn)是否相交。然后利用對(duì)齊的思想,計(jì)算兩個(gè)鏈表的長(zhǎng)度(這個(gè)可以放在之前的遍歷中做),分別用 p1 和 p2 指向兩個(gè)鏈表的頭,然后將較長(zhǎng)鏈表的 p1 (假設(shè)為 p1)向后移動(dòng) LB - LA 個(gè)節(jié)點(diǎn)。這樣 p1 和 p2 對(duì)齊了,然后同時(shí)向后移動(dòng) p1 和 p2,直到 p1 == p2,相遇的點(diǎn)就是第一個(gè)節(jié)點(diǎn)。

  2. 解法 1 中為了對(duì)齊需要計(jì)算鏈表的長(zhǎng)度,有沒(méi)有什么方法可以不用計(jì)算鏈表長(zhǎng)度呢?假設(shè) A 鏈表和 B 鏈表的長(zhǎng)度為 LA 和 LB,假設(shè) LB >= LA,兩個(gè)指針 p1 和 p2 分別指向 A 鏈表和 B 鏈表的頭節(jié)點(diǎn)。同時(shí)向后移動(dòng),當(dāng) p1 移動(dòng) A 鏈表的末尾時(shí),p2 距離 B 鏈表的末尾的距離為 LB - LA,此時(shí)可以看出我們已經(jīng)得到了長(zhǎng)度差,如何利用這個(gè)長(zhǎng)度差對(duì)齊呢。這時(shí)將 p1 移動(dòng)到 B 鏈表的頭部,兩個(gè)指針繼續(xù)移動(dòng),當(dāng) p2 移動(dòng)到 B 鏈表的末尾時(shí),p1 剛好移動(dòng)了 LB - LA 步。此時(shí)再將 p2 移動(dòng)到 A 鏈表的頭部,這樣 p1 和 p2 就對(duì)齊了,然后繼續(xù)移動(dòng),直到 p1 == p2。如果兩個(gè)鏈表不相交,p1 和 p2 移動(dòng)會(huì)同時(shí)移動(dòng)到末尾都指向空,而相交的話,第一次相等時(shí)就是第一個(gè)相交點(diǎn)。這種方法的時(shí)間復(fù)雜度為 O (2 * (Length(B))),最多要遍歷兩次長(zhǎng)度較長(zhǎng)的鏈表。

?解法 2 的代碼如下:

// 求兩個(gè)無(wú)環(huán)單鏈表的第一個(gè)相交點(diǎn)
public ListNode getIntersectionNode(ListNode headA, ListNode headB) {
    if (null == headA || null == headB) {
        return null;
    }
    if (headA == headB) {
        return headA;
    }

    ListNode p1 = headA;
    ListNode p2 = headB;
    while (p1 != p2) {
        // 遍歷完所在鏈表后從另外一個(gè)鏈表再開(kāi)始
        // 當(dāng) p1 和 p2 都換到另一個(gè)鏈表時(shí),它們對(duì)齊了:
        // (1)如果鏈表相交,p1 == p2 時(shí)為第一個(gè)相交點(diǎn)
        // (2)如果鏈表不相交,p1 和 p2 同時(shí)移動(dòng)到末尾,p1 = p2 = null,然后退出循環(huán)
        p1 = (null == p1) ? headB : p1.next;
        p2 = (null == p2) ? headA : p2.next;
    }
    return p1;
}

10. 總結(jié)

回過(guò)頭來(lái),會(huì)發(fā)現(xiàn)上面的鏈表問(wèn)題主要用到了「貍貓換太子」、「對(duì)齊」以及「兩個(gè)指針」的方式來(lái)提高效率。其中利用兩個(gè)指針來(lái)提供效率的方式經(jīng)常用到,在遇到鏈表問(wèn)題時(shí)可以多考慮下這種思路。推薦大家記住這幾種典型的鏈表問(wèn)題,以后很多類似的題目都可以轉(zhuǎn)換到熟悉的問(wèn)題再解決。

參考文章:

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,327評(píng)論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,996評(píng)論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人,你說(shuō)我怎么就攤上這事。” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 177,316評(píng)論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 63,406評(píng)論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,128評(píng)論 6 410
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 55,524評(píng)論 1 324
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,576評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書人閱讀 42,759評(píng)論 0 289
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,310評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,065評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,249評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,821評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,479評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 34,909評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 36,140評(píng)論 1 290
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,984評(píng)論 3 395
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,228評(píng)論 2 375

推薦閱讀更多精彩內(nèi)容