算法(1):遞歸

??腦抽的我上個文章爛尾坏平,又開新坑,锦亦,舶替,,我只能對自己前面開的爛坑說一句:青山不改杠园,綠水長流顾瞪,我們有緣再見!
??這次我想刷一刷算法題(對抛蚁,我又叒叕換目標(biāo)了)陈醒,把常見的基礎(chǔ)算法做一個總結(jié)(千萬別又是起個頭就扔那里不管了,真的是廢人一個了瞧甩。钉跷。。)
??好肚逸,話不多說爷辙,遞歸(Recursion)走起!



概念理解:

??首先我們分析一下定義朦促,遞歸是一種使用某種函數(shù)來解決問題的方法(當(dāng)然你可以忽略這句廢話)膝晾,特殊之處便在于該函數(shù)會不斷調(diào)用它自身來作為其子程序

??那么务冕,如何實現(xiàn)這么一個函數(shù)呢血当?它調(diào)用自己,又是干了些什么呢禀忆?
??這個小技巧便是該遞歸函數(shù)每一次調(diào)用的時候臊旭,它都能將給定的問題變成該問題的子問題,該函數(shù)會不知疲倦的一直調(diào)用它自己(覺得像影分身之術(shù)油湖,但是確切點說的話巍扛,是那種分身又施展影分身術(shù)的 feel...),直到子問題被解決掉乏德,不再產(chǎn)生遞歸為止(所以說撤奸,不是子子孫孫無窮匱哦,遞歸沒有我們的愚公爺爺厲害)喊括。

??所以胧瓜,遞歸函數(shù)是一定存在邊界的,也就是終止條件郑什。在遇到某種情況時府喳,遞歸函數(shù)將不再調(diào)用自身,而是輸出一個結(jié)果(當(dāng)然也可以什么也不輸出蘑拯,直接結(jié)束子程序)钝满。所以寫遞歸函數(shù)的時候兜粘,一定不要忘了寫終止遞歸的條件(個人建議,先寫這些邊界條件弯蚜,后面再寫程序處理邏輯)~


??扯了這么多孔轴,腦中揮散不去的還是大家對我爆喊 “talk is cheap, show me the code!"的場景碎捺,那么路鹰,代碼兄,該你登場了(以下題目均來自LeetCode)~
??附注:建議大家看看問題3收厨,因為提到了一個遞歸經(jīng)常遇到的問題晋柱,重復(fù)計算,而解決重復(fù)計算的方法也很簡單诵叁,加入一個記憶機制(Memoization)雁竞,也就是儲存我們計算過的值即可。


問題1:字符串翻轉(zhuǎn)黎休,要求浓领,O(1)空間復(fù)雜度(看所給的例子輸入,題目應(yīng)該叫列表翻轉(zhuǎn)才更貼切)
例子:
輸入: ['a','b','c']
輸出: ['c','b','a']
解決思路:
1.取出首尾兩個字符势腮,并做交換;
2.遞歸調(diào)用該函數(shù)漫仆,來翻轉(zhuǎn)剩下的子串捎拯。
3.設(shè)計跳出遞歸的邊界條件,這里是begin >= end盲厌,即字符串遍歷完畢署照。

def reverseString(begin, end,s) -> None:
    """
    Do not return anything, modify s in-place instead.
    """
    if begin >= end:
        return
    s[begin], s[end] = s[end], s[begin]
    reverseString(begin + 1, end - 1, s)

s = ['a','b','c']
reverseString(0, len(s) - 1, s)
print(s)

### output ###
# ['c', 'b', 'a']

問題2:給定一個鏈表,每兩個相鄰的節(jié)點交換位置吗浩,并返回頭節(jié)點建芙。
例子:
輸入鏈表:1->2->3->4
輸出鏈表:2->1->4->3
解決思路:
1.交換前兩個節(jié)點的位置;
2.把剩下的鏈表傳遞給自身懂扼,遞歸調(diào)用禁荸。
3.當(dāng)?shù)诌_鏈表尾部時結(jié)束遞歸。

