算法初級(jí)-01-時(shí)間復(fù)雜度

年輕即出發(fā)...

簡書http://www.itdecent.cn/u/7110a2ba6f9e

知乎https://www.zhihu.com/people/zqtao23/posts

GitHub源碼https://github.com/zqtao2332

個(gè)人網(wǎng)站http://www.zqtaotao.cn/ (停止維護(hù)更新內(nèi)容,轉(zhuǎn)移簡書)

? 咆哮怪獸一枚...嗷嗷嗷...趁你現(xiàn)在還有時(shí)間,盡你自己最大的努力。努力做成你最想做的那件事,成為你最想成為的那種人,過著你最想過的那種生活。也許我們始終都只是一個(gè)小人物,但這并不妨礙我們選擇用什么樣的方式活下去,這個(gè)世界永遠(yuǎn)比你想的要更精彩。

最后:喜歡編程,對(duì)生活充滿激情



本節(jié)內(nèi)容預(yù)告

算法時(shí)間復(fù)雜度評(píng)定標(biāo)準(zhǔn)

實(shí)例1:一個(gè)簡單的理解時(shí)間復(fù)雜度的例子

實(shí)例2:冒泡排序

實(shí)例3:選擇排序

實(shí)例4:插入排序

實(shí)例5:對(duì)數(shù)器

實(shí)例6:理解遞歸行為,以及遞歸行為事件復(fù)雜度的估算

實(shí)例7:歸并排序

實(shí)例8:小和問題和逆序?qū)栴}



算法的評(píng)定標(biāo)準(zhǔn)有兩個(gè)-時(shí)間復(fù)雜度,空間復(fù)雜度

1、常數(shù)時(shí)間的操作:一個(gè)操作如果和數(shù)據(jù)量沒有關(guān)系,每次都是固定時(shí)間內(nèi)完成的操作,叫做常數(shù)操作。+

例如:

  1. 加減乘除
  2. 位運(yùn)算
  3. 數(shù)組尋址

這些操作的時(shí)間和樣本是數(shù)據(jù)量是沒有關(guān)系的

時(shí)間復(fù)雜度是一個(gè)算法流程中,評(píng)價(jià)常數(shù)操作數(shù)量的指標(biāo)。

常用O(讀作big O)來表示,具體,在常數(shù)操作數(shù)量的表達(dá)式中,只要高階項(xiàng),不要低階項(xiàng),也不要高階項(xiàng)的系數(shù),剩下的部分如果記為f(N), 那么時(shí)間復(fù)雜度為O(f(N))。

評(píng)價(jià)算法流程好壞

評(píng)價(jià)一個(gè)算法流程的好壞,先看時(shí)間復(fù)雜度的指標(biāo),然后在分析不同數(shù)據(jù)樣本下的實(shí)際運(yùn)行時(shí)間,也就是常數(shù)項(xiàng)時(shí)間。

如:第一種算法流程的時(shí)間復(fù)雜度指標(biāo)為N,所以他的算法好一些。(當(dāng)然數(shù)據(jù)樣本非常小,第二種好一些)

1562051795592.png

實(shí)例·1

一個(gè)簡單的理解時(shí)間復(fù)雜度的例子
一個(gè)有序數(shù)組A,另一個(gè)無序數(shù)組B,請(qǐng)打印B中的所有不在A中的數(shù),A數(shù) 組長度為N,B數(shù)組長度為M。

可以使用三種常用的算法流程來解決這個(gè)問題:

算法流程1:對(duì)于數(shù)組B中的每一個(gè)數(shù),都在A中通過遍歷的方式找一下;
算法流程2:對(duì)于數(shù)組B中的每一個(gè)數(shù),都在A中通過二分的方式找一下;
算法流程3:先把數(shù)組B排序,然后用類似外排的方式打印所有不在A中出現(xiàn) 的數(shù);
三個(gè)流程,三種時(shí)間復(fù)雜度的表達(dá)...
如何分析好壞?

