時間復(fù)雜度的認(rèn)識,遞歸,歸并排序

時間復(fù)雜度

算法的時間復(fù)雜度是一個函數(shù),它定性描述了該算法的運行時間。時間復(fù)雜度常用O(讀作big O)來表示,不包括這個函數(shù)的低階項和首項(高階項)的系數(shù)。
來思考一個問題:

有一個有序數(shù)組A,以及另一個無序數(shù)組B,請打印出B中的所有不在A中的數(shù)。

對于這個問題可以使用以下幾種思路解決:
思路一:對于B中的每一個數(shù)都通過遍歷數(shù)組A來判斷

public class Solution{
    public static void printMethod1(int[] arrA,int[] arrB){
        for(int i = 0;i<arrB.length;i++){
            for(int j = 0;j<arrA.length;j++){
                if(arrA[j] == arrB[i])
                    break;
                if(j == arrA.length-1 && arrA[j] != arrB[i])
                    System.out.println(arrB[i]);
            }
        }
    }
}

在遍歷嵌套的內(nèi)部,進行了數(shù)組的尋址,以及比較等操作,這樣的操作是一個常數(shù)時間的操作,常數(shù)操作的時間復(fù)雜度記作:O(1)。對于printMethod1方法,執(zhí)行算法的時間和數(shù)組A及數(shù)組B的樣本量有關(guān),假設(shè)A中有N個數(shù),B中有M個數(shù),兩層for循環(huán)實際上就是將數(shù)組A和數(shù)組B遍歷一遍。那么該算法的時間復(fù)雜度為(M×N)O(1) ,可以表示為O(M×N)

思路二:對于B中的每一個數(shù),都在A中通過二分查找判斷

public class Solution{
    public static void printMethod2(int[] arrA,int[] arrB){
        for(int i = 0;i<arrB.length;i++){
            if(!bSearch(arrA,0,arrA.length-1,arrB[i]))
                System.out.println(arrB[i]);
        }
        
    }
    public static boolean bSearch(int []arr,int L,int R,int target){
        if(L < R){ 
            int mid = L + ((R-L)>>1) ;
            if(target == arr[mid]){
                return true;
            }else if(target < arr[mid]){
                return bSearch(arr,L,mid-1,target);
            }else{
                return bSearch(arr,mid+1,R,target);
            }
        }else if(L == R){
            return arr[L]==target?true:false;
        }else{
            return false;
        }
    }
}

第二種算法,可以分解為兩個過程,第一個過程是對數(shù)組B遍歷的過程,第二個過程是對數(shù)組A二分搜索的過程,其他的比較兩個數(shù),數(shù)組尋址等操作都可以記作O(1)。二分搜索同一棵完全二叉樹一樣,其時間復(fù)雜度和二叉樹的高度有關(guān)為為O(logN),對數(shù)組B遍歷的時間復(fù)雜度為O(M),也就是說共需要M次O(logN)的時間復(fù)雜度,為O(M logN)

思路三:對數(shù)組B進行排序,再利用外排的方式篩選數(shù)據(jù)。


public class Solution{

    public static void printMethod3(int[] arrA,int[] arrB){
        // 先對數(shù)組B進行排序
        mergeSort(arrB);
        // 利用外排的方式進行篩選判斷
        int p1 = 0;
        int p2 = 0;
        int lenA = arrA.length;
        int lenB = arrB.length;
        while(p1 <= lenA-1 && p2 <= lenB-1){
            if(arrB[p2]<arrA[p1] && p1 <= lenA-1 && p2 <= lenB-1){
                System.out.println(arrB[p2]);
                p2++;
            }
            if(arrB[p2] == arrA[p1] && p1 <= lenA-1 && p2 <= lenB-1 ){
                p2++;
            }
            if(arrB[p2] > arrA[p1] && p1 <= lenA-1 && p2 <= lenB-1){
                p1++;
            }
        }
        
        while(p2 <= lenB-1){
            System.out.println(arrB[p2++]);
        }
    }
    // 
    public static void mergeSort(int []arr){
        if (arr == null || arr.length < 2) {
            return;
        }
        sort(arr,0,arr.length-1);
    }
    public static void sort(int []arr,int L,int R){
        if(L == R)
            return; 
        
        int mid = L + ((R-L)>>1);
        sort(arr,L,mid);
        sort(arr,mid+1,R);
        merge(arr,L,mid,R);
    }
    public static void merge(int []arr,int L,int mid,int R){
        int p1 = L;
        int p2 = mid+1;
        int []temp = new int[R-L+1];
        int i = 0;
        while(p1<=mid && p2<=R){
            temp[i++] = arr[p1]<arr[p2]?arr[p1++]:arr[p2++];
        }
        while(p1<=mid){
            temp[i++] = arr[p1++];
        }
        while(p2<=R){
            temp[i++] = arr[p2++];
        }
        
        for(i = 0;i<temp.length;i++){
            arr[L+i] = temp[i];
        }
    }
}