class ListNode:   #定義節(jié)點類
    def __init__(self, x):
        self.val = x
        self.next = None

def swapPairs(head) -> ListNode:   #實現(xiàn)功能的遞歸函數(shù)
    if head == None or head.next == None:
        return head
    temp = head.next   #  節(jié)點2阀湿,也就是temp赶熟,即為我們所要的head
    head.next = swapPairs(temp.next)   #將節(jié)點1 和后面的鏈表串拼接,也就是(4->3)
    temp.next = head   # 將節(jié)點2的后面接上節(jié)點1
    return temp   #返回節(jié)點2

def printListNode(node):   #輔助函數(shù),打印鏈表
    while node:
        print(node.val, end=' ')
        if node.next:
            print('->', end=' ')
        node = node.next
    print()

if __name__ == '__main__':
    head = node = ListNode(1)
    for i in range(2,5):
        node.next = ListNode(i)
        node = node.next

    printListNode(head)
    ans = swapPairs(head)
    printListNode(ans)

        

問題3楊輝三角形(聽說你不知道什么是楊輝三角形陷嘴,鏈接附上映砖,送給各位看官)

楊輝三角形

??在討論這個問題之前,為了讓大家看的更清晰灾挨,我們先提綱挈領(lǐng)一波邑退,在此討論一下兩個概念竹宋,遞推關(guān)系和邊界條件。
??遞推關(guān)系說白了就是問題結(jié)果和子問題的結(jié)果之間的關(guān)系地技,而邊界條件我們前面提到過蜈七,便是遞歸到了終點,問題無法繼續(xù)分解為子問題乓土,可以直接得到答案宪潮。
??那么通過這個例子,大家一起來看看這兩個概念的具現(xiàn)到底是何方神圣把~
??首先趣苏,我們定義一個函數(shù)狡相,f(i,j)i 代表第 i 行食磕, j 代表第 j 列尽棕,那么,我們可以列出遞歸關(guān)系式:
f(i,j) = f(i-1,j-1) + f(i-1,j)
其次彬伦,再列出邊界條件:
f(i,j) = 1, \space where \space j =1 \space or \space j = i
??這樣子滔悉,思路是不是就清晰明了一些了呢?當(dāng)以后遇到復(fù)雜的遞歸問題的時候单绑,可以先嘗試列出遞歸關(guān)系式和邊界條件回官,可以方便我們更清晰的整理思路呦~

當(dāng)然,問題以及代碼如下:
輸入: 5
輸出:
[
[1],
[1,1],
[1,2,1],
[1,3,3,1],
[1,4,6,4,1]
]

def generate(numRows) -> list:
    def helper(i, j):
        if j == 0 or j == i:
            return 1
        return helper(i - 1, j - 1) + helper(i - 1, j)

    ans = []
    for i in range(0, numRows):
        temp = []
        for j in range(0, i + 1):
            temp.append(helper(i, j))
        ans.append(temp)

    print(ans)
    return ans

if __name__ ==  '__main__':
    generate(5)

??上面我們的helper函數(shù)搂橙,完美的按照邊界條件和遞歸關(guān)系式要求所寫歉提,結(jié)果也是沒有任何問題。但是区转,但是苔巨,但是!各位小伙伴試試把generate(5) 換成generate(30)試試(測測你電腦性能 /斜眼笑)废离?花費的時間多的讓你懷疑人生侄泽,哈哈~ 那么問題來了,到底是什么原因?qū)е碌哪兀?br> ??我們思考一下蜻韭,當(dāng)計算f(5,3)的時候悼尾,我們需要計算f(4,2)f(4,3),而這兩個都需要計算一次f(3,2)湘捎,聰明的朋友诀豁,你是不是發(fā)現(xiàn)了問題所在?對窥妇,那就是重復(fù)計算(這個地方一定要加黑加粗舷胜,因為遞歸非常容易遇到這個問題,大家一定要留意才行)!當(dāng)你需要顯示的行數(shù)愈多時烹骨,重復(fù)計算的量就會越大翻伺。
??所以,上面的程序也就逗小孩子玩玩沮焕,實用性幾乎為零(為什么用幾乎吨岭?因為它還能逗小孩子玩玩。所以這里充分體現(xiàn)了作者嚴(yán)謹(jǐn)?shù)淖膽B(tài)度)峦树。那么辣辫,這種問題該如何解決呢?正解魁巩,加入記憶機制急灭,將我們之前計算過的全部儲存下來即可~
??關(guān)門,上代碼谷遂!