流程1

時(shí)間復(fù)雜度:O(N*M)

流程2

二分法:每次排除一半的樣本數(shù)據(jù)

時(shí)間復(fù)雜度:O(M*logN)

ps : logN是以2為底

流程3

先排序 O(M*logM)

外排比較時(shí)間復(fù)雜度:O(N + M)

總結(jié),流程1性能最差;如果A長,B短,流程2好;如果A短,B長,流程3好;

實(shí)例2

冒泡排序

每次相鄰的兩個(gè)數(shù)進(jìn)行比較,然后交換(需要時(shí)交換),每一趟都找到了當(dāng)前樣本中的最大數(shù)
// 排序
    public static void bubbleSort(int[] arr) {
        if (arr == null || arr.length < 2)
            return;
        // 每一趟少一個(gè)最大元素,固定范圍
        for (int end = arr.length - 1; end > 0; end--) {
            for (int i = 0; i < end; i++) { // i 不能= end ,不然 i + 1 數(shù)組越界
                if (arr[i] > arr[i + 1])
                    swap(arr, i, i + 1);
            }
        }

        // 打印結(jié)果
        System.out.println(Arrays.toString(arr));
    }

    // 交換
    public static void swap(int[] arr, int i, int j) {
        // 交換時(shí)間復(fù)雜度:常數(shù)時(shí)間復(fù)雜度
        // 交換只涉及到了數(shù)組元素的尋址操作,這是常數(shù)時(shí)間操作
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

時(shí)間復(fù)雜度O(N^2),額外空間復(fù)雜度O(1)

實(shí)例3

選擇排序

每次選擇一個(gè)最小的放在該放的位置上
    public static void selectionSort(int[] arr) {
        if (arr == null || arr.length < 2)
            return;

        /*
            5 9 4 1 2
            第一次 i = 0, 循環(huán)完畢找到 數(shù)1 的下標(biāo),交換數(shù),將1 放到 第0 個(gè)位置上
            交換后結(jié)果:1 9 4 5 2

            第二次 i = 1, 循環(huán)完畢找到 數(shù)2 的下標(biāo),交換數(shù),將2 放到 第1 個(gè)位置上
            交換后結(jié)果:1 2 4 5 9

            依次類推 ...5 個(gè)數(shù),需要循環(huán)4次
         */
        // 外層規(guī)定循環(huán)范圍, 每次找到最小的數(shù),放在第 i 個(gè)位置上
        // N個(gè)元素,當(dāng)前N-1 個(gè)位置上的數(shù)已經(jīng)確定,則最后一個(gè)也是確定的,所以 i < arr.length - 1
        for (int i = 0; i < arr.length - 1; i++) {

            // 假設(shè)當(dāng)前 i 位置上的數(shù)就是最小數(shù)
            int minIndex = i;

            // 內(nèi)層尋找最小數(shù)下標(biāo)
            for (int j = i + 1; j < arr.length; j++) {
                minIndex = arr[minIndex] < arr[j] ? minIndex : j;
            }

            swap(arr, i, minIndex);
        }

        System.out.println(Arrays.toString(arr));
    }

    public static void swap(int[] arr, int i, int j) {
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

時(shí)間復(fù)雜度O(N^2),額外空間復(fù)雜度O(1)

實(shí)例4

插入排序

算法時(shí)間復(fù)雜度

插入排序和選擇排序,冒泡排序不同,它跟數(shù)據(jù)的狀態(tài)有關(guān)。

最好情況:數(shù)據(jù)是有序的如:1 2 3 4 5,O(N)

最壞情況:數(shù)據(jù)是反序的如:5 4 3 2 1, 求小到大序,則O(N^2)

時(shí)間復(fù)雜度O(N^2),額外空間復(fù)雜度O(1)

將數(shù)據(jù)組劃分為兩塊,一塊是已經(jīng)排序好的,一塊是待排序的
每一次從待排序數(shù)組中取出一個(gè)元素,進(jìn)行插入
插入選擇:從排序好的數(shù)組的最后一個(gè)元素開始進(jìn)行倒序遍歷,尋找它應(yīng)該存放的位置,進(jìn)行交換插入

實(shí)例5

對(duì)數(shù)器

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

測(cè)試一下插入排序

模型

import java.util.Arrays;

/**
 * @description: 排序隨機(jī)樣本產(chǎn)生器模型
 * @version: 1.0
 */
public class SortModel {
    // for test : 一個(gè)絕對(duì)正確的排序方法 --> 這里使用Java自帶方法
    public static void comparator(int[] arr) {
        Arrays.sort(arr);
    }

    // for test : 隨機(jī)樣本產(chǎn)生器
    public static int[] generateRandomArray(int maxSize, int maxValue) {

        // 隨機(jī)數(shù)組長度,隨機(jī)長度
        int[] arr = new int[(int) (Math.random() * (maxSize + 1))];
        // 隨機(jī)數(shù)據(jù)
        for (int i = 0; i < arr.length; i++) {
            // 兩個(gè)隨機(jī)數(shù)相減,可以隨機(jī)出負(fù)數(shù)
            arr[i] = (int) (Math.random() * (maxValue + 1)) - (int) (Math.random() * (maxValue + 1));
        }
        return arr;
    }

    // for test : 復(fù)制數(shù)組
    public static int[] copyArray(int[] arr) {
        if (arr == null)
            return null;
        int[] res = new int[arr.length];
        for (int i = 0; i < arr.length; i++)
            res[i] = arr[i];
        return res;
    }

    // for test : 實(shí)現(xiàn)一個(gè)對(duì)比方法
    public static boolean isEqual(int[] arr1, int[] arr2) {
        // 有一個(gè)數(shù)組為null
        if (arr1 == null && arr2 != null
                || arr1 != null && arr2 == null)
            return false;
        // 兩個(gè)數(shù)組都為null
        if (arr1 == null && arr2 == null) return true;

        // 兩個(gè)數(shù)組的長度不一致
        if (arr1.length != arr2.length) return false;

        // 對(duì)比兩個(gè)數(shù)組中的每一個(gè)元素
        for (int i = 0; i < arr1.length; i++) {
            if (arr1[i] != arr2[i])
                return false;
        }
        return true;
    }

       /*
        采用對(duì)數(shù)器來進(jìn)行驗(yàn)證
        1、一個(gè)你想要測(cè)試的方法 a
        2、一個(gè)絕對(duì)正確但是復(fù)雜度不好是方法 b
        3、實(shí)現(xiàn)一個(gè)隨機(jī)樣本產(chǎn)生器
        4、實(shí)現(xiàn)對(duì)比的方法
        5、把方法a和方法b比對(duì)很多次來驗(yàn)證方法a 是否正確
        6、如果有一個(gè)樣本使得對(duì)比出錯(cuò),打印出樣本,分析到底是哪個(gè)方法出錯(cuò)
        7、當(dāng)樣本數(shù)量很多時(shí)比對(duì)測(cè)試依然正確,可以確定方法a 正確
     */
}

測(cè)試

import cn.zqtao.learn.model.SortModel;

import java.util.Arrays;

/**
 * @description: 插入排序(相對(duì)工程中使用挺多)
 * <p>
 * 類似插牌
 * <p>
 * 將數(shù)據(jù)組劃分為兩塊,一塊是已經(jīng)排序好的,一塊是待排序的
 * <p>
 * 每一次從待排序數(shù)組中取出一個(gè)元素,進(jìn)行插入
 * 插入選擇:從排序好的數(shù)組的最后一個(gè)元素開始進(jìn)行倒序遍歷,尋找它應(yīng)該存放的位置,進(jìn)行交換插入
 * @version: 1.0
 */
public class Code_02_InsertionSort {

    public static void insertionSort(int[] arr) {

        if (arr == null || arr.length < 2)
            return;

        // 外層循環(huán)控制循環(huán)次數(shù), 默認(rèn)認(rèn)為第一個(gè)元素是已經(jīng)排序好的
        for (int i = 1; i < arr.length; i++) {
            // 對(duì)已經(jīng)排序好的數(shù)組進(jìn)行倒敘遍歷,查詢新元素的插入下標(biāo)
            for (int j = i - 1; j >= 0 && arr[j] > arr[j + 1]; j--) {
                swap(arr, j, j + 1);
            }
        }

    }

    // 不需要使用臨時(shí)變量,進(jìn)行交換
    public static void swap(int[] arr, int i, int j) {
        arr[i] = arr[i] ^ arr[j];
        arr[j] = arr[i] ^ arr[j];
        arr[i] = arr[i] ^ arr[j];
    }

    public static void main(String[] args) {
        int testTime = 5000;
        int maxSize = 10;
        int maxValue = 100;

        for (int i = 0; i < testTime; i++) {
            int[] randomArr = SortModel.generateRandomArray(maxSize, maxValue);
            int[] arr1 = SortModel.copyArray(randomArr);
            int[] arr2 = SortModel.copyArray(randomArr);

            insertionSort(arr1);
            SortModel.comparator(arr2);

            if (!SortModel.isEqual(arr1, arr2)) {
                System.out.println("錯(cuò)誤: " + Arrays.toString(randomArr));
                System.out.println("待測(cè)方法結(jié)果:" + Arrays.toString(arr1));
                System.out.println("正確方法結(jié)果:" + Arrays.toString(arr2));
                break;
            }
        }
    }

}

實(shí)例6

理解遞歸行為,以及遞歸行為事件復(fù)雜度的估算

master公式的使用

T(N) = aT(N/b) + O(N^d)* 滿足master此形式的,都可以使用下面的計(jì)算方法計(jì)算時(shí)間復(fù)雜度

  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)

ps: log(b, a) 表示以b 為底

補(bǔ)充閱讀:www.gocalf.com/blog/algorithm-complexity-and-mastertheorem.html

實(shí)例7

歸并排序

分治思想

左邊部分排序?yàn)橛行?/p>

