Skip to main content

Command Palette

Search for a command to run...

Data Structure: Arrays Exercise - Reverse A String

Published
3 min read

Reverse A String: 把任意input的string倒敘排列

JavaScript:

解法一:先把input string轉換成array,組合後再轉回string,最後return

Time Complexity: O(n)

for loop會iterate整個string → O(n)

join會iterate整個array → O(n)

Space Complexity: O(n)

push把資料一個一個放入result array → O(1)

join會建立新的string,長度等於input string → O(n)

function reverseString(input) {
    // check input is string or string length less than 2
    // Time Complexity: O(1)
    if(!input || typeof input != 'string' || input.length < 2 ) {
        return input
    }

    // Space Complexity: O(n)
    const result = []
    const totalItems = input.length - 1
    // Time Complexity: O(n)
    for(let i = totalItems; i >= 0; i--){
        // Time Complexity: O(1)
        result.push(str[i])
    }

    // Time Complexity: O(n)
    // Space Complexity: O(n)
    return result.join('')
}

解法二:直接運用現有的Array methods

Time Complexity: O(n)

split會iterate整個string → O(n)

reversejoin會iterate整個array → 都是O(n)

Space Complexity: O(n)

split會建立新的array,長度等於input string → O(n)

reverse原地反轉整個array,不需建立新的array → O(1)

join會建立新的string,長度等於input string → O(n)

function reverseString(input) {
    return input.split('').reverse().join('')
}

解法三:直接運用現有的Array methods,搭配spread operator

Time Complexity: O(n)

[...input]會iterate整個string → O(n)

reversejoin會iterate整個array → 都是O(n)

Space Complexity: O(n)

[...input]會建立新的array,長度等於input string → O(n)

reverse原地反轉整個array,不需建立新的array → O(1)

join會建立新的string,長度等於input string → O(n)

// [...input]效果等同於split('')
const reverseString = input => [...input].reverse().join('')

Go:

解法一:直接從input string的最後開始iterate,把結果存到output string,最後回傳

Time Complexity: O(n)

for loop會iterate整個string → O(n)

Space Complexity: O(n)

建立新的變數output來儲存for loop iterate的結果 → O(n)

缺點:

方法一比較適合input string長度較短的情境,因為當input string很長的時候,每次執行for迴圈都會建立一個新的output,且在memory上,每建立一個新的output,就需要釋放舊的output,不斷建立和釋放會降低執行效能

func reverseString(input string) string {
    // check the input length
    if len(input) < 2 {
        return input
    }

    output := ""
    for i := len(input) - 1; i >= 0; i-- {
        output += string(input[i])
    }

    return output
}

方法二:建立rune slice,之後都只在這個slice上反轉rune的排序,最後把rune轉換成string再return,適合應用在有Unicode的情境

Time Complexity: O(n)

執行for loop → O(n)

string(output)iterate rune slice,轉換成string→ O(n)

Space Complexity: O(n)

output := []rune(input)建立與input string長度相當的rune slice → O(n)

func reverseString(input string) string {
    // check the input length
    if len(input) < 2 {
        return input
    }

    output := []rune(input)
    // i < j 確保了只有iterate到rune slice的中間,避免了不必要的交換操作
    for i, j := 0, len(output)-1; i < j; i, j = i+1, j-1 {
        // "同時"交換位置
        output[i], output[j] = output[j], output[i]
        // 錯誤寫法:
        // output[i] = output[j]
        // output[j] = output[i]
    }
    return string(output)
}

方法三:把使用情境細分成分別處理ASCII和Unicode,因為Unicode包含了ASCII,先判斷是ASCII,就能直接用效率較高的byte slice[]byte處理,Unicode則用rune slice[]rune處理,不論哪種處理方式,最後都會再轉換成string後回傳

Time Complexity: O(n)

for loop iterate input string逐一檢查是否為純ASCII → O(n)

不論是byte slice方法或rune slice方法,都會執行迴圈轉換位置 → O(n)

string(b)/string(r)iterate byte slice/ rune slice,轉換成string→ O(n)

Space Complexity: O(n)

b := []byte(input)建立與input string長度相當的byte slice → O(n)

r := []rune(input)建立與input string長度相當的rune slice → O(n)

func reverseString(input string) string {
    if len(input) < 2 {
        return input
    }

    // 檢查是否為純 ASCII
    isASCII := true
    for i := 0; i < len(input); i++ {
        // input[i]:
        // 是ASCII時,結果會是ASCII int
        // 非ASCII時,結果會是大於127的int
        if input[i] > 127 {
            isASCII = false
            break
        }
    }

    if isASCII {
        // 使用byte slice方法處理ASCII
        b := []byte(input)
        for i, j := 0, len(b)-1; i < j; i, j = i+1, j-1 {
            b[i], b[j] = b[j], b[i]
        }
        return string(b)
    } else {
        // 使用rune slice方法處理Unicode
        r := []rune(input)
        for i, j := 0, len(r)-1; i < j; i, j = i+1, j-1 {
            r[i], r[j] = r[j], r[i]
        }
        return string(r)
    }
}