def generate(numRows) -> list:
    cache = {}
    def helper(i, j):
        if (i,j) in cache:
            return cache[(i,j)]

        if j == 0 or j == i:
            return 1

        result =  helper(i - 1, j - 1) + helper(i - 1, j)
        cache[(i,j)] = result
        return result

    ans = []
    for i in range(0, numRows):
        temp = []
        for j in range(0, i + 1):
            temp.append(helper(i, j))
        ans.append(temp)

    print(ans)
    return ans

if __name__ ==  '__main__':
    generate(5)

??這個時候葬馋,我們哪怕把5換成500,也是分分鐘的事情肾扰,不畴嘶,秒秒鐘。


問題4:鏈表翻轉(zhuǎn)(又是一道可惡的鏈表題)
例子:
輸入: 1->2->3->4->5
輸出: 5->4->3->2->1
解決思路:
1.遞歸函數(shù)傳遞兩個參數(shù)集晚,head 和 pre窗悯,head 保存的是原來的鏈表,pre 保存的是翻轉(zhuǎn)的鏈表偷拔。
2.在每次遞歸時蟀瞧,從head上取下來一個節(jié)點,然后把 pre 接在該節(jié)點后面条摸。
3.在遞歸到最后時,head 節(jié)點為空铸屉,而 pre 里面則為翻轉(zhuǎn)好的鏈表钉蒲。

class ListNode:   #定義節(jié)點類
    def __init__(self, x):
        self.val = x
        self.next = None

def reverseList( head, pre = None):
    if not head: return pre
    cur, head.next = head.next, pre
    return reverseList(cur, head)

def printListNode(node):   #輔助函數(shù),打印鏈表
    while node:
        print(node.val, end=' ')
        if node.next:
            print('->', end=' ')
        node = node.next
    print()

if __name__ == '__main__':
    head = node = ListNode(1)
    for i in range(2,6):
        node.next = ListNode(i)
        node = node.next

    printListNode(head)
    ans = reverseList(head)
    printListNode(ans)

問題5:鏈表相加(跟鏈表杠上了)
一個鏈表相當(dāng)于存了一個數(shù)彻坛,如鏈表(2 -> 4 -> 3)相當(dāng)于數(shù)字342顷啼,我們要做的就是把數(shù)讀出來,然后相加昌屉,再將結(jié)果寫成鏈表形式钙蒙。
輸入: (2 -> 4 -> 3) + (5 -> 6 -> 4)
輸出: 7 -> 0 -> 8
解釋: 342 + 465 = 807.

class ListNode(object):
    def __init__(self, x):
        self.val = x
        self.next = None
        self.prev = None

def printListNode(node):   #輔助函數(shù),打印鏈表
    while node:
        print(node.val, end=' ')
        if node.next:
            print('->', end=' ')
        node = node.next
    print()

