国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频

一次搞定九大排序策略

共 37542字,需瀏覽 76分鐘

 ·

2021-08-13 16:13

點(diǎn)擊上方 三分鐘學(xué)前端,關(guān)注公眾號

回復(fù)交流,加入前端編程面試算法每日一題群


面試官也在看的前端面試資料

14.1 冒泡排序

原理:

從左到右,相鄰元素進(jìn)行比較,如果前一個元素值大于后一個元素值(正序),則交換,這樣一輪下來,將最大的數(shù)在最右邊冒泡出來。這樣一輪一輪下來,最后實(shí)現(xiàn)從小到大排序。

動圖演示:

代碼實(shí)現(xiàn):

function bubbleSort(arr{
    for (let i = 0; i < arr.length; i++) {
        for (let j = 0; j < arr.length - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                const temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
            }
        }
    }
}

// 改進(jìn)冒泡排序
function bubbleSort1(arr{
    for (let i = 0; i < arr.length; i++) {
        // 提前退出冒泡循環(huán)的標(biāo)識位
        let flag = false;
        for (let j = 0; j < arr.length - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                const temp = arr[j];
                arr[j] = arr[j + 1];
                arr[j + 1] = temp;
                flag = true;
                // 表示發(fā)生了數(shù)據(jù)交換
            }
        }
        // 沒有數(shù)據(jù)交換
        if(!flag) break
    }
}


// 測試
let arr = [13254]
bubbleSort(arr)
console.log(arr) // [1, 2, 3, 4, 5]

let arr1 = [13254]
bubbleSort1(arr1)
console.log(arr1) // [1, 2, 3, 4, 5]

復(fù)雜度分析:

  • 時間復(fù)雜度:最好時間復(fù)雜度 O(n),平均時間復(fù)雜度 O(n^2^)
  • 空間復(fù)雜度:O(1)

14.2 選擇排序

原理

從未排序的序列中找到最大(或最小的)放在已排序序列的末尾(為空則放在起始位置),重復(fù)該操作,知道所有數(shù)據(jù)都已放入已排序序列中。

動態(tài)演示

代碼實(shí)現(xiàn)