對于第三個算法,對數(shù)組B先進行排序,這里面使用的排序為歸并排序(merge-sort),歸并排序的時間復(fù)雜度為O(N logN),對數(shù)組B排好序后,利用兩個變量p1,p2分別指向數(shù)組A和數(shù)組B的第一個數(shù)
while(p1 <= lenA-1 && p2 <= lenB-1)
在上面的循環(huán)條件內(nèi),如果p2指向的數(shù)小于p1指向的數(shù),那么打印p2指向的數(shù)字并移動p2;如果p2指向的數(shù)等于p1指向的數(shù),那么移動p2不打印;如果p2指向的數(shù)大于p1指向的數(shù),那么移動p1不打印。這樣利用p1,p2對兩個數(shù)組依次外排,就可以打印出符合條件的數(shù)。這個過程,最壞的情況需要遍歷一遍數(shù)組A和數(shù)組B,所以時間復(fù)雜度顯而易見為O(M+N)。那么該算法的時間復(fù)雜度可以表示為:O(M logM)+O(M+N)

三種算法時間復(fù)雜度的比較

第一種算法的時間復(fù)雜度為O(M×N),第二種算法的時間復(fù)雜度為O(M logN),如果了解過指數(shù)爆炸,那么就知道第二種算法要遠遠好于第一種算法。當(dāng)N的數(shù)量級達到幾千萬,幾億時logN還沒有超過100。那么對于第二種算法和第三種算法,哪種算法更好呢?這就沒有辦法比較了,第三種算法跟數(shù)組B的數(shù)據(jù)量有很大關(guān)系,當(dāng)數(shù)據(jù)量M很大時,這個算法的評價指標(biāo)趨近為O(N logN)級別的算法,當(dāng)M的值很小時,這個算法的評價指標(biāo)可以看做一個O(N)級別的算法。不過第二種算法和第三種算法的時間復(fù)雜度肯定是優(yōu)于算法一的。

冒泡排序,選擇排序與插入排序的時間復(fù)雜度分析

冒泡排序

public class BubbleSort{
    public static void sort(int []arr){
        //每次將最大的數(shù)字排到最后,一共需要排len-1次
        for(int i = 0;i < arr.length-1;i++){
            // 需要交換的次數(shù)
            for(int j = 0;j<arr.length-1-i;j++){
                if(arr[j] > arr[j+1])
                    swap(arr,j,j+1);
            }
        }
    }
    
    public static void swap(int []arr,int i,int j){
        if(i>arr.length-1 || j>arr.length-1 ||i==j)
            return;
        
        arr[i] = arr[i]^arr[j];
        arr[j] = arr[i]^arr[j];
        arr[i] = arr[i]^arr[j];
    }
}

冒泡排序的時間復(fù)雜度顯而易見為O(N2)

選擇排序

public class SelectionSort{
    public static void sort(int []arr){
        for(int i = 0;i<arr.length;i++){
            int minIndex = i;
            for(int j = i+1;j<arr.length;j++){
                if(arr[j]<arr[minIndex])
                    minIndex = j;
            }
            swap(arr,i,minIndex);
        }
    }
    
    public static void swap(int []arr,int i,int j){
        if(i>arr.length-1 || j>arr.length-1 || i==j)
            return;
        
        arr[i] = arr[i]^arr[j];
        arr[j] = arr[i]^arr[j];
        arr[i] = arr[i]^arr[j];
    }
}

選擇排序使用一個minIndex來記錄最小值的下標(biāo),每次將最小值排序出來,因為有兩次遍歷數(shù)組的過程,所以這個選擇排序算法的時間復(fù)雜度也是O(N2)。

插入排序

public class InsertionSort{
    public static void sort(int []arr){
        for(int i = 1;i<arr.length;i++){
            for(int j = i;j>=1 && arr[j]<arr[j-1];j--){
                swap(arr,j,j-1);
            }
            
        }
    }
    
    public static void swap(int []arr,int i,int j){
        if(i>arr.length-1 || j>arr.length-1 || i==j)
            return;
        
        arr[i] = arr[i]^arr[j];
        arr[j] = arr[i]^arr[j];
        arr[i] = arr[i]^arr[j];
    }
}

