今是昨非

今是昨非

日出江花红胜火,春来江水绿如蓝

アルゴリズム_ソート

Algorithem_Sort#

与えられた整数配列 nums が非減少順にソートされている場合、各数の平方の配列を非減少順にソートして返します。

QuickSort#

実装ロジック:
指定された位置の index の値 key を取り、index と index の前の数字を比較します。前の数字が後の数字より大きい場合は、位置を交換します。

例えば:


[ 8 3 5 1 4 2 ]

index が1の位置から始めます。現在の要素は3で、前の要素は8です。8 > 3 なので、位置を交換します。配列はまだ [ 3 8 5 1 4 2 ] です。
次に index が2、現在の要素は5、前の要素は8です。8 > 5 なので、位置を交換します。配列は [ 3 5 8 1 4 2 ] です。
次に index が3、現在の要素は1、前の要素は8です。8 > 1 なので、位置を交換します。配列は [ 3 5 1 8 4 2 ] です;5 > 1 なので、位置を交換します。配列は [ 3 1 5 8 4 2 ] です;3 > 1 なので、位置を交換します。配列は [ 1 3 5 8 4 2 ] です。
次に index が4、現在の要素は4、前の要素は8です。8 > 4 なので、位置を交換します。配列は [ 1 3 5 4 8 2 ] です;5 > 4 なので、位置を交換します。配列は [ 1 3 4 5 8 2 ] です。
次に index が5、現在の要素は2、前の要素は8です。8 > 2 なので、位置を交換します。配列は [ 1 3 4 5 2 8 ] です;5 > 2 なので、位置を交換します。配列は [ 1 3 4 2 5 8 ] です;4 > 2 なので、位置を交換します。配列は [ 1 3 2 4 5 8 ] です;3 > 2 なので、位置を交換します。配列は [ 1 2 3 4 5 8 ] です;1 < 2 なので、停止します。

コードは以下の通りです:


class Solution {
    func sortedSquares(_ nums: [Int]) -> [Int] {
        // まず、squareList を取得します
        var squareNums = nums.map({ $0 * $0 })
        for j in 0..<squareNums.count {
            let key = squareNums[j]
            var i = j - 1
            while (i >= 0 && squareNums[i] > key) {
                squareNums[i+1] = squareNums[i]
                i = i - 1
            }
            squareNums[i+1] = key
        }
        return squareNums
    }
}

Selection Sort#

実装ロジック:

配列を走査して最小の値を見つけ、結果配列の index 0 の位置に置きます;
配列を走査して 2 番目に小さい値を見つけ、結果配列の index 1 の位置に置きます;
...

コードは以下の通りです:


class Solution {
    func sortedSquares(_ nums: [Int]) -> [Int] {
        // まず、squareList を取得します
        var squareNums = nums.map({ $0 * $0 })
        
        // selectionSort
        let count = squareNums.count
        for i in 0..<(count-1) {
            var j_min = i
            var j = i+1

            // i から始めて最小の要素の index を見つける
            while (j < count) {
                if squareNums[j] < squareNums[j_min] {
                    j_min = j
                } 
                j = j + 1
            }
            
            // i と最小の index が異なる場合、2つの位置の要素を交換します
            if i != j_min {
                squareNums.swapAt(i, j_min)
            }
        }
        return squareNums
    }
}

Bubble Sort#

ロジックは以下の通りです:

隣接する 2 つの要素を順に走査し、前の要素が大きい場合は位置を交換します;その後、後ろに進んで比較を続けます;
上記の手順を繰り返します
さらに上記の手順を繰り返します
...
交換可能な要素がなくなるまで続けます

例は以下の通りです:


[2, 1, 6, 4, 7, 5]

最初の走査:
index = 1; 現在の要素は2、前の要素は1、2 < 1、位置を交換、[1, 2, 6, 4, 7, 5]
index = 2; 現在の要素は6、前の要素は2、6 > 2、交換は不要
index = 3; 現在の要素は4、前の要素は6、4 < 6、位置を交換、[1, 2, 4, 6, 7, 5]
index = 4; 現在の要素は7、前の要素は6、7 > 6、交換は不要
index = 5; 現在の要素は5、前の要素は7、5 < 7、位置を交換、[1, 2, 4, 6, 5, 7]
中間に交換位置があります

