#算法 第4版# 2.1.14 撲克牌出列排序 答案

啃算法

題目

出列排序。說說你會如何將一副撲克牌排序(花色順序是黑桃、紅桃、梅花和方片),限制條件是隻能查看最上面的兩張牌,交換最上面的兩張牌,或是將最上面的一張牌放到這摞牌的最下面。算法

Ace King

分析

以冒泡排序的思路處理,可是因爲只能看兩張牌,因此在排序過程當中是沒法斷定排序是否提早完成。bash

// 僞代碼
N = 52 // 總牌數
S = 0 // 已經排序整齊的牌數

for (1 到 N -1) {
  // 作 N - 1 輪排序,每輪排序都能找到一張最小牌
  for (1 到 N) {
    // 每輪 N 次交換或移動
   
    if (前兩張牌都是未排列整齊的牌) {
        比較後將大的放到最下面(在未排列整齊的牌裏找小牌)
    if (一旦前兩張牌中出現排列整齊的牌) {
        比較後將小的牌放到最下面
    }
  }
}

將最上面的一張牌放到最後

排序完成
複製代碼

咱們假設只有 5 張牌,來看看具體會變成什麼樣子。less

初始順序 -> 4 2 5 3 1 
    第1輪排序
比較並移動大牌 -> 2 5 3 1 4
比較並移動大牌 -> 2 3 1 4 5
比較並移動大牌 -> 2 1 4 5 3
比較並移動大牌 -> 1 4 5 3 2  // 此時最上面的牌最小
比較並移動小牌 -> 4 5 3 2 1  // 因此改成比較小牌

    第2輪排序
// 太巧合了 0,0 看上去雖然順了,但實際咱們只能看到前兩張牌,因此是這樣的 4 3 * * *
比較並移動大牌 -> 4 3 2 1 5 
比較並移動大牌 -> 3 2 1 5 4
比較並移動大牌 -> 2 1 5 4 3 // 此時最上面的牌第二小
比較並移動小牌 -> 2 5 4 3 1 // 因此改成比較小牌
比較並移動小牌 -> 5 4 3 1 2

    第3輪排序
比較並移動大牌 -> 4 3 1 2 5 
比較並移動大牌 -> 3 1 2 5 4 // 此時最上面的牌第三小
比較並移動小牌 -> 3 2 5 4 1 // 因此改成比較小牌
比較並移動小牌 -> 3 5 4 1 2 
比較並移動小牌 -> 5 4 1 2 3

...
複製代碼

每次第 n 輪結束時,牌堆最後 n 張牌都是從小到大排序整齊的了。ui

因此在 n - 1輪結束時,牌堆最上面的一張牌是最大的牌,其他 n - 1 張牌都是從小大排序整齊的,直接將最上面的牌放到最下面排序就完成了。spa

第3輪排序結束時 -> 5 4 1 2 3
    第4輪排序
比較並移動大牌 -> 4 1 2 3 5 // 此時最上面的牌第四小
比較並移動小牌 -> 4 2 3 5 1 // 因此改成比較小牌
比較並移動小牌 -> 4 3 5 1 2
比較並移動小牌 -> 4 5 1 2 3  
比較並移動小牌 -> 5 1 2 3 4

    第5輪排序
移動最上面一張 -> 1 2 3 4 5

排序完成
複製代碼

代碼

let array = [...] // 牌堆
function less (a, b) {...} // 比較 a 是否小於 b,並返回布爾值
function exch (array, i, j) {...} // 交換 array 中 i 和 j 的值

let N = array.length;

for (let i = 1; i < N - 1; i++) {

  for (let j = 0; j < N; j++) {
    if (j < (N - 1 - i)) {
      if (less(array[0], array[1])) {
        exch(array, 0, 1);
      }
    } else {
      if (less(array[1], array[0])) {
        exch(array, 0, 1);
      }
    }

    array.push(array.shift());
  }
}

array.push(array.shift());
複製代碼

DEMO

CodePencode

羅小黑寫寫文字

若是喜歡文章 請留下一個贊~ 若是喜歡文章 分享給更多人~cdn

掘金中關注我 在簡書中關注我blog

自由轉載-非商用-非衍生-保持署名(創意共享3.0許可證) 轉載時請保留原文連接 以保證可及時獲取對文章的訂正和修改排序

相關文章
相關標籤/搜索