插入排序又叫撲克牌排序,它的排序過程和我們抓牌并理牌的過程一樣。插入排序和冒泡以及選擇排序不同,冒泡和選擇排序是一個穩(wěn)定的時間復(fù)雜度,但是插入排序不同,試想一個數(shù)組如果是已經(jīng)排好序的數(shù)組,那么插入排序只需要依次插入,遍歷了一個循環(huán)即可,那么時間復(fù)雜度就是O(n),如果一個數(shù)組為逆序數(shù)組,那么插入排序則退化成了O(N2)的算法。而冒泡排序和選擇排序則不會依賴數(shù)組的分布狀況,無論怎樣都會遍歷N2次。所以插入排序在當(dāng)前也是一個非常有意義的排序,如果一個數(shù)組是一個近乎有序的數(shù)組,那么插入排序的速度就會很快。

遞歸的本質(zhì)與master公式的使用

設(shè)計一個算法,結(jié)果返回一個無序數(shù)組的最大值

非遞歸思路:

public class Solution{
    public static int findMax(int []arr){
        if(arr == null)
            return -1;
        
        int maxIndex = 0;
        for(int i = 1;i<arr.length;i++){
            if(arr[i]>arr[maxIndex])
                maxIndex = i;
        }
        return arr[maxIndex];
    }
}

遞歸思路:

public class Solution{
    public static int findMax(int []arr,int L,int R){
        if(arr == null)
            return -1;

        if(L==R)
            return arr[L];

        int mid = L+((R-L)>>1);
        int maxInLeft = findMax(arr,L,mid);
        int maxInRight = findMax(arr,mid+1,R);
        return maxInLeft > maxInRight?maxInLeft:maxInRight;
    }
}

在寫遞歸程序的時候,第一步是分治,將一個問題化成更小的一個問題,對于本題,把求出一個數(shù)組中最大值這個問題轉(zhuǎn)化成了將一個數(shù)組分成兩半兒,左邊求出最大值,右邊也求出最大值,左邊的最大值和右邊的最大值比較出一個最大值。這是分治的過程,第二步就是為遞歸程序設(shè)計一個終止點的返回值,當(dāng)遞歸到最簡單的情況時,返回什么。遞歸的本質(zhì)則是系統(tǒng)的壓棧。

程序自上而下執(zhí)行,執(zhí)行到int maxInLeft = findMax(arr,L,mid);時,系統(tǒng)棧會記錄程序執(zhí)行到第幾行,有哪些變量等信息,并把這些信息壓入到系統(tǒng)棧中,保存好信息以后程序進入到findMax方法,等到L==R時,終于得到了返回值,系統(tǒng)棧開始pop,最后進棧的最先還原,因為棧記錄了所有信息,所以得以還原現(xiàn)場,當(dāng)maxInLeft拿到返回值后,系統(tǒng)棧也沒有殘留的信息了,程序就可以繼續(xù)往下面執(zhí)行。

master公式

一個遞歸過程,如何去分析它的時間復(fù)雜度?對于將一個過程分解成均等子過程的遞歸來說,可以使用master公式來計算時間復(fù)雜度。

master公式:T(N) = a*T(N/b) + O(N^d)
1) log(b,a) > d -> 復(fù)雜度為O(N^log(b,a))
2) log(b,a) = d -> 復(fù)雜度為O(N^d * logN)
3) log(b,a) < d -> 復(fù)雜度為O(N^d)

b代表的含義是遞歸分解成了幾個子過程,a代表的含義是一次遞歸子過程執(zhí)行了幾次,O(N^d)表示除去遞歸外,額外需要的過程的時間復(fù)雜度。
用遞歸求數(shù)組最大值問題中,master通式為:2T(N/2)+O(1)
所以該式子滿足條件二:log(b,a) > d。所以這個求最大值的時間復(fù)雜度為:O(N)。

歸并排序與歸并排序時間復(fù)雜度分析、額外空間復(fù)雜度分析

歸并排序的思路:將一個數(shù)組,分治成左數(shù)組和右數(shù)組,對左,右數(shù)組分別排序,然后利用外排的方式,使用一個輔助數(shù)組將兩個數(shù)組進行merge操作。代碼如下:

    public static void mergeSort(int []arr){
        if (arr == null || arr.length < 2) {
            return;
        }
        sort(arr,0,arr.length-1);
    }
    public static void sort(int []arr,int L,int R){
        if(L == R)
            return; 
        
        int mid = L + ((R-L)>>1);
        sort(arr,L,mid);
        sort(arr,mid+1,R);
        merge(arr,L,mid,R);
    }
    public static void merge(int []arr,int L,int mid,int R){
        int p1 = L;
        int p2 = mid+1;
        int []temp = new int[R-L+1];
        int i = 0;
        while(p1<=mid && p2<=R){
            temp[i++] = arr[p1]<arr[p2]?arr[p1++]:arr[p2++];
        }
        while(p1<=mid){
            temp[i++] = arr[p1++];
        }
        while(p2<=R){
            temp[i++] = arr[p2++];
        }
        
        for(i = 0;i<temp.length;i++){
            arr[L+i] = temp[i];
        }
    }