def addTwoNumbers( l1: ListNode, l2: ListNode) -> ListNode:
    def toint(node):
        return node.val + 10 * toint(node.next) if node else 0

    def tolist(n):
        node = ListNode(n % 10)
        if n >= 10:
            node.next = tolist(n // 10)
        return node
    return tolist(toint(l1) + toint(l2))

if __name__ == '__main__':
    head1 = node1 = ListNode(1)

    for i in range(2,10,2):
        node1.next = ListNode(i)
        node1 = node1.next

    printListNode(head1)
    ans = addTwoNumbers(head1,head1)
    printListNode(ans)


??最后的最后间驮,渴望變成天使躬厌,,竞帽,啊呸扛施,最后的最后鸿捧,我們來分析一下遞歸問題的時間復(fù)雜度和空間復(fù)雜度,這也是一個需要我們下功夫思考的地方疙渣,那么匙奴,Let’s begin!

  • 時間復(fù)雜度
    ??遞歸問題時間復(fù)雜度可以由一個公式來表示:
    O(T)=R?O(s)??其中妄荔,O(T)為遞歸問題的時間復(fù)雜度泼菌,R 表示為該問題共調(diào)用遞歸函數(shù)的次數(shù)(遞歸花時間,一般問題出在這里啦租。重復(fù)計算導(dǎo)致計算機吐血而亡哗伯,GG前,面對電腦前的你刷钢,帶著疑惑和不甘笋颤,向你道出了最后的遺言:“我跟你...咳咳...什么仇什么怨,我如此強大的計算能力内地,咳咳伴澄,精通千萬種高級計算方法,你為什么要...咳咳...要讓我算1+1算到死阱缓?”非凌。這時,你會如何回答荆针?)敞嗡,而O(s)表示單個遞歸函數(shù)的時間復(fù)雜度。很好理解吧~
    ??在此航背,我給大家列兩個例子喉悴,方便各位理解:
    ??例子1:我們來一起重溫一下問題1,字符串翻轉(zhuǎn)問題玖媚。每次我們?nèi)〕鰞蓚€字符箕肃,剩下的繼續(xù)調(diào)用遞歸函數(shù),那么我們需要調(diào)用n/2次(n代表字符串長度)今魔,那么可得R =n/2勺像。在每個遞歸函數(shù)當(dāng)中,我們只做了一個交換動作错森,s[begin], s[end] = s[end], s[begin]吟宦,所以時間復(fù)雜度為O(1),那么涩维,該算法的復(fù)雜度便為:R*O(1) = n/2 * O(1) = O(n)是不是很簡單呢殃姓?
    ??例子2:大家可以回想一下斐波那契數(shù)列,如果我們用遞歸來表示的話,可以得到如下公式:f(i) = f(i-1) + f(i-2) ??看起來辰狡,好像R的復(fù)雜度也是O(n)锋叨,但是!但是宛篇!但是娃磺!他的復(fù)雜度為O(2^n)!因為當(dāng)它計算到第n個數(shù)時,需要調(diào)用該遞歸函數(shù)共(2^n - 1)次叫倍!
    ??如下圖所示(為了表示方便偷卧,我們在該數(shù)列前面加上一個數(shù)字0),我們要得到f(4)吆倦,那么需要計算f(2)和f(3)听诸,而計算f(3),我們又需要再算一遍f(2)蚕泽!從圖中可以看出晌梨,通過這種方式計算,調(diào)用遞歸函數(shù)次數(shù)是指數(shù)級上升的须妻!那么仔蝌,當(dāng)你回想問題3當(dāng)中的楊輝三角形時,會不會發(fā)現(xiàn)了什么異曲同工之處荒吏?那么敛惊,如何解決這種指數(shù)爆炸問題,是不是各位老爺也心中有數(shù)了呢绰更?(是的瞧挤,就是加入記憶機制,把之前計算結(jié)果全部保存下來即可~這時你會驚奇的發(fā)現(xiàn)儡湾,時間復(fù)雜度變成了n*O(1) = O(n)!
    斐波那契數(shù)列計算.png
  • 空間復(fù)雜度
    ??空間復(fù)雜度我們也是分兩部分來考慮特恬,一部分是遞歸相關(guān)的空間,另一部分是非遞歸相關(guān)的空間徐钠。
    ??遞歸相關(guān)空間:每次調(diào)用遞歸函數(shù)時鸵鸥,計算機都會從一個棧(stack)當(dāng)中給該函數(shù)分配一些空間,如丹皱,當(dāng)該函數(shù)執(zhí)行結(jié)束時,需要返回原先運算的地方宋税,這便需要一塊內(nèi)存來存儲之前中斷的位置(計算機需要該地址摊崭,才知道該函數(shù)執(zhí)行結(jié)束后,從哪里開始下一步運算)杰赛,還有傳遞給該遞歸函數(shù)的參數(shù)呢簸,以及該函數(shù)的局部變量等等,這些都是跟遞歸相關(guān)的空間使用。
    ??如果只是一個普通的函數(shù)根时,那么當(dāng)他運行完之后瘦赫,該空間就會被釋放,但是對于遞歸調(diào)用來說蛤迎,直到遇到邊界條件之前确虱,所有被調(diào)用到的遞歸函數(shù)占用的空間都不會被釋放,相當(dāng)于每調(diào)用一次遞歸函數(shù)替裆,空間使用是累計增加的校辩。所以如果不注意,便會遇到 “stack overflow”的場景辆童。
    ??對于問題1當(dāng)中的字符串翻轉(zhuǎn)問題來說宜咒,遞歸函數(shù)里只進行了一步交換元素位置的操作,所以需要的額外空間為O(1)把鉴,遞歸共進行了n次故黑,所以該算法的遞歸相關(guān)空間的復(fù)雜度為O(n)
    ??非遞歸相關(guān)空間:這部分空間指的是不直接跟遞歸相關(guān)的那部分空間使用情況庭砍。諸如全局變量(常儲存在堆(heap)當(dāng)中)场晶,如我們?yōu)榱丝朔貜?fù)計算問題,所加入的記憶機制逗威,還有算法程序的輸入以及輸出數(shù)據(jù)所占用的空間等峰搪。