右半部分排序?yàn)橛行?/p>

采用外排方式,合并兩個(gè)有序部分到一個(gè)臨時(shí)數(shù)組

復(fù)制回寫到原數(shù)組


import cn.zqtao.learn.model.SortModel;

import java.util.Arrays;

/**
 * @description: 歸并排序
 * <p>
 * 分治思想
 * <p>
 * 左半部分排序
 * 右半部分排序
 * <p>
 * 采用外排方式,合并兩個(gè)有序部分到一個(gè)臨時(shí)數(shù)組
 * <p>
 * 復(fù)制回原數(shù)組
 * @version: 1.0
 */
public class Code_03_MergerSort {

    public static void mergerSort(int[] arr) {
        if (arr == null || arr.length < 2)
            return;
        sortProcess(arr, 0, arr.length - 1);
//        System.out.println(Arrays.toString(arr));

    }

    public static void sortProcess(int[] arr, int L, int R) {
        if (L == R)
            return;
        int mid = L + ((R - L) >> 1); // 等同于 (L + R) / 2
        sortProcess(arr, L, mid);
        sortProcess(arr, mid + 1, R);

        merger(arr, L, mid, R); // O(N)
        // T(N) = 2 T(N/2) + O(N) 符合master公式
        // 所以時(shí)間復(fù)雜度: O(N * logN)
        // 空間復(fù)雜度:O(N)  臨時(shí)輔助數(shù)組
    }