歸并排序中利用了非常重要的遞歸思想,對歸并排序的時間復(fù)雜度進行分析為:T(N) = 2T(N/2) + O(N)。遞歸的過程分解了執(zhí)行兩次的子過程,并且兩次sort后,還需要進行merge操作,這里面需要一個額外空間的數(shù)組,并把兩個sort好的數(shù)組進行遍歷,兩個數(shù)組的總長度為N,所以除去遞歸,額外需要的時間復(fù)雜度為O(N),因為log(b,a) = d,所以歸并排序的時間復(fù)雜度為:O(N logN)。什么是額外空間復(fù)雜度呢?空間復(fù)雜度(Space Complexity)是對一個算法在運行過程中臨時占用存儲空間的大小,額外空間復(fù)雜度則是,刨去算法本身程序所占的空間,輸入數(shù)據(jù)所占的空間外,額外的輔助變量所需要的空間與輸入數(shù)據(jù)量N的關(guān)系。歸并排序在merge過程中,需要一個長度為N的輔助數(shù)組來完成,所以歸并排序的額外空間復(fù)雜度為O(N)。下表為幾種常見的排序的時間復(fù)雜度與額外空間復(fù)雜度:


image.png

版權(quán)聲明:本文為CSDN博主「-出發(fā)-」的原創(chuàng)文章,遵循 CC 4.0 BY-SA 版權(quán)協(xié)議,轉(zhuǎn)載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/happyjacob/article/details/84620880

對數(shù)器

對數(shù)器的概念和使用

1:有一個你想要測的方法a,
2:實現(xiàn)一個絕對正確但是復(fù)雜度不好的方法b,
3:實現(xiàn)一個隨機樣本產(chǎn)生器
4:實現(xiàn)比對的方法
5:把方法a和方法b比對很多次來驗證方法a是否正確。
6:如果有一個樣本使得比對出錯,打印樣本分析是哪個方法出錯
7:當(dāng)樣本數(shù)量很多時比對測試依然正確,可以確定方法a已經(jīng)正確。

如何驗證歸并排序的結(jié)果是絕對正確的:
設(shè)計對數(shù)器的代碼如下:

    // test 實現(xiàn)一個絕對正確的,同要測試的算法實現(xiàn)相同功能的方法
    public static void comparator(int[]arr){
        Arrays.sort(arr);
    }

    // test 實現(xiàn)一個隨機樣本生成器
    public static int[] generateRandomArray(int maxSize,int maxValue){
        // 最多生成容量為 maxSize長度的數(shù)組
       int []arr = new int[(int)((maxSize+1)*Math.random())];
       for(int i = 0;i<arr.length;i++){
           // 數(shù)組每一個數(shù)的范圍為:(-maxValue,maxValue)
           arr[i] = (int)((maxValue+1)*Math.random() - (maxValue*Math.random()));
       }
       return arr;
    }

    // test 判斷兩數(shù)組是否相等
    public static boolean isEqual(int []arr1,int []arr2){
        if(arr1 == null && arr2 == null)
            return true;
        if(arr1 == null && arr2 !=null || arr1 !=null && arr2 == null)
            return false;
        if(arr1.length != arr2.length)
            return false;

        for(int i = 0;i<arr1.length;i++){
            if(arr1[i] != arr2[i])
                return false;
        }
        return true;
    }

    // test 打印
    public static void printArray(int []arr){
        if(arr == null)
            return;
        for(int i = 0;i<arr.length;i++){
            System.out.print(arr[i]+ " ");
        }
        System.out.println();
    }

    // test 復(fù)制數(shù)組
    public static int[] copyArray(int []arr){
        if(arr == null)
            return null;

        int [] copyArr = new int[arr.length];
        for(int i = 0;i<arr.length;i++){
            copyArr[i] = arr[i];
        }
        return copyArr;
    }
    // 測試mergeSort是否正確0
    public static void main(String[]args){
        int testTime = 5000;
        int maxSize = 100;
        int maxValue = 100;
        boolean succeed = true;
        for(int i = 0;i<testTime;i++){
            int [] arr1 = generateRandomArray(maxSize,maxValue);
            int [] arr2 = copyArray(arr1);
            mergeSort(arr1);
            comparator(arr2);
            if(!isEqual(arr1,arr2)){
                succeed = false;
                printArray(arr1);
                printArray(arr2);
                break;
            }
        }
        System.out.println(succeed?"Nice":"Wrong");
    }