2回目の走査:
index = 1; 現在の要素は2、前の要素は1、2 > 1、交換は不要、[1, 2, 4, 6, 5, 7]
index = 2; 現在の要素は4、前の要素は2、4 > 2、交換は不要
index = 3; 現在の要素は6、前の要素は4、6 > 4、交換は不要
index = 4; 現在の要素は5、前の要素は6、5 < 6、位置を交換、[1, 2, 4, 5, 6, 7]
index = 5; 現在の要素は7、前の要素は6、7 > 6、交換は不要
中間に交換位置があります

3回目の走査:
index = 1; 現在の要素は2、前の要素は1、2 > 1、交換は不要、[1, 2, 4, 5, 6, 7]
index = 2; 現在の要素は4、前の要素は2、4 > 2、交換は不要
index = 3; 現在の要素は6、前の要素は4、6 > 4、交換は不要
index = 4; 現在の要素は6、前の要素は5、6 > 5、交換は不要
index = 5; 現在の要素は7、前の要素は6、7 > 6、交換は不要
今回の走査では交換位置がありませんでした。走査終了です。

コードは以下の通りです:


class Solution {
    func sortedSquares(_ nums: [Int]) -> [Int] {
        // まず、squareList を取得します
        var squareNums = nums.map({ $0 * $0 })
        
        // bubble sort
        var sorted = false;
        while (!sorted) {
            sorted = true
            for i in 1..<(squareNums.count) {
                if (squareNums[i] < squareNums[i-1]) {
                    squareNums.swapAt(i, i-1)
                    sorted = false
                }
            }
        }
        return squareNums
    }
}

merge sort#

実装ロジック:
配列を 2 つに分割し、さらにその 2 つの配列を分割し続け、配列の要素数が 1 になるまで続けます。最後に分割された最小の配列を比較し、ソートして返します。

示意図は以下の通りです:

merge sort demo

コードは以下の通りです:


class Solution {
    func merge(_ left: [Int], _ right: [Int]) -> [Int] {
        // ソートされた結果を格納するための新しい配列を定義します
        var result: [Int] = []

        // 引数を可変にします
        var mutLeft = left
        var mutRight = right

        // ソートを走査します
        while mutLeft.count > 0 && mutRight.count > 0 {
            // ソート
            // 左側が小さい場合は、左側の最初の要素を取り出し、結果配列に追加します。そうでなければ、右側の最初の要素を取り出し、結果配列に追加します。
            result.append(mutLeft[0] < mutRight[0] ? mutLeft.removeFirst() : mutRight.removeFirst())
        }
        // 空でない配列を結合します
        result += (mutLeft.count > 0 ? mutLeft : mutRight)
        // 戻り値
        return result
    }
    
    func mergeSort(_ nums: [Int]) -> [Int] {
        // 配列の要素数が2未満の場合、分割する必要はなく、配列を返します
        if nums.count < 2 {
            return nums
        }
        
        // 中間で配列を分割します
        let middle = nums.count / 2
        
        // 0から middle までの配列の一部を取得します
        let leftSlice = nums[0..<middle]
        // さらに分割を続けます
        let subLeft = mergeSort(Array(leftSlice))
        
        // middle 右側の配列の一部を取得します
        let rightSlice = nums[middle..<nums.count]
        // さらに分割を続けます
        let subRight = mergeSort(Array(rightSlice))

        // 分割できなくなるまで続け、ソートして結合して返します
        return merge(subLeft, subRight)
    }
    
    func sortedSquares(_ nums: [Int]) -> [Int] {
        // まず、squareList を取得します
        var squareNums = nums.map({ $0 * $0 })
        
        // merge sort
        return mergeSort(squareNums)
    }
}

参考#

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。