尾遞歸(Tail Recursion)
??有一種遞歸較為特殊,叫尾遞歸凯旭。在此簡單講解一下:尾遞歸是一種遞歸概耻,其中遞歸調(diào)用是遞歸函數(shù)中的最后一條指令。 并且函數(shù)中應(yīng)該只有一個遞歸調(diào)用罐呼。說白了鞠柄,其他地方不能出現(xiàn)遞歸調(diào)用,只能是最后一句是遞歸調(diào)用嫉柴。那么厌杜,這么搞到底有什么好處呢?大家先來看兩個例子(功能很簡單计螺,列表求和):

def sum_non_tail_recursion(ls):
    """
    :type ls: List[int]
    :rtype: int, the sum of the input list.
    """
    if len(ls) == 0:
        return 0
    
    # not a tail recursion because it does some computation after the recursive call returned.
    return ls[0] + sum_non_tail_recursion(ls[1:])


def sum_tail_recursion(ls):
    """
    :type ls: List[int]
    :rtype: int, the sum of the input list.
    """
    def helper(ls, acc):
        if len(ls) == 0:
            return acc
        # this is a tail recursion because the final instruction is a recursive call.
        return helper(ls[1:], ls[0] + acc)
    
    return helper(ls, 0)

??第一個便不是尾遞歸夯尽,雖然遞歸調(diào)用只出現(xiàn)了一次且出現(xiàn)在最后一句,即return語句里登馒,但是匙握,該return里面還包含了加法運算,相當(dāng)于是先遞歸調(diào)用陈轿,再計算加法圈纺,然后把該加法結(jié)果返回秦忿。這樣子看蛾娶,最后一步運算確實不是遞歸調(diào)用灯谣。
??那么大家明白了什么是尾遞歸,可能就有疑惑了蛔琅,這么做到底有啥好處胎许,代碼變得略復(fù)雜了,并且還多了個參數(shù)揍愁,那么這么做到底能得到什么呢呐萨?答案就是,極大的降低了空間復(fù)雜度莽囤!各位懵逼的少年谬擦,且聽我慢慢道來:
??從前有座山,山上呢有座廟朽缎,廟里呢惨远,有個老和尚...(此處省略十萬八千字),于是话肖,琦玉老師對杰諾斯說到北秽,假設(shè),我們的遞歸函數(shù)為f(x)最筒,如果我們的遞歸調(diào)用如下:
f(x_1) -> f(x_2)->... -> f(x_n) ??那么正常情況下贺氓,代碼運行結(jié)束前,每次調(diào)用需要開辟一塊空間床蜘,最終需要開辟n塊空間才行辙培。即空間復(fù)雜度為O(n)。但是如果是尾遞歸呢邢锯?我們只需要開辟兩塊空間扬蕊,空間復(fù)雜度驟降為O(1)
??因為尾遞歸函數(shù)在遞歸結(jié)束時不需要再進行任何計算丹擎,直接將結(jié)果返回給上一層遞歸函數(shù)尾抑,那么也就意味著,遞歸到f(x_n)的時候蒂培,可以直接將返回值送給f(x_1)再愈,而不是f(x_{n-1})!那么护戳,當(dāng)我計算完f(x_{2})的時候践磅,f(x_{2})函數(shù)所占用的內(nèi)存便可以釋放掉,無需保留灸异!
??杰諾斯趕緊拿小本本記下來府适,心中想道,這可能就是老師這么強的原因肺樟,我要趕快記下來才行檐春。
??當(dāng)然,還有一點需要提醒一下大家么伯,那就是這種內(nèi)存優(yōu)化是需要看語言的疟暖。C 以及 C++ 都支持尾遞歸的這種優(yōu)化方式,但是據(jù)我所知田柔,Java 和 Python 好像還不行(當(dāng)然不排除以后會支持)俐巴。所以當(dāng)你所使用的語言不支持時,什么尾不尾的硬爆,那都是浮云一片~