    // 合并兩個(gè)有序部分
    private static void merger(int[] arr, int L, int mid, int R) {
        // 輔助數(shù)組
        int[] help = new int[R - L + 1];
        int i = 0;

        // 雙指針,分別指向第一個(gè)有序部分第一個(gè)數(shù)位置,第二個(gè)有序部分第一個(gè)數(shù)位置
        int p1 = L;
        int p2 = mid + 1;

        // 外排方式選填進(jìn)入臨時(shí)輔助數(shù)組的數(shù), 當(dāng)兩個(gè)指針任意一個(gè)越界時(shí)跳出
        while (p1 <= mid && p2 <= R) {
            help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
        }

        // 有且只有一個(gè)越界
        while (p1 <= mid)
            help[i++] = arr[p1++];
        while (p2 <= R)
            help[i++] = arr[p2++];

        // 回寫到原數(shù)組
        for (int j = 0; j < help.length; j++) {
            arr[L + j] = help[j];
        }
    }

    public static void main(String[] args) {
        int testTime = 5000;
        int maxSize = 10;
        int maxValue = 100;

        for (int i = 0; i < testTime; i++) {
            int[] randomArr = SortModel.generateRandomArray(maxSize, maxValue);
            int[] arr1 = SortModel.copyArray(randomArr);
            int[] arr2 = SortModel.copyArray(randomArr);

            mergerSort(arr1);
            SortModel.comparator(arr2);

            if (!SortModel.isEqual(arr1, arr2)) {
                System.out.println("錯(cuò)誤: " + Arrays.toString(randomArr));
                System.out.println("待測(cè)方法結(jié)果:" + Arrays.toString(arr1));
                System.out.println("正確方法結(jié)果:" + Arrays.toString(arr2));
                break;
            }
        }
    }
}

