2381. 字母移位 II

123 阅读1分钟

题目:
给你一个小写英文字母组成的字符串 s 和一个二维整数数组 shifts ,其中 shifts[i] = [starti, endi, directioni] 。对于每个 i ,将 s 中从下标 starti 到下标 endi (两者都包含)所有字符都进行移位运算,如果 directioni = 1 将字符向后移位,如果 directioni = 0 将字符向前移位。

将一个字符 向后 移位的意思是将这个字符用字母表中 下一个 字母替换(字母表视为环绕的,所以 'z' 变成 'a')。类似的,将一个字符 向前 移位的意思是将这个字符用字母表中 前一个 字母替换(字母表是环绕的,所以 'a' 变成 'z' )。

请你返回对 s 进行所有移位操作以后得到的最终字符串。

算法:
方法一:差分数组
前缀和适用于原始数组不变,多次范围查询的场景。
差分数组适合,多次范围变化,最后通过差分还原前缀和,再范围查询的场景。

func shiftingLetters(s string, shifts [][]int) string {
    diff := make([]int, len(s) + 1)
    // 计算差分数组
    for i := range shifts {
        val := shifts[i][2] 
        // 左移一位相当于右移25位
        if val == 0 {
            val = -1
        } 
        diff[shifts[i][0]] = diff[shifts[i][0]] + val
        diff[shifts[i][1] + 1] = diff[shifts[i][1] + 1] - val
    }
    // 通过差分数组,还原前缀和,计算每一位的移动数
    for i := 1; i < len(diff); i ++ {
        diff[i] = diff[i - 1] + diff[i]
    }
    // fmt.Println(diff)
    byt := []byte(s)
    for i := range byt {
        // 可能有负数,加上26再求余,左移一位-1相当于右移25位+25
        // (int(byt[i] - 'a' ) + diff[i]) % 26 防溢出
        byt[i] = byte('a' + ((int(byt[i] - 'a' ) + diff[i]) % 26 + 26 ) % 26)
    }
    return string(byt)
}