總結(jié)
接下來說三點遞歸算法使用小貼士:

  1. 毫無疑問欣舵,首先寫下遞歸關(guān)系式。
  2. 只要有可能缀磕,咱就用記憶機制缘圈。
  3. 當(dāng)發(fā)生stack overflow 的時候,嘗試使用尾遞歸袜蚕。

附注
Answer 1. 你向瀕死的計算機冷笑道:“誰讓你只認識 0 和 1 兩個數(shù)呢”瞄勾。
Answer 2. 你掏出了另一臺閃閃發(fā)光的計算機弓柱,“對不起,我有新歡了⌒练酰”
Answer 3. 你語重心長、態(tài)度堅定的說到:“為了實現(xiàn)中華民族偉大復(fù)興萌京⊙媲幔”


各位看官老爺,希望可以不吝賜教狭归,如有不妥之處還望指出~
也熱切希望大家可以給個小贊夭坪,或點個關(guān)注!
在此謝謝各位爺勒~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末过椎,一起剝皮案震驚了整個濱河市室梅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌疚宇,老刑警劉巖亡鼠,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異敷待,居然都是意外死亡间涵,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進店門榜揖,熙熙樓的掌柜王于貴愁眉苦臉地迎上來勾哩,“玉大人抗蠢,你說我怎么就攤上這事∷祭停” “怎么了迅矛?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長潜叛。 經(jīng)常有香客問我秽褒,道長,這世上最難降的妖魔是什么威兜? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任销斟,我火速辦了婚禮,結(jié)果婚禮上椒舵,老公的妹妹穿的比我還像新娘蚂踊。我一直安慰自己,他們只是感情好逮栅,可當(dāng)我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布悴势。 她就那樣靜靜地躺著,像睡著了一般措伐。 火紅的嫁衣襯著肌膚如雪特纤。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天侥加,我揣著相機與錄音捧存,去河邊找鬼。 笑死担败,一個胖子當(dāng)著我的面吹牛昔穴,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播提前,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼吗货,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了狈网?” 一聲冷哼從身側(cè)響起宙搬,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎拓哺,沒想到半個月后勇垛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡士鸥,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年闲孤,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片烤礁。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡讼积,死狀恐怖肥照,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情勤众,我是刑警寧澤建峭,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站决摧,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏凑兰。R本人自食惡果不足惜掌桩,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望姑食。 院中可真熱鬧波岛,春花似錦、人聲如沸音半。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽曹鸠。三九已至煌茬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間彻桃,已是汗流浹背坛善。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留邻眷,地道東北人眠屎。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像肆饶,于是被迫代替她去往敵國和親改衩。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,781評論 2 354

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