時(shí)間復(fù)雜度: O(N * logN)
空間復(fù)雜度:O(N)  臨時(shí)輔助數(shù)組

實(shí)例8

小和問題和逆序?qū)栴}
小和問題
在一個(gè)數(shù)組中,每一個(gè)數(shù)左邊比當(dāng)前數(shù)小的數(shù)累加起來,叫做這個(gè)數(shù)組的小和。求一個(gè)數(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
逆序?qū)栴} 在一個(gè)數(shù)組中,左邊的數(shù)如果比右邊的數(shù)大,則折兩個(gè)數(shù)構(gòu)成一個(gè)逆序?qū)?,?qǐng)打印所有逆序 對(duì)。

小和問題

import cn.zqtao.learn.model.SortModel;

import java.util.Arrays;

/**
 * @description: 小和問題
 * <p>
 * 小和問題
 * 在一個(gè)數(shù)組中,每一個(gè)數(shù)左邊比當(dāng)前數(shù)小的數(shù)累加起來,叫做這個(gè)數(shù)組的小和。求一個(gè)數(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
 * @version: 1.0
 */
public class Code_04_SmallSum {

    public static int smallSum(int[] arr) {
        if (arr == null || arr.length < 2) return 0;
        return mergesort(arr, 0, arr.length - 1);
    }


    public static int mergesort(int[] arr, int L, int R) {
        if (L == R) return 0;

        int mid = L + ((R - L) >> 1);
        return mergesort(arr, L, mid) +
                mergesort(arr, mid + 1, R) +
                merge(arr, L, mid, R);
        //左邊產(chǎn)生的小和+右邊產(chǎn)生的小和+合并產(chǎn)生的小和就是整個(gè)數(shù)組的小和
    }

    public static int merge(int[] arr, int L, int mid, int R) {
        // 輔助數(shù)組
        int[] help = new int[R - L + 1];
        int i = 0;

        // 雙指針
        int p1 = L;
        int p2 = mid + 1;

        int res = 0;
        while (p1 <= mid && p2 <= R) {
            // 左邊小于右邊,左邊數(shù) * 右邊比左邊大的數(shù)的個(gè)數(shù),因?yàn)橐呀?jīng)使用歸并排序進(jìn)行了排序
            // 所以右邊剩下的數(shù)也比左邊數(shù)大
            // 如左邊  1 3
            //   右邊  2 5 6
            // 1 < 2 ,此時(shí)右邊數(shù),5 6 一定都比1大, 則 小和結(jié)果是 1 * 3

            res = arr[p1] < arr[p2] ? arr[p1] * (R - p2 + 1) : 0;
            help[i++] = arr[p1] < arr[p2] ? arr[p1++] : arr[p2++];
        }

        while (p1 <= mid)
            help[i++] = arr[p1++];
        while (p2 <= R)
            help[i++] = arr[p2++];

        for (i = 0; i < help.length; i++)
            arr[L + i] = help[i];
        return res;
    }