對數(shù)器用大樣本來測試算法的正確性,可以對算法進行驗證,如果設(shè)計的算法有誤,還可以打印出導(dǎo)致算法與comparator不一致的樣本,來進行對比觀察。

小和與逆序?qū)栴}

小和問題:

在一個數(shù)組中,每一個數(shù)左邊比當(dāng)前數(shù)小的數(shù)累加起來,叫做這個數(shù)組的小和。求一個數(shù)組
的小和。
例子:

[1,3,4,2,5]
1左邊比1小的數(shù),沒有;
3左邊比3小的數(shù),1;
4左邊比4小的數(shù),1、3;
2左邊比2小的數(shù),1;
5左邊比5小的數(shù),1、3、4、2;
所以小和為1+1+3+1+1+3+4+2=16

解決思路:
可以使用對數(shù)組每一個值遍歷求得,但是時間復(fù)雜度為O(N2)。可以使用歸并排序,代碼如下:

public class SmallSum{
    public static int smallSum(int[] arr){
        return mergeSort(arr);
    }
    public static int mergeSort(int[] arr){
        return sort(arr,0,arr.length-1);
    }
    public static int sort(int[] arr,int L,int R){
        
        if(L == R)
            return 0;
        int mid = L+((R-L)>>1);
        
        return sort(arr,L,mid)
                +sort(arr,mid+1,R)
                +merge(arr,L,mid,R);
    }
    public static int merge(int[] arr,int L,int mid,int R){
        int p1 = L;
        int p2 = mid+1;
        int[] temp = new int[R-L+1];
        int i = 0;
        int result = 0;
        while(p1<=mid && p2<=R){
            result += arr[p1]<arr[p2]?(R-p2+1)*arr[p1]:0;
            temp[i++] = arr[p1]<arr[p2]?arr[p1++]:arr[p2++];
        }
        // only one can run
        while(p1<=mid){
            temp[i++] = arr[p1++];
        }
        // only one can run
        while(p2<=R){
            temp[i++] = arr[p2++];
        }
        
        // temp -> arr
        for(i = 0;i<temp.length;i++){
            arr[L+i] = temp[i];
        }
        return result;
    }
}

除了小和問題外,逆序?qū)栴}也可以通過歸并排序巧妙解決,

來源于劍指offer:

在數(shù)組中的兩個數(shù)字,如果前面一個數(shù)字大于后面的數(shù)字,則這兩個數(shù)字組成一個逆序?qū)Α?輸入一個數(shù)組,求出這個數(shù)組中的逆序?qū)Φ目倲?shù)P。
并將P對1000000007取模的結(jié)果輸出。 即輸出P%1000000007

逆序?qū)托『蛦栴}的思路是一樣的,代碼如下:

public class Solution{
    int result = 0;
    public int InversePairs(int[]array){
        mergeSort(array);
        
        return result;
    }
    // 
    public void mergeSort(int [] arr){
        sort(arr,0,arr.length-1);
    }
    // 
    public void sort(int []arr,int L,int R){
        if(L == R)
            return;
        
        int mid = L + ((R-L)>>1);
        sort(arr,L,mid);
        sort(arr,mid+1,R);
        merge(arr,L,mid,R);
    }
    // merge
    public void merge(int[]arr,int L,int mid,int R){
        
        int p1 = L;
        int p2 = mid+1;
        int [] temp = new int[R-L+1];
        int i = 0;
        while(p1<=mid && p2<=R){
            result=arr[p1]>arr[p2]?(result+(R-p2+1))%1000000007:result;
            temp[i++] = arr[p1]>arr[p2]?arr[p1++]:arr[p2++];
        }
        
        // only one can  execute
        while(p1<=mid){
            temp[i++] = arr[p1++];
        }
        // only one can execute
        while(p2<=R){
            temp[i++] = arr[p2++];
        }
        
        // temp -> arr
        for(i = 0;i<temp.length;i++){
            arr[L+i] = temp[i];
        }
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,673評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,610評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,668評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,004評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,173評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,705評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,426評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,656評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,833評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評論 0 28
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,371評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,621評論 2 380

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