function selectionSort(arr{
  let length = arr.length,
      indexMin
  for(let i = 0; i < length - 1; i++) {
    indexMin = i
    for(let j = i; j < length; j++) {
      if(arr[indexMin] > arr[j]) {
        indexMin = j
      }
    }
    if(i !== indexMin) {
      let temp = arr[i]
      arr[i] = arr[indexMin]
      arr[indexMin] = temp
    }
  }
}

// 測試
let arr = [13254]
selectionSort(arr)
console.log(arr) // [1, 2, 3, 4, 5]

復(fù)雜度分析

**時間復(fù)雜度:**O(n^2^)

**空間復(fù)雜度:**O(1)

14.3 歸并排序

原理

它采用了分治策略,將數(shù)組分成2個較小的數(shù)組,然后每個數(shù)組再分成兩個更小的數(shù)組,直至每個數(shù)組里只包含一個元素,然后將小數(shù)組不斷的合并成較大的數(shù)組,直至只剩下一個數(shù)組,就是排序完成后的數(shù)組序列。

實(shí)現(xiàn)步驟:

  • 將原始序列平分成兩個小數(shù)組
  • 判斷小數(shù)組長度是否為1,不為1則繼續(xù)分裂
  • 原始數(shù)組被分稱了長度為1的多個小數(shù)組,然后合并相鄰小數(shù)組(有序合并)
  • 不斷合并小數(shù)組,直到合并稱一個數(shù)組,則為排序后的數(shù)組序列

動圖演示

代碼實(shí)現(xiàn)

function mergeSort(arr{
  let array = mergeSortRec(arr)
  return array
}

// 若分裂后的兩個數(shù)組長度不為 1,則繼續(xù)分裂
// 直到分裂后的數(shù)組長度都為 1,
// 然后合并小數(shù)組
function mergeSortRec(arr{
  let length = arr.length
  if(length === 1) {
    return arr
  }
  let mid = Math.floor(length / 2),
      left = arr.slice(0, mid),
      right = arr.slice(mid, length)
  return merge(mergeSortRec(left), mergeSortRec(right))
}

// 順序合并兩個小數(shù)組left、right 到 result
function merge(left, right{
  let result = [],
      ileft = 0,
      iright = 0
  while(ileft < left.length && iright < right.length) {
    if(left[ileft] < right[iright]){
      result.push(left[ileft ++])
    } else {
      result.push(right[iright ++])
    }
  }
  while(ileft < left.length) {
    result.push(left[ileft ++])
  }
  while(iright < right.length) {
    result.push(right[iright ++])
  }
  return result
}

// 測試
let arr = [13254]
console.log(mergeSort(arr)) // [1, 2, 3, 4, 5]

復(fù)雜度分析

**時間復(fù)雜度:**O(nlog~2~n)

**空間復(fù)雜度:**O(n)

14.4 快速排序

原理

和歸并排序一致,它也使用了分治策略的思想,它也將數(shù)組分成一個個小數(shù)組,但與歸并不同的是,它實(shí)際上并沒有將它們分隔開。

快排使用了分治策略的思想,所謂分治,顧名思義,就是分而治之,將一個復(fù)雜的問題,分成兩個或多個相似的子問題,在把子問題分成更小的子問題,直到更小的子問題可以簡單求解,求解子問題,則原問題的解則為子問題解的合并。

快排的過程簡單的說只有三步:

  • 首先從序列中選取一個數(shù)作為基準(zhǔn)數(shù)
  • 將比這個數(shù)大的數(shù)全部放到它的右邊,把小于或者等于它的數(shù)全部放到它的左邊 (一次快排 partition
  • 然后分別對基準(zhǔn)的左右兩邊重復(fù)以上的操作,直到數(shù)組完全排序

具體按以下步驟實(shí)現(xiàn):

  • 1,創(chuàng)建兩個指針分別指向數(shù)組的最左端以及最右端
  • 2,在數(shù)組中任意取出一個元素作為基準(zhǔn)
  • 3,左指針開始向右移動,遇到比基準(zhǔn)大的停止
  • 4,右指針開始向左移動,遇到比基準(zhǔn)小的元素停止,交換左右指針?biāo)赶虻脑?/section>
  • 5,重復(fù)3,4,直到左指針超過右指針,此時,比基準(zhǔn)小的值就都會放在基準(zhǔn)的左邊,比基準(zhǔn)大的值會出現(xiàn)在基準(zhǔn)的右邊
  • 6,然后分別對基準(zhǔn)的左右兩邊重復(fù)以上的操作,直到數(shù)組完全排序

注意這里的基準(zhǔn)該如何選擇喃?最簡單的一種做法是每次都是選擇最左邊的元素作為基準(zhǔn):

但這對幾乎已經(jīng)有序的序列來說,并不是最好的選擇,它將會導(dǎo)致算法的最壞表現(xiàn)。還有一種做法,就是選擇中間的數(shù)或通過 Math.random() 來隨機(jī)選取一個數(shù)作為基準(zhǔn),下面的代碼實(shí)現(xiàn)就是以隨機(jī)數(shù)作為基準(zhǔn)。

代碼實(shí)現(xiàn)

let quickSort = (arr) => {
  quick(arr, 0 , arr.length - 1)
}

let quick = (arr, left, right) => {
  let index
  if(left < right) {
    // 劃分?jǐn)?shù)組
    index = partition(arr, left, right)
    if(left < index - 1) {
      quick(arr, left, index - 1)
    }
    if(index < right) {
      quick(arr, index, right)
    }
  }
}

// 一次快排
let partition = (arr, left, right) => {
  // 取中間項為基準(zhǔn)
  var datum = arr[Math.floor(Math.random() * (right - left + 1)) + left],
      i = left,
      j = right
  // 開始調(diào)整
  while(i <= j) {
    
    // 左指針右移
    while(arr[i] < datum) {
      i++
    }
    
    // 右指針左移
    while(arr[j] > datum) {
      j--
    }
    
    // 交換
    if(i <= j) {
      swap(arr, i, j)
      i += 1
      j -= 1
    }
  }
  return i
}

// 交換
let swap = (arr, i , j) => {
    let temp = arr[i]
    arr[i] = arr[j]
    arr[j] = temp
}

// 測試
let arr = [13254]
quickSort(arr)
console.log(arr) // [1, 2, 3, 4, 5]
// 第 2 個最大值
console.log(arr[arr.length - 2])  // 4

快排是從小到大排序,所以第 k 個最大值在 n-k 位置上

復(fù)雜度分析

  • 時間復(fù)雜度:O(nlog~2~n)
  • 空間復(fù)雜度:O(nlog~2~n)

14.5 希爾排序

1959年Shell發(fā)明,第一個突破 O(n^2^) 的排序算法,是簡單插入排序的改進(jìn)版。它與插入排序的不同之處在于,它會優(yōu)先比較距離較遠(yuǎn)的元素。

插入排序

插入排序的工作原理是通過構(gòu)建有序序列,對于未排序數(shù)據(jù),在已排序序列中從后向前掃描,找到相應(yīng)位置并插入

代碼實(shí)現(xiàn):

function insertionSort(arr{
    let n = arr.length;
    let preIndex, current;
    for (let i = 1; i < n; i++) {
        preIndex = i - 1;
        current = arr[i];
        while (preIndex >= 0 && arr[preIndex] > current) {
            arr[preIndex + 1] = arr[preIndex];
            preIndex--;
        }
        arr[preIndex + 1] = current;
    }
    return arr;
}

插入算法的核心思想是取未排序區(qū)間中的元素,在已排序區(qū)間中找到合適的插入位置將其插入,并保證已排序區(qū)間數(shù)據(jù)一直有序。重復(fù)這個過程,直到未排序區(qū)間中元素為空,算法結(jié)束。

復(fù)雜度分析:

  • 時間復(fù)雜度:O(n^2^)
  • 空間復(fù)雜度:O(1)

希爾排序

回顧一下上面的插入排序:

  • 第一趟插入排序后,我們得到的有效序列長度為 2
  • 第二趟插入排序后,我們得到的有效序列長度為 3
  • ...
  • 直到這個序列有序

所以,如果序列足夠亂的話,時間復(fù)雜度為 O(n^2^)

希爾排序又是如何優(yōu)化的喃?

希爾排序又叫縮小增量排序,就是把數(shù)列進(jìn)行分組(組內(nèi)不停使用插入排序),直至從宏觀上看起來有序,最后插入排序起來就容易了(無須多次移位或交換)。

其中組的數(shù)量稱為 增量 ,顯然的是,增量是不斷遞減的(直到增量為1)

那我們有是如何進(jìn)行分組喃?

**往往的:**如果一個數(shù)列有 8 個元素,我們第一趟的增量是 4 ,第二趟的增量是 2 ,第三趟的增量是 1 。如果一個數(shù)列有 18 個元素,我們第一趟的增量是 9 ,第二趟的增量是 4 ,第三趟的增量是2 ,第四趟的增量是 1

很明顯我們可以用一個序列來表示增量:n/2、(n/2)/2、...、1每次增量都/2

例如:

let arr = [415873]

排序前:

  • 將該數(shù)組看成三組( Math.floor(arr.length/2) ),分別是: [4, 1] , [5, 8] , [7, 3]

第一趟排序:

  • 對三組數(shù)據(jù)分別進(jìn)行插入排序,因此我們?nèi)齻€數(shù)組得到的結(jié)果為: [1, 4] , [5, 8] , [3, 7]

此時數(shù)組是這樣子的:[1, 4, 5, 8, 3, 7]

第二趟排序:

  • 增量減少了,上面增量是 3 ,此時增量應(yīng)該為 1 了,因此把 [1, 4, 5, 8, 3, 7] 看成一個數(shù)組(從宏觀上是有序的了),對其進(jìn)行插入排序,直至有序

代碼實(shí)現(xiàn):

function shellSort(arr{
    let n = arr.length;
    for (let gap = Math.floor(n / 2); gap > 0; gap = Math.floor(gap / 2)) {
        for (let i = gap; i < n; i++) {
            let j = i;
            let current = arr[i];
            while (j - gap >= 0 && current < arr[j - gap]) {
                 arr[j] = arr[j - gap];
                 j = j - gap;
            }
            arr[j] = current;
        }
    }
    return arr;
}

復(fù)雜度分析:

  • 時間復(fù)雜度:O(nlogn)
  • 空間復(fù)雜度:O(1)

14.6 計數(shù)排序

原理

計數(shù)排序不是基于比較的排序算法,其核心在于將輸入的數(shù)據(jù)值轉(zhuǎn)化為鍵存儲在額外開辟的數(shù)組空間中。

作為一種線性時間復(fù)雜度的排序,計數(shù)排序要求輸入的數(shù)據(jù)必須是有確定范圍的整數(shù)。它是一種典型的拿空間換時間的排序算法

代碼實(shí)現(xiàn)

function countingSort(arr, maxValue) => {
    // 開辟的新的數(shù)組,用于將輸入的數(shù)據(jù)值轉(zhuǎn)化為鍵存儲
    var bucket = new Array(maxValue + 1),
        sortedIndex = 0,
        arrLen = arr.length,
        bucketLen = maxValue + 1

    // 存儲
    for (var i = 0; i < arrLen; i++) {
        if (!bucket[arr[i]]) {
            bucket[arr[i]] = 0
        }
        bucket[arr[i]]++
    }

    // 將數(shù)據(jù)從bucket按順序?qū)懭隺rr中
    for (var j = 0; j < bucketLen; j++) {
        while(bucket[j]-- > 0) {
            arr[sortedIndex++] = j
        }
    }
    return arr
}

復(fù)雜度分析

  • 時間復(fù)雜度:O(n+k)
  • 空間復(fù)雜度:O(n+k)

14.7 桶排序

原理

桶排序是計數(shù)排序的升級版。它也是利用函數(shù)的映射關(guān)系。

桶排序 (Bucket sort)的工作的原理:假設(shè)輸入數(shù)據(jù)服從均勻分布,將數(shù)據(jù)分到有限數(shù)量的桶里,每個桶再分別排序(有可能再使用別的排序算法或是以遞歸方式繼續(xù)使用桶排序進(jìn)行排)。

完整步驟:

  • 首先使用 arr 來存儲頻率
  • 然后創(chuàng)建一個數(shù)組(有數(shù)量的桶),將頻率作為數(shù)組下標(biāo),對于出現(xiàn)頻率不同的數(shù)字集合,存入對應(yīng)的數(shù)組下標(biāo)(桶內(nèi))即可。
// 桶排序
let bucketSort = (arr) => {
    let bucket = [], res = []
    arr.forEach((value, key) => {
        // 利用映射關(guān)系(出現(xiàn)頻率作為下標(biāo))將數(shù)據(jù)分配到各個桶中
        if(!bucket[value]) {
            bucket[value] = [key]
        } else {
            bucket[value].push(key)
        }
    })
    // 遍歷獲取出現(xiàn)頻率
    for(let i = 0;i <= bucket.length - 1;i++){
        if(bucket[i]) {
            res.push(...bucket[i])
        }
 }
 return res
}

復(fù)雜度分析:

  • 時間復(fù)雜度:O(n)
  • 空間復(fù)雜度:O(n)

14.8 基數(shù)排序

原理

基數(shù)排序是一種非比較型整數(shù)排序算法,其原理是將整數(shù)按位數(shù)切割成不同的數(shù)字,然后按每個位數(shù)分別比較。由于整數(shù)也可以表達(dá)字符串(比如名字或日期)和特定格式的浮點(diǎn)數(shù),所以基數(shù)排序也不是只能使用于整數(shù)。

完整步驟:

  • 取得數(shù)組中的最大數(shù),并取得位數(shù);
  • arr為原始數(shù)組,從最低位開始取每個位組成radix數(shù)組;
  • 對radix進(jìn)行計數(shù)排序(利用計數(shù)排序適用于小范圍數(shù)的特點(diǎn));

動圖演示

代碼實(shí)現(xiàn)

//LSD Radix Sort
var counter = [];
function radixSort(arr, maxDigit{
    var mod = 10;
    var dev = 1;
    for (var i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {
        for(var j = 0; j < arr.length; j++) {
            var bucket = parseInt((arr[j] % mod) / dev);
            if(counter[bucket]==null) {
                counter[bucket] = [];
            }
            counter[bucket].push(arr[j]);
        }
        var pos = 0;
        for(var j = 0; j < counter.length; j++) {
            var value = null;
            if(counter[j]!=null) {
                while ((value = counter[j].shift()) != null) {
                      arr[pos++] = value;
                }
          }
        }
    }
    return arr;
}

復(fù)雜度分析

  • 時間復(fù)雜度:基數(shù)排序基于分別排序,分別收集,所以是穩(wěn)定的。但基數(shù)排序的性能比桶排序要略差,每一次關(guān)鍵字的桶分配都需要O(n)的時間復(fù)雜度,而且分配之后得到新的關(guān)鍵字序列又需要O(n)的時間復(fù)雜度。假如待排數(shù)據(jù)可以分為d個關(guān)鍵字,則基數(shù)排序的時間復(fù)雜度將是O(d*2n) ,當(dāng)然d要遠(yuǎn)遠(yuǎn)小于n,因此基本上還是線性級別的
  • 空間復(fù)雜度:O(n+k),其中k為桶的數(shù)量。一般來說n>>k,因此額外空間需要大概n個左右

基數(shù)排序 vs 計數(shù)排序 vs 桶排序

這三種排序算法都利用了桶的概念,但對桶的使用方法上有明顯差異:

  • 基數(shù)排序:根據(jù)鍵值的每位數(shù)字來分配桶;
  • 計數(shù)排序:每個桶只存儲單一鍵值;
  • 桶排序:每個桶存儲一定范圍的數(shù)值;

14.9 堆排序

原理

堆是一棵完全二叉樹,它可以使用數(shù)組存儲,并且大頂堆的最大值存儲在根節(jié)點(diǎn)(i=1),所以我們可以每次取大頂堆的根結(jié)點(diǎn)與堆的最后一個節(jié)點(diǎn)交換,此時最大值放入了有效序列的最后一位,并且有效序列減1,有效堆依然保持完全二叉樹的結(jié)構(gòu),然后堆化,成為新的大頂堆,重復(fù)此操作,知道有效堆的長度為 0,排序完成。

完整步驟為:

  • 將原序列(n個)轉(zhuǎn)化成一個大頂堆
  • 設(shè)置堆的有效序列長度為 n
  • 將堆頂元素(第一個有效序列)與最后一個子元素(最后一個有效序列)交換,并有效序列長度減1
  • 堆化有效序列,使有效序列重新稱為一個大頂堆
  • 重復(fù)以上2步,直到有效序列的長度為 1,排序完成

動圖演示

代碼實(shí)現(xiàn)

function heapSort(items{
    // 構(gòu)建大頂堆
    buildHeap(items, items.length-1)
    // 設(shè)置堆的初始有效序列長度為 items.length - 1
    let heapSize = items.length - 1
    for (var i = items.length - 1; i > 1; i--) {
        // 交換堆頂元素與最后一個有效子元素
        swap(items, 1, i);
        // 有效序列長度減 1
        heapSize --;
        // 堆化有效序列(有效序列長度為 currentHeapSize,拋除了最后一個元素)
        heapify(items, heapSize, 1);
    }
    return items;
}

// 原地建堆
// items: 原始序列
// heapSize: 有效序列長度
function buildHeap(items, heapSize{
    // 從最后一個非葉子節(jié)點(diǎn)開始,自上而下式堆化
    for (let i = Math.floor(heapSize/2); i >= 1; --i) {    
        heapify(items, heapSize, i);  
    }
}
function heapify(items, heapSize, i{
    // 自上而下式堆化
    while (true) {
        var maxIndex = i;
        if(2*i <= heapSize && items[i] < items[i*2] ) {
            maxIndex = i*2;
        }
        if(2*i+1 <= heapSize && items[maxIndex] < items[i*2+1] ) {
            maxIndex = i*2+1;
        }
        if (maxIndex === i) break;
        swap(items, i, maxIndex); // 交換 
        i = maxIndex; 
    }
}  
function swap(items, i, j{
    let temp = items[i]
    items[i] = items[j]
    items[j] = temp
}

// 測試
var items = [,192837465]
heapSort(items)
// [empty, 1, 2, 3, 4, 5, 6, 7, 8, 9]

測試成功

復(fù)雜度分析

  • **時間復(fù)雜度:**建堆過程的時間復(fù)雜度是 O(n) ,排序過程的時間復(fù)雜度是 O(nlogn) ,整體時間復(fù)雜度是 O(nlogn)
  • 空間復(fù)雜度: O(1)

14.10 加深

14.10.1 介紹一下快排原理以及時間復(fù)雜度,并實(shí)現(xiàn)一個快排

快排使用了分治策略的思想,所謂分治,顧名思義,就是分而治之,將一個復(fù)雜的問題,分成兩個或多個相似的子問題,在把子問題分成更小的子問題,直到更小的子問題可以簡單求解,求解子問題,則原問題的解則為子問題解的合并。

快排的過程簡單的說只有三步:

  • 首先從序列中選取一個數(shù)作為基準(zhǔn)數(shù)
  • 將比這個數(shù)大的數(shù)全部放到它的右邊,把小于或者等于它的數(shù)全部放到它的左邊 (一次快排 partition
  • 然后分別對基準(zhǔn)的左右兩邊重復(fù)以上的操作,直到數(shù)組完全排序

具體按以下步驟實(shí)現(xiàn):

  • 1,創(chuàng)建兩個指針分別指向數(shù)組的最左端以及最右端
  • 2,在數(shù)組中任意取出一個元素作為基準(zhǔn)
  • 3,左指針開始向右移動,遇到比基準(zhǔn)大的停止
  • 4,右指針開始向左移動,遇到比基準(zhǔn)小的元素停止,交換左右指針?biāo)赶虻脑?/section>
  • 5,重復(fù)3,4,直到左指針超過右指針,此時,比基準(zhǔn)小的值就都會放在基準(zhǔn)的左邊,比基準(zhǔn)大的值會出現(xiàn)在基準(zhǔn)的右邊
  • 6,然后分別對基準(zhǔn)的左右兩邊重復(fù)以上的操作,直到數(shù)組完全排序

注意這里的基準(zhǔn)該如何選擇喃?最簡單的一種做法是每次都是選擇最左邊的元素作為基準(zhǔn):

但這對幾乎已經(jīng)有序的序列來說,并不是最好的選擇,它將會導(dǎo)致算法的最壞表現(xiàn)。還有一種做法,就是選擇中間的數(shù)或通過 Math.random() 來隨機(jī)選取一個數(shù)作為基準(zhǔn),下面的代碼實(shí)現(xiàn)就是以隨機(jī)數(shù)作為基準(zhǔn)。

代碼實(shí)現(xiàn)

let quickSort = (arr) => {
  quick(arr, 0 , arr.length - 1)
}

let quick = (arr, left, right) => {
  let index
  if(left < right) {
    // 劃分?jǐn)?shù)組
    index = partition(arr, left, right)
    if(left < index - 1) {
      quick(arr, left, index - 1)
    }
    if(index < right) {
      quick(arr, index, right)
    }
  }
}

// 一次快排
let partition = (arr, left, right) => {
  // 取中間項為基準(zhǔn)
  var datum = arr[Math.floor(Math.random() * (right - left + 1)) + left],
      i = left,
      j = right
  // 開始調(diào)整
  while(i <= j) {
    
    // 左指針右移
    while(arr[i] < datum) {
      i++
    }
    
    // 右指針左移
    while(arr[j] > datum) {
      j--
    }
    
    // 交換
    if(i <= j) {
      swap(arr, i, j)
      i += 1
      j -= 1
    }
  }
  return i
}

// 交換
let swap = (arr, i , j) => {
    let temp = arr[i]
    arr[i] = arr[j]
    arr[j] = temp
}

// 測試
let arr = [13254]
quickSort(arr)
console.log(arr) // [1, 2, 3, 4, 5]
// 第 2 個最大值
console.log(arr[arr.length - 2])  // 4

快排是從小到大排序,所以第 k 個最大值在 n-k 位置上

復(fù)雜度分析

  • 時間復(fù)雜度:O(nlogn)
  • 空間復(fù)雜度:O(nlogn)

更多解答

14.10.2 打亂數(shù)組(洗牌算法)

打亂一個沒有重復(fù)元素的數(shù)組。

示例:

// 以數(shù)字集合 1, 2 和 3 初始化數(shù)組。
int[] nums = {1,2,3};
Solution solution = new Solution(nums);

// 打亂數(shù)組 [1,2,3] 并返回結(jié)果。任何 [1,2,3]的排列返回的概率應(yīng)該相同。
solution.shuffle();

// 重設(shè)數(shù)組到它的初始狀態(tài)[1,2,3]。
solution.reset();

// 隨機(jī)返回數(shù)組[1,2,3]打亂后的結(jié)果。
solution.shuffle();

解答:Fisher-Yates 洗牌算法

let Solution = function(nums{
    this.nums = nums
};

Solution.prototype.reset = function({
    return this.nums
};

Solution.prototype.shuffle = function({
    let res = [...this.nums]
    let n = res.length
    for(let i = n-1; i >= 0; i--) {
        let randIndex = Math.floor(Math.random() * (i + 1))
        swap(res, randIndex, i)
    }
    return res
};

let swap = function(arr, i, j{
    const temp = arr[i]
    arr[i] = arr[j]
    arr[j] = temp
}

復(fù)雜度分析:

  • 時間復(fù)雜度:O(n)
  • 空間復(fù)雜度:O(n),需要實(shí)現(xiàn) reset 功能,原始數(shù)組必須得保存一份

更多解答

14.10.3 阿里五面:說下希爾排序的過程?希爾排序的時間復(fù)雜度和空間復(fù)雜度又是多少?

1959年Shell發(fā)明,第一個突破 O(n^2^) 的排序算法,是簡單插入排序的改進(jìn)版。它與插入排序的不同之處在于,它會優(yōu)先比較距離較遠(yuǎn)的元素。

插入排序

插入排序的工作原理是通過構(gòu)建有序序列,對于未排序數(shù)據(jù),在已排序序列中從后向前掃描,找到相應(yīng)位置并插入

代碼實(shí)現(xiàn):

function insertionSort(arr{
    let n = arr.length;
    let preIndex, current;
    for (let i = 1; i < n; i++) {
        preIndex = i - 1;
        current = arr[i];
        while (preIndex >= 0 && arr[preIndex] > current) {
            arr[preIndex + 1] = arr[preIndex];
            preIndex--;
        }
        arr[preIndex + 1] = current;
    }
    return arr;
}

插入算法的核心思想是取未排序區(qū)間中的元素,在已排序區(qū)間中找到合適的插入位置將其插入,并保證已排序區(qū)間數(shù)據(jù)一直有序。重復(fù)這個過程,直到未排序區(qū)間中元素為空,算法結(jié)束。

復(fù)雜度分析:

  • 時間復(fù)雜度:O(n^2^)
  • 空間復(fù)雜度:O(1)

希爾排序

回顧一下上面的插入排序:

  • 第一趟插入排序后,我們得到的有效序列長度為 2
  • 第二趟插入排序后,我們得到的有效序列長度為 3
  • ...
  • 直到這個序列有序

所以,如果序列足夠亂的話,時間復(fù)雜度為 O(n^2^)

希爾排序又是如何優(yōu)化的喃?

希爾排序又叫縮小增量排序,就是把數(shù)列進(jìn)行分組(組內(nèi)不停使用插入排序),直至從宏觀上看起來有序,最后插入排序起來就容易了(無須多次移位或交換)。

其中組的數(shù)量稱為 增量 ,顯然的是,增量是不斷遞減的(直到增量為1)

那我們有是如何進(jìn)行分組喃?

往往的: 如果一個數(shù)列有 8 個元素,我們第一趟的增量是 4 ,第二趟的增量是 2 ,第三趟的增量是 1 。如果一個數(shù)列有 18 個元素,我們第一趟的增量是 9 ,第二趟的增量是 4 ,第三趟的增量是2 ,第四趟的增量是 1

很明顯我們可以用一個序列來表示增量:n/2、(n/2)/2、...、1,每次增量都/2

例如:

let arr = [415873]

排序前:

  • 將該數(shù)組看成三組( Math.floor(arr.length/2) ),分別是: [4, 1] , [5, 8] , [7, 3]

第一趟排序:

  • 對三組數(shù)據(jù)分別進(jìn)行插入排序,因此我們?nèi)齻€數(shù)組得到的結(jié)果為: [1, 4] , [5, 8] , [3, 7]

此時數(shù)組是這樣子的:[1, 4, 5, 8, 3, 7]

第二趟排序:

  • 增量減少了,上面增量是 3 ,此時增量應(yīng)該為 1 了,因此把 [1, 4, 5, 8, 3, 7] 看成一個數(shù)組(從宏觀上是有序的了),對其進(jìn)行插入排序,直至有序

代碼實(shí)現(xiàn):

function shellSort(arr{
    let n = arr.length;
    for (let gap = Math.floor(n / 2); gap > 0; gap = Math.floor(gap / 2)) {
        for (let i = gap; i < n; i++) {
            let j = i;
            let current = arr[i];
            while (j - gap >= 0 && current < arr[j - gap]) {
                 arr[j] = arr[j - gap];
                 j = j - gap;
            }
            arr[j] = current;
        }
    }
    return arr;
}

復(fù)雜度分析:

  • 時間復(fù)雜度:O(nlogn)
  • 空間復(fù)雜度:O(1)

更多解答

14.10.4 排序鏈表

在 O(n log n) 時間復(fù)雜度和常數(shù)級空間復(fù)雜度下,對鏈表進(jìn)行排序。

示例 1:

輸入: 4->2->1->3
輸出: 1->2->3->4

示例 2:

輸入: -1->5->3->4->0
輸出: -1->0->3->4->5

解答:采用歸并排序

歸并排序采用了分治策略,將數(shù)組分成2個較小的數(shù)組,然后每個數(shù)組再分成兩個更小的數(shù)組,直至每個數(shù)組里只包含一個元素,然后將小數(shù)組不斷的合并成較大的數(shù)組,直至只剩下一個數(shù)組,就是排序完成后的數(shù)組序列。

對應(yīng)于鏈表喃?

4->2->1->3

第一步:分割

  • 使用快慢指針(雙指針法),獲取鏈表的中間節(jié)點(diǎn)
  • 根據(jù)中間節(jié)點(diǎn),分割成兩個小鏈表
  • 遞歸執(zhí)行上一步,直到小鏈表中只有一個節(jié)點(diǎn)

第二步:歸并(合并有序鏈表)

代碼實(shí)現(xiàn)

let sortList = function(head{
    return mergeSortRec(head)
}

// 歸并排序
// 若分裂后的兩個鏈表長度不為 1,則繼續(xù)分裂
// 直到分裂后的鏈表長度都為 1,
// 然后合并小鏈表
let mergeSortRec = function (head{
    if(!head || !head.next) {
        return head
    }

    // 獲取中間節(jié)點(diǎn)
    let middle = middleNode(head)
    // 分裂成兩個鏈表
    let temp = middle.next
    middle.next = null
    let left = head, right = temp
    // 繼續(xù)分裂(遞歸分裂)
    left = mergeSortRec(left)
    right = mergeSortRec(right)
    // 合并兩個有序鏈表
    return mergeTwoLists(left, right)
}

// 獲取中間節(jié)點(diǎn)
// - 如果鏈表長度為奇數(shù),則返回中間節(jié)點(diǎn)
// - 如果鏈表長度為偶數(shù),則有兩個中間節(jié)點(diǎn),這里返回第一個
let middleNode = function(head{
    let fast = head, slow = head
    while(fast && fast.next && fast.next.next) {
        slow = slow.next
        fast = fast.next.next
    }
    return slow
}

// 合并兩個有序鏈表
let mergeTwoLists = function(l1, l2{
    let preHead = new ListNode(-1);
    let cur = preHead;
    while(l1 && l2){
        if(l1.val < l2.val){
            cur.next = l1;
            l1 = l1.next;
        }else{
            cur.next = l2;
            l2 = l2.next;
        }
        cur = cur.next;
    }
    cur.next = l1 || l2;
    return preHead.next;
}

引入遞歸算法的復(fù)雜度分析:

  • 遞歸算法的時間復(fù)雜度:遞歸的總次數(shù) * 每次遞歸的數(shù)量
  • 遞歸算法的空間復(fù)雜度:遞歸的深度 * 每次遞歸創(chuàng)建變量的個數(shù)

復(fù)雜度分析

  • 時間復(fù)雜度:遞歸的總次數(shù)為 T(logn) ,每次遞歸的數(shù)量為 T(n) ,時間復(fù)雜度為 O(nlogn)
  • 空間復(fù)雜度:遞歸的深度為 T(logn) ,每次遞歸創(chuàng)建變量的個數(shù)為 T(c) (c為常數(shù)),空間復(fù)雜度為 O(logn)

關(guān)于復(fù)雜度分析,請看這篇:前端進(jìn)階算法1:如何分析、統(tǒng)計算法的執(zhí)行效率和資源消耗?

優(yōu)化遞歸

使用迭代代替遞歸,優(yōu)化時間復(fù)雜度:O(logn) —> O(1)

更多解答

14.10.5 撲克牌問題

魔術(shù)師手中有一堆撲克牌,觀眾不知道它的順序,接下來魔術(shù)師:

  • 從牌頂拿出一張牌, 放到桌子上
  • 再從牌頂拿一張牌, 放在手上牌的底部

如此往復(fù)(不斷重復(fù)以上兩步),直到魔術(shù)師手上的牌全部都放到了桌子上。

此時,桌子上的牌順序為:(牌頂) 1,2,3,4,5,6,7,8,9,10,11,12,13 (牌底)。

問:原來魔術(shù)師手上牌的順序,用函數(shù)實(shí)現(xiàn)。

解答:反向推導(dǎo)

假設(shè),原來魔術(shù)師手上牌的順序數(shù)組為 origin ,最后放在桌子上的順序數(shù)組為 result

正向的操作為: origin 取出第一個插入 result 前面, origin 再取出第一個換到自己的末尾,如此重復(fù);

反向操作為: origin 最后一個放到自己的第一個前面, result 拿出第一個插入 origin 前面,如此重復(fù);

const calc = (arr) => {
    const origin = [];
    for (let i = 0; i < arr.length; i++) {
        if (origin.length) {
            const item = origin.pop();
            origin.unshift(item);
        }
        origin.unshift(result[i])
    }
    return origin;
}

// 測試
const result = [12345678910111213]
// 原有順序
calc(result)
// [13, 2, 12, 6, 11, 3, 10, 5, 9, 1, 8, 4, 7]

更多解答

14.10.6 有效三角形的個數(shù)

給定一個包含非負(fù)整數(shù)的數(shù)組,你的任務(wù)是統(tǒng)計其中可以組成三角形三條邊的三元組個數(shù)。

示例 1:

輸入: [2,2,3,4]
輸出: 3
解釋:
有效的組合是: 
2,3,4 (使用第一個 2)
2,3,4 (使用第二個 2)
2,2,3

注意:

  • 數(shù)組長度不超過1000。
  • 數(shù)組里整數(shù)的范圍為 [0, 1000]。

本題可結(jié)合:

  • 字節(jié)&leetcode1:兩數(shù)之和
  • 騰訊&leetcode15:三數(shù)之和

一起練習(xí)

解法:排序+雙指針

我們知道三角形的任意兩邊之和大于第三邊,任意兩邊之差小于第三邊,如果這三條邊長從小到大為 a 、 b 、 c ,當(dāng)且僅當(dāng) a + b > c 這三條邊能組成三角形

解題思路: 先數(shù)組排序,排序完后,固定最長的邊,利用雙指針法判斷其余邊

以 nums[nums.length - 1] 作為最長的邊 nums[k] ( k = nums.length - 1 )

以 nums[i] 作為最短邊,以 nums[nums.length - 2] 作為第二個數(shù) nums[j] ( j = nums.length - 2 ) ,

判斷 nums[i] + nums[j] 是否大于 nums[k] ,

  • nums[i] + nums[j] > nums[k] ,則:

    nums[i+1] + nums[j] > nums[k]
    nums[i+2] + nums[j] > nums[k]
    ...
    nums[j-1] + nums[j] > nums[k]

    則可構(gòu)成三角形的三元組個數(shù)加 j-i ,并且 j 往前移動一位( j-- ), 繼續(xù)進(jìn)入下一輪判斷

  • nums[i] + nums[j] <= nums[k],則 l 往后移動一位(nums 是增序排列),繼續(xù)判斷

代碼實(shí)現(xiàn):

let triangleNumber = function(nums{
    if(!nums || nums.length < 3return 0
    let count = 0
    // 排序
    nums.sort((a, b) => a - b) 
    for(let k = nums.length - 1; k > 1; k--){
        let i = 0, j = k - 1
        while(i < j){ 
            if(nums[i] + nums[j] > nums[k]){
                count += j - i
                j--
            } else {
                i++
            }
        }
    }       
    return count
}

復(fù)雜度分析:

  • 時間復(fù)雜度:O(n^2^)
  • 空間復(fù)雜度:O(n)

注意:

關(guān)于 Array.prototype.sort() ,ES 規(guī)范并沒有指定具體的算法,在 V8 引擎中, 7.0 版本之前,數(shù)組長度小于10時, Array.prototype.sort() 使用的是插入排序,否則用快速排序。

在 V8 引擎 7.0 版本之后就舍棄了快速排序,因為它不是穩(wěn)定的排序算法,在最壞情況下,時間復(fù)雜度會降級到 O(n2)。

而是采用了一種混合排序的算法:TimSort 。

這種功能算法最初用于Python語言中,嚴(yán)格地說它不屬于以上10種排序算法中的任何一種,屬于一種混合排序算法:

在數(shù)據(jù)量小的子數(shù)組中使用插入排序,然后再使用歸并排序將有序的子數(shù)組進(jìn)行合并排序,時間復(fù)雜度為 O(nlogn) 。

更多解答

最后

歡迎關(guān)注「三分鐘學(xué)前端」,回復(fù)「交流」自動加入前端三分鐘進(jìn)階群,每日一道編程算法面試題(含解答),助力你成為更優(yōu)秀的前端開發(fā)!

號內(nèi)回復(fù):

網(wǎng)絡(luò)」,自動獲取三分鐘學(xué)前端網(wǎng)絡(luò)篇小書(90+頁)
JS」,自動獲取三分鐘學(xué)前端 JS 篇小書(120+頁)
算法」,自動獲取 github 2.9k+ 的前端算法小書
面試」,自動獲取 github 23.2k+ 的前端面試小書
簡歷」,自動獲取程序員系列的 120 套模版
》》面試官也在看的前端面試資料《《
“在看和轉(zhuǎn)發(fā)”就是最大的


瀏覽 41
點(diǎn)贊
評論
收藏
分享

手機(jī)掃一掃分享

分享
舉報
評論
圖片
表情
推薦
點(diǎn)贊
評論
收藏
分享

手機(jī)掃一掃分享

分享
舉報

感谢您访问我们的网站,您可能还对以下资源感兴趣:

国产秋霞理论久久久电影-婷婷色九月综合激情丁香-欧美在线观看乱妇视频-精品国avA久久久久久久-国产乱码精品一区二区三区亚洲人-欧美熟妇一区二区三区蜜桃视频 久青草视频| 午夜福利在线播放| 黑人av在线观看| 91在线精品视频| 四川少扫搡BBw搡BBBB| 黄色一级免费电影| 在线观看内射视频| 欧产日产国产swag| 亚洲色视频在线| 欧美毛视频| 91香蕉在线| 强辱丰满人妻HD中文字幕| 91麻豆香蕉| 996re| 中文无码AV在线| 九九天堂网| AV天堂影视在线观看| 女人的天堂AV| 性久久久久久| 国产亚洲一区二区三区| 欧美成人在线免费视频| 996re| 久久久久久大香蕉| 蜜桃性视频| 无码乱伦AV| 东方美美高清无码一区| 草草网| 国产成人免费在线观看| 午夜无码精品一区二区三区99午 | 最新av资源| 甘肃WBBBB搡wBBBB| 青娱乐超碰在线| 依人成人| 91小视频在线观看| 国产精品1区2区| 一级二级三级无码| 免费看黄色的视频| 青娱乐免费视频| 操逼网址大全| 躁BBB躁BBB躁BBBBBB日视频| 性欧美丰满熟妇XXXX性久久久| 伊人AV在线| 俺去也| 中文字幕毛片| 成人一区二区三区四区| 亚洲A级毛片| av婷婷在线| 大香蕉中文网| 91AV无码| 久久久久久久麻豆| 成人久久久久| 十八禁视频在线观看网站.www| 亚洲最大网站| 日韩日韩日韩日韩日韩| 91大神在线免费观看| 俺也去色色| 日本一区二区三区四区| 西西4444www无码精品| 午夜性爽视频男人的天堂| 强伦轩人妻一区二区三区70后| 欧美黄色网| 国产777777| 国产性生活| 中文字幕无码Av在线看| 俺也去在线视频| 97人人爽人人爽人人人| 成人三级视频在线观看| 亚洲成人AV在线观看| 东京热在线视频观看| 天堂网中文| 精品人妻无码一区二区三区四川人| 91丨九色丨国产在线| 精品日逼| 国产美女精品视频| 国产成人综合在线| 日本AⅤ电影| 五月天福利影院| 少妇久久久久久久久久| 久久97人妻AⅤ无码一区| 欧美一二三| www.91在线视频| 国产精品啪啪啪啪| 免费一级A| 日逼高清视频| 国产一精品一aⅴ一免费| 狠狠撸综合| 91视频美女| 91视频免费在线看| 日韩资源站| 伦理无码| av无码免费在线观看| 精品久久久久久亚洲| av啊啊| 四虎无码视频| 日韩一区二区三区四区久久久精品有吗| 91白丝喷水自慰网站| 欧美日韩亚洲另类| 99热99re6国产线播放| 能看的操逼视频| 丁香一区二区| 91成人久久| 777色色色| 欧美成人无码一区二区三区| 特黄AAAAAAAAA真人毛片| 亚洲成人精品一区二区| 天天视频国产| www.日韩无码| 成人在线黄色| 精东影业秘国产传媒| 四川少扫搡BBw搡BBBB| 国产逼| 婷婷视频在线| 无码群交东京热| 亚洲性爱电影| 色色网站| 亚洲福利影院| 青青草免费福利视频| www91久久| 久久综合加勒比| 精品吃奶一区二区三区视频| av网站导航| 日韩在线91| 三级毛片在线| 柠檬AV导航| 奇米99| 亚洲成人性爱网站| 无码AV大香线蕉伊人| 怡红院男人的天堂| 日批视频网站| 国产日韩欧美在线| 懂色一区二区三区免费| 亚洲人一级电影| 97精品久久| 91在线看18| 九九色在线视频| 人操人人人操| 97香蕉久久夜色精品国产| 亚洲秘无码一区二区三区观看| 午夜天堂| 男人天堂中文字幕| 欧洲黄网| 一本一道久久综合| 粉嫩99精品99久久久久| 成年人在线观看视频网站| 免费操| 欧美福利| 91无码人妻传媒tv| 国产欧美精品成人在线观看| AV影音在线| 2022天天干| 日本黄色免费在线观看| 欧美三级片网| 97人妻人人揉人人躁人人| 五月丁香伊人| 大乳奶一级婬片A片| 欧美午夜精品一区二区蜜桃| 国产精品久久久久久最猛| 日韩中文无码电影| 成人亚洲av| 欧美内射网站| 大香蕉伊| 中文字幕在线观看av| 91性爱视频| 激情视频免费看| 特黄特色免费视频| 中文字幕视频免费| 91丨露脸丨熟女抽搐| 国产香蕉网| 亚洲无码免费观看视频| 欧美激情色色| 91三级片在线播放| 蜜桃传媒一区二区亚洲A| wwwa片| 躁BBB躁BBB添BBBBBB| 伊人99| 奶头和荫蒂添的好舒服囗交漫画| 97福利导航| 校园春色亚洲色图| 加勒比日韩| 亚洲无码电影网站| 免费国产黄色| 撸撸操在线视频观看只有精品| 综合视频一区| 亚洲成人在线观看视频| 久久久WWW成人免费精品| 91av免费观看| 久久久久9999| 亚洲国产成人精品激情在线| 少妇搡BBBB搡BBB搡小说| 国产精品porn| 怡红院视频| 一区二区三区无码视频| 中文字幕线观看| 国产精品国产三级囯产普通话2 | 人人操AV| 亚洲AVwww| 免费视频一二区| аⅴ资源新版在线天堂| 精品熟妇| 高清无码人妻| 蜜桃性视频| 国产AV电影网| 久久嫩草国产成人一区| 综合五月| 黄色视频在线免费看| 婷婷五月激情中文字幕| 操熟女视频| 婷婷精品国产一区二区三区日韩 | www.A片| 少妇免费视频| 亚洲国产成人va| 日韩黄色精品| 五月天国产| 麻豆免费视频| 亚洲国产精品久久久久婷婷老年| 五月天婷婷在线视频| 国产男女视频| 91久久国产性奴调教| 免费一级片| 大BBBw大BBBW另类| 亚洲aⅴ| jjzz亚洲| 亚洲免费网站| 成人性爱视频免费在线观看| 日韩成人无码免费视频| 成人在线小视频| 色色天堂成人电影| 熟女视频网| 亚洲免费观看高清完整版在va线观看| 91性视频| 免费AV观看| 免费播放黄色成人片| 黄片在线免费播放| 色噜噜狠狠色综无码久久合欧美| TokyoKot大交乱无码| 一区二区三区不卡在线| 一区二区三区免费看| 免费操逼网站| 免费在线无码视频| AV无码免费一区二区三区不卡| 免费看黃色AAAAAA片| 在线观看高清无码中文字幕| 91高清无码视频| 中文字幕2025年最好看电视剧| 91在线资源| 思思精品视频| 丰满人妻一区二区三区免费| 欧美黄视频| 99精品视频北条麻妃国产版| 欧美福利在线观看| 欧美三级精品| 亚洲色在线播放| 国内自拍视频网站| 欧美性爱-熊猫成人网| 精品无码一| 久久AA| 91九色视频| 狼友视频第二页| 丰满人妻一区二区三区四区不卡 | 好吊一区二区三区| www.俺去啦| 久久免费视屏| 国产在线不卡年轻点的| 99久久婷婷国产综合精品| 一区二区三区中文字幕| 最新AV在线播放| 日本亲子乱婬一级A片| 成人色色网| 淫色综合网| 亚欧洲精品在线视频| 日韩A级毛片| 日韩极品视频在线| 国产AA片| 色播五月天| 日本成人一区二区| 大香蕉伊人在线观看视频| 大屌一区二区三区| www.91AV| 麻豆久久久| 国产91高跟丝袜| 久久AV秘一区二区三区水生| mm131亚洲国产精品久久| 日韩免费成人视频| 3D动漫精品啪啪一区二区下载| 成人黄色毛片视频| 色天使视频| 午夜A片| 东京热第一页| 免费黄片网站在线观看| 成人h网站在线观看| 黄色精品网站| 欧美一区二区在线观看| 可以看的黄色视频| 一级爱爱片| 国产午夜精品视频| 欧美人人| 羞羞色院91蜜桃| 五月天激情四射| www.911国产| 蜜桃传媒在线| 五月天激情综合网| 三级片日本在线| 欧美黄色性爱| 国产无码自拍| 人人综合网| 神马午夜久久| 日韩视频免费在线| 免费看成人片| 亚洲wwwwww| 天堂网中文| 91搞一搞| 亚洲AV无码精品国产| 亚洲日韩AV在线| 夜间福利视频| a在线免费观看| 日韩无码三级视频| 成人在线超碰| 3D动漫精品啪啪一区二区| www.狠狠爱| 国产人妻一区二区三区欧美毛片 | 蜜臀av一区二区三区| 午夜做爱视频| 久久毛| 不卡a12| 国产成人精品AV在线观| 国产精品成人在线视频| 国产成人AⅤ| 操逼黄视频| 高清无码在线观看18| 无码人妻丰满熟妇区17水蜜桃| 国产灬性灬淫灬欲水灬| 国产一级电影网站| 91国产视频在线观看| 手机免费Av| 99热在线观看免费精品| 韩国AV三级| 亚洲国产久久| 欧美成人视频大全| 亚洲综合中文字幕在线| 详情:绿帽夫妻多人运动开淫啪-91n| 内射熟妇| www久久| AV在线免费网站| 免费中文字幕日韩欧美| 精品亚洲一区二区三区四区五区 | 亚洲视频中文字幕在线观看| 人人人妻人人人操| 免费看成人片| 日韩激情视频在线观看| 九色一区| 伊人日逼| 在线观看亚洲天堂| 国产无码做爱视频| 亚洲性爱视频在线观看| 先锋影音AV资源站| 操B视频网站| 天天日少妇| 欧美色图在线视频| 国产精品你懂得| 亚洲91视频| 欧美精品一卡二卡| 黄色在线欣赏| 日本操逼片| 亚洲A网站| 久久久穴| 97精产国品久久蜜桃臀| 人人操人人干人人摸| 99热这里只有精品999| 欧美色图在线播放| 四川少BBB搡BBB爽爽爽| 成人伊人网| 精品无码人妻一区二区三区| 老司机狠狠干| 西西人体大胆裸体A片| www.99免费视频| 好吊妞在线| 99在线小视频| 亚洲精品国产精品国自产在线| 丁香六月激情婷婷| 欧美日韩A片| 91人妻人人澡人人爽人人爽| 精品无码一区二区三区四区久久久软件| 99Re66精品免费视频| 欧美偷拍一区二区| 成人无码区免费A片| 操逼手机视频| 无码一区在线观看| 亚洲天堂网在线观看视频| 俺去俺来也在线www色官网| 成人AV三级片| 国产激情电影| 日韩一级电影在线观看| 中文字幕乱码在线| 热无码| 成人网大香蕉| 色丁香视频在线观看的| 丁香五月天啪啪| 国产精品免费人成网站酒店 | 国产ww| 超碰九一| 久操久操| 狠狠躁日日躁夜夜躁A片小说免费| 亚洲去干网| 高清无码操逼| 久久久久亚洲AV无码专区| 看毛片网站| 永久免费黄色视频| 一道本无码免费视频| 婷婷狠狠| www.久热| 亚洲高清国产欧美综合s8| 呦小BBBB小小BBBB| 51福利导航| 欧美精产国品一二三区| 色婷婷精品视频| 欧美综合视频在线观看| 国产一区二区三区免费播放| 亚洲在线观看中文字幕| 悠悠AV导航| 在线天堂av| 99视频+国产日韩欧美| 嫩草av| 日韩三级一区| 粉嫩小泬BBBB免费看| 无码A区| 日韩无码视频观看| www.爆操| 国产福利视频导航| 一级大香蕉| 午夜3D动漫AV| 无码免费一区| 日韩精品中文无码| 精品夜夜澡人妻无码AV| 免费操逼视频在线观看| 青草网| 亚洲黄片大全| 狠狠se| 黄片免费大全| 大香蕉欧美视频| 永久免费叼嘿| 亚洲成人黄色| 777视频在线观看| 91伊人久热精品| 国产免费一区二区三区| 在线免费看A片| 日韩毛片在线免费观看| 99大香蕉| 婷婷五月天网| 在线国产激情视频| 中文字幕高清AⅤ| 国产三级av在线| 亚洲最大网站| 国产欧美视频在线| 超碰精品在线| 蜜桃传媒视频| 国产人妻精品一区二区三区不卡| 91精品人妻一区二区三区蜜桃欧美 | 色婷婷香蕉| 精品久| 777免费视频| 欧美性爱18| 午夜成人大片| 国产AV三级片| 欧美日韩成人在线观看| 天天夜夜有| 欧美黄色一级| 精品免费国产一区二区三区四区| 韩国无码视频在线观看| 亚洲无码视频在线观看高清| 日本免费中文字幕| 亚洲AV播放| 欧洲无码一区二区三区| 四虎av| 婷婷色色网| 四虎在线免费视频| 竹菊影视一区二区三区| 久久久噜噜噜久久中文字幕色伊伊| 翔田千里91| 天天操视频网站| 91人妻人人操| 国产一区二区成人久久919色| 99国产免费| 麻豆黄网| JUY-579被丈夫的上司侵犯后的第7天,我| 中文在线字幕免费观看| 国产精品自产拍| 国产清纯可爱美女自卫裸贷偷情| 亚洲丁香五月| 影音先锋国产AV| 国产熟女AV| 国产清纯可爱美女自卫裸贷偷情| 成人在线小视频| 日本成人毛片| 美女被操面费网站| 99美女精品视频| 一级免费黄色片| jizz麻豆| 成人不卡在线| 人人爽爽人人| 男女日皮视频| 刘玥91精一区二区三区| 成年片| 欧美精品一级| 成人视频欧美| 香蕉久久久| 中文字幕无码亚| аⅴ资源新版在线天堂| 欧美日韩国| 亚洲日韩视频| 日韩极品视频| 色色热热| 欧美成人电影在线观看| 久色婷婷在线| 丁香婷婷五月| 国产理论片| 男女视频91| 中文字幕在线永久| 国产免费av在线观看| 操逼在线观看| 亚洲日韩在线观看视频| 欧美亚洲综合在线| 国产精品1区2区3区| 欧美成人一区二区三区片| 影音先锋一区二区三区| 国产一级a毛一级a做免费高清视频| 亚洲中文字幕视频在线| 国产18禁网站| 人人摸人人操人人爽| 成人A毛片| 色色色99| 黄色视频免费播放| 亚洲欲色| 91porn国产| 成人A电影| 黄色电影免费在线观看| 操少妇| 蜜桃久久久亚洲精品| 波多野59部无码喷潮| 在线A片免费观看| 日韩情色片| 六月激情| 97国产超碰| 国产熟女| 俺也来www俺也色com| 狼友免费视频| 乱子伦一区二区三区视频在线观看 | 婷婷精品免费久久| 中文字幕精品视频在线| 婷婷视频导航| 综合天堂网| 刘玥91精品一区二区三区| 青青草免费在线| 懂色av蜜臀av粉嫩av分享| 日韩精品A片| 2024无码| 特级特黄A级高潮播放| 大香蕉综合| 欧美黄色一级视频| 一本色道久久综合无码人妻| 婷婷亚洲天堂| 毛茸茸BBBBBB毛茸茸| 91成人视频免费观看| 小黄片在线免费观看| 三级AV在线免费观看| 黄色片免费| 四川少扫搡BBw搡BBBB| 狠狠干2021| 久久国产欧美| 成人免费在线网站| 一级无码免费| 亚洲码AV波多野| 无套内射在线免费观看| 午夜乱伦| 天天日综合| 特黄AV| av无码一区| 日韩a片在线观看| 狼人一区二区| 亚洲第一成人网址| 色婷婷综合视频| 日韩V欧美| 先锋影音资源站av每日资源在线| 9久热| 成人黄色A片| 欧美日韩成人在线视频| 大香蕉看片| 91精品内射| 国产36页| 黄色电影网页| 日韩欧美在线免费| 热久久国产| 91人妻一区二区三区| 瘦精品无码一区二区三区四区五区六区七区八区 | 久久私人影院| 国产毛片久久久久久久| 99精品自拍| 精品国产乱码| 六月综合激情| 白峰美羽人妻AND-499| 天天爽爽爽爽爽成人片| 国产精品免费久久影院| 中文字幕av在线播放| 一区二线视频| www.偷拍| 日本激情网站| 日韩免费三级片| 91网址| 99这里有精品| 自拍偷拍精品| 成人AV十八亚洲二区| 日本成人高清视频| 亚洲视频五区| 国产欧美成人在线| 大香蕉亚洲在线| yw尤物在线| 2024男人天堂| 国产suv精品一区二区6精华液| 91人体视频| 日韩中文久久| 久久免费看视频| 日韩精品一区二区三区四在线播放| 91就要爱爱视频| 免费黄色在线观看| 国产欧美一区二区精品性色超碰 | 亚洲精品天堂无码| 日本高清视频www| 久久久久久国产免费A片| 五月天av在线观看| 久久久久久久久久国产精品免费观看-百度 | 日韩高清一区| 免费看黄色片| 唐山熟女工棚嗷嗷叫| 国产高清精品软件丝瓜软件| www欧美| 国产免费AV在线| 一级黄色电影网| 欧美一区视频| 午夜精品久久久久久久| 69式荫蒂被添全过程频| 婷婷五月天国产| 一级AA毛片| 天天色天天日天天干| 人妻人人澡| 超碰在线国产| 99在线观看精品视频| 蜜桃视频成人app| 东方AV在线播放| 狠狠操狠狠撸| 亚洲人妻无码在线| 大香蕉网伊人| 另类罕见稀奇videos| 好色综合| 91做爱视频| 91在线精品一区二区| 亚洲精品免费视频| 亚洲无码三区| 泄火熟妇2-ThePorn| 一级a片免费看| 天堂一区二区三区| 在线观看黄| 麻豆一级片| 亚洲欧美日韩在线| 韩剧《邻居的妻子》电视剧| 国产激情艹逼| 日韩无码专区电影| a片视频免费观看| 亚洲一区日韩| 四川揉BBB搡BBB| 西西888WWW大胆视频| 91麻豆电影| 中文无码AV在线| 操小嫩逼视频| 91麻豆精品无码人妻| 免费69视频看片| 777777国产7777777| 成人久久久久一级大黄毛片中国| 日本一区二区三区在线播放| 亚洲国产无码在线| 99精品视频免费看| 一本一道AV| 97国产精品视频| 天天日天天干天天日| 中文字幕av久久久久久欧洲尺码| 少妇一级片| 2025AV天堂| AA片免费| 91伊人| 久久密| 欧美裸体视频| 日韩爱爱爱| 无码网| 亚洲精品色婷婷| 91AV视频在线| 久热在线视频| 久久538| 欧美在线黄片| 成人性爱在线| 欧美性爱91| 成人国产综合| 日韩爱爱爱| 日本熟妇高潮BBwBBwBBw| 免费操| 少妇嫩搡BBBB搡BBBB| 欧美黄色一级视频| 成人无码视频| 久久久久人妻| 欧美黄片在线免费看| 高清无码视频免费版本在线观看 | 超碰99在线| 国产欧美综合在线三区| 中文字幕无码毛片| 国产超级无码高清在线视频观看| 国产又爽又黄免费观看| 草逼视频免费看| 成人无码区亚洲AV久久| 黄色电影天堂网| 国产精品午夜福利视频| 欧美中文在线观看| 日韩一区无码| 国产激情在线视频| 色色色色色欧美网| 亚洲日韩网站在线观看| 99热青青| 三级黄色免费网站| www.日本黄色视频| 一区二区视频在线| а√最新版天堂中文在线| 操久久| 欧美一级欧美三级在线观看| 91视频亚洲| 欧美性猛交ⅩXXX乱大交| 国产又粗又长的视频| 久久久aaa| 被黑人猛躁10次高潮视频| 亚洲精品成人av| 日本一区二区三区在线播放| 免费国产黄色视频网站| 欧美性爱在线播放| 亚洲天堂2016| 99热这里是精品| 欧美日韩精品一区二区三区视频播放 | 亚欧成人在线视频| 中文字幕理论片| 成人av免费观看| 亚洲精品无码a片| 色色五月天婷婷| 亚洲无码免费看| 日韩性爱一区二区| 亚洲日本中文字幕在线| A片在线观看网站| 亚洲天堂精品视频| 白嫩外女BBWBBWBBW| 欧美成人精品一区二区| 国产在线成人视频| 成年片免费观看网站免费观看,亚洲+欧...| 超碰人| 激情深爱五月| 国产h视频在线观看| 日逼视频网站| 亚洲一级二级片| 国产成人无码精免费视频| 国产乱码一区二区三区的区别| 俺来也俺去了| 精品欧美无人区乱码毛片| 中文字幕的色| www.大香蕉伊人| 97人妻人人澡人人爽人人| 国产精品99久久久久久成人| 日本无码电影| 日本一级特黄电影| 婷婷日逼| av高清无码| 四虎成人无码A片观看| 老太奶性BBwBBw侧所| 99热在线观看精品免费| 成人性爱自拍| 91久久视频| 无码熟妇人妻无码AV在线天堂 | 国产精品怡红院有限公司| 亚洲国产97| 波多野结衣av一区| 免费日韩无码| 成人婷婷| 久久久国产精品黄毛片| 免费一级片视频| 黄色大片免费网站| 免费网站观看www在线观| 亚洲第一黄网| 国产成人AV片| 日本少妇高清视频| AA片网站| 草草视频在线观看| 少妇综合网| 久久一区二区三区四区| 精品人妻一区二区乱码一区二区 | 伊人久久久久久久久久久| 亚洲无码AV在线观看| 天天色天天爱| 91日韩欧美| 亚洲精品字幕久久久久| 蜜桃人妻无码AV天堂二区| 思思热思思操| 天天综合国产| 国产高清AV| 影音先锋色资源站| 自拍视频一区| 免费操B视频| 免费AV在线| 嫩BBB搡BBBB搡BBBB| 97人人干人人| 91露脸熟女四川熟女在线观看| 一级A片在线观看| 西西www444无码免费视频| www.99热视频| 91人妻人人澡人人澡人人精品| 亚洲欧美视频在线观看| 小H片在线观看| 天天日天天草天天干| 久久国产毛片| 色色射| jizz国产| 中文AV在线播放| 91久久人澡人妻人人做人人爽97 | 一区二区三区四区在线播放| 亚洲欧美91| 一级黄片免费看| 亚洲AV无码成人精品区| 1024国产| AV免费网站| 51午夜福利| 嫩草久久99www亚洲红桃| 高H视频在线观看| 国产激情视频| 欧美大屌网站| 亚洲精品乱码久久久久久| 国产在线秘麻豆精品观看| 欧美自拍视频| 99er在线观看| 天天色天天日天天干| 黄色大片网站| 国产在线接入| 免费欧美A片| 久久久国产精品黄毛片| 成人午夜视频精品一区| 国內精品久久久久久久| 国产成人精品电影| 动图综合亚洲综合欧美男男| 2026AV天堂网| 亚洲美女免费视频| 中文字幕一区在线观看| 婷婷色大师| 亚洲中文字幕免费在线观看| 伊人成色| 国产AV大香蕉| 黑人巨大翔田千里AⅤ| 三级成人无码| 一本色道88久久加勒比精品| 国产高清无码福利| 日本精品无码a62v在线| 中文字幕成人| av一卡二卡| 免费黄片视频在线观看| 黄片网站免费观看| 国产91高跟丝袜| 中文电视剧字幕在线播放免费视频| 黄色视频网站在线| 中文字幕天天在线| 日韩人妻av| 男女激情网站| 激情二区| 男人日女人视频| 欧美日韩激情| 亚洲欧美91| 青青草手机在线观看| 淫香淫色综合网| 久久77777| 久久国产99| 天天操天天操天天操天天操 | b逼一区| 国产免费自拍视频| 色婷婷激情综合网| 俺来也俺去www色情网| 色欲成人AV| 青青操国产乱伦| 久久久三级片| 日韩在线免费观看视频| 亚洲精品99| 五月天婷婷在线观看视频| 精品少妇一区| 无码成人AV在线看免费| 午夜亚洲AⅤ无码高潮片苍井空 | 神马午夜福利影院| 毛片国产| 爱爱亚洲| 黄色直播在线观看| 白虎高清无码大尺度免费在线观看| 免费日韩黄色电影| 国产综合AV| 国产精品aaa| anwuye官方网站|