    // for test 寫一個(gè)實(shí)現(xiàn)簡單,絕對(duì)正確但是時(shí)間復(fù)雜度高的算法
    public static int comparator(int[] arr) {
        if (arr == null || arr.length < 2) {
            return 0;
        }
        int res = 0;
        for (int i = 1; i < arr.length; i++) {
            for (int j = 0; j < i; j++) {
                res += arr[j] < arr[i] ? arr[j] : 0;
            }
        }
        return res;
    }

    public static void main(String[] args) {
        int testTime = 500000;
        int maxSize = 100;
        int maxValue = 100;
        boolean succeed = true;
        for (int i = 0; i < testTime; i++) {
            int[] randomArr = SortModel.generateRandomArray(maxSize, maxValue);
            int[] arr1 = SortModel.copyArray(randomArr);
            int[] arr2 = SortModel.copyArray(randomArr);
            if (!SortModel.isEqual(arr1, arr2)) {
                succeed = false;
                System.out.println("錯(cuò)誤: " + Arrays.toString(randomArr));
                System.out.println("待測(cè)方法結(jié)果:" + Arrays.toString(arr1));
                System.out.println("正確方法結(jié)果:" + Arrays.toString(arr2));
                break;
            }
        }
        System.out.println(succeed ? "Nice!" : "Fucking fucked!");
    }
}

逆序?qū)?/p>

import java.util.Arrays;
import java.util.Scanner;

/**
 * @description: 逆序?qū)栴}
 * 在一個(gè)數(shù)組中,左邊的數(shù)如果比右邊的數(shù)大,則兩個(gè)數(shù)構(gòu)成一個(gè)逆序?qū)?,?qǐng)打印所有逆序?qū)? * @version: 1.0
 */
public class Code_05_InvertedNum {

    public static void invertedNum(int[] arr) {
        if (arr == null || arr.length < 2) return;
        mergeSort(arr, 0, arr.length - 1);
    }

    public static void mergeSort(int[] arr, int L, int R) {
        if (L == R) return;

        int mid = L + ((R - L) >> 1);
        // 打印左邊逆序?qū)?        mergeSort(arr, L, mid);
        // 打印右邊逆序?qū)?        mergeSort(arr, mid + 1, R);
        // 打印合并后的逆序?qū)?        merge(arr, L, mid, R);
    }

    public static void merge(int[] arr, int L, int mid, int R) {
        // 輔助數(shù)組
        int[] help = new int[R - L + 1];
        int i = 0;

        int p1 = L;
        int p2 = mid + 1;

        while (p1 <= mid && p2 <= R) {
            if (arr[p1] > arr[p2]) {
                for (int j = p2; j <= R; j++) {
                    System.out.println("逆序?qū)Γ? + arr[p1] + "--" + arr[j]);
                }
            }
            help[i++] = arr[p1] > arr[p2] ? arr[p1++] : arr[p2++];
        }

        while (p1 <= mid)
            help[i++] = arr[p1++];
        while (p2 <= R)
            help[i++] = arr[p2++];

        for (i = 0; i < help.length; i++)
            arr[L + i] = help[i];
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        while (sc.hasNext()) {
            String[] str = sc.nextLine().split(",");
            int[] num = new int[str.length];
            for (int i = 0; i < str.length; i++) {
                num[i] = Integer.parseInt(str[i]);
            }
            invertedNum(num);
        }
        sc.close();
    }

}

以上都是算法課程學(xué)習(xí)總結(jié)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容