package
0.0.0-20241125063422-a7e1e0bf04b0
Repository: https://github.com/blueblue0102/leetcode-go.git
Documentation: pkg.go.dev

# README

324. Wiggle Sort II

https://leetcode.com/problems/wiggle-sort-ii/

已知偶數 index 的數字必須較小,奇數 index 的數字較大
若題目的要求是 nums[0] <= nums[1] => nums[2] <= nums[3]
則就只要使用 quick select 找出 nums 的中位數後,將中位數以左的數字放入偶數 index ;以右的數字放入奇數 index 即可
但題目要求的是 nums[0] < nums[1] > nums[2] < nums[3]
因此若與中位數大小相同的數字不只一個的話,就不能肆意的「將中位數以左的數字放入偶數 index 以右的數字放入奇數」
否則可能導致中位數被擺放在一起的情況發生

所以需要將 nums 分成三堆,分別是【< 中位數】、【= 中位數】和【> 中位數】
且由於需要符合 wiggle 的原因,擺放的方法需要調整
將數字分為三堆,可以使用 DNF 來進行
而過去在進行 DNF 時,【< 中位數】的值會從左邊開始擺起,【> 中位數】會從右邊擺起,【= 中位數】則會不斷夾在 leftright 之間

若將偶數 index 視為過去陣列中的"左邊",奇數 index 視為"右邊"
也就是 len(nums)=10; A(0)=0, A(1)=2, A(2)=4, A(3)=6, A(4)=8, A(5)=1, A(6)=3, A(7)=5, A(8)=7, A(9)=9
如此若將數字由小至大放置的話,【< 中位數】的值會從 A(0) A(1) A(2)... 開始放起;【> 中位數】的值會從 A(9) A(8) A(7)... 開始放起
而最後【= 中位數】會落在 A(3) A(4) A(5) A(6)(隨意舉例),相當於 nums 偶數 index 的尾端以及奇數 index 的頭
由於中位數會從 nums 偶數 index 的尾端開始放起,因此會和奇數 index 的尾端成對,也就是【> 中位數】的那些值
這代表了中位數會優先和【> 中位數】湊一對,直到【> 中位數】不夠湊了,才會從奇數 index 頭端開始放起和【< 中位數】的值配對

這表示,除非【> 中位數】和【< 中位數】的個數都已耗盡,否則中位數之間不可能發生配對

SSSSMMMMLL 為例的話,使用 DNF 擺放完後的結果就會是 A(0)~A(3)=S, A(4)~A(7)=M, A(8)~A(9)=L
nums 實際上相當於 SMSMSMSLML 的排列,符合了題目所需

但是注意,以上狀況在 SSSMMMMMLL 時便會失敗
若按照以上規則,則 SSSMMMMMLL 會排出 SMSMSMMLML,但其實可以排成 MLMLSMSMSM
差別在於 SM + ML or ML + SMSMML 是非法的組合,而 MLSM 是合法的
所以排序的順序要由大至小排列,而不能是由小至大

因此上方以小排至大的一些處理方式就需要調整

在非 worst case 的情況下
quick select 和 DNF 都是 $O(n)$ 時間複雜度和 $O(1)$ 空間複雜度

Takeaway

  • quick select
  • DNF