[Go版]算法通关村第十二关白银——字符串经典基础面试题

目录

反转专题

题目:反转字符串

题目链接:LeetCode-344. 反转字符串

思路分析:左右双指针 + 对向交换

复杂度:时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( 1 ) O(1) O(1)

Go代码

go 复制代码
func reverseString(s []byte)  {
    length := len(s)
    left, right := 0, length-1
    for left <= right {
        s[left], s[right] = s[right], s[left]
        left++
        right--
    }
    return
}

题目:反转字符串 II

题目链接:LeetCode-541. 反转字符串 II

思路分析:K个一组反转思想(找到每组的首尾索引)

复杂度:时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( n ) O(n) O(n)

Go代码

go 复制代码
func reverseStr(s string, k int) string {
    arr := []byte(s)
    length := len(arr)
    left := 0
    for left < length {
        // 剩余字符少于 k 个,则将剩余字符全部反转。
        if (length-left) < k {
            reverse(arr, left, length-1)
        } else {
            reverse(arr, left, left+k-1)
        }
        left = left+k*2
    }
    return string(arr)
}

func reverse(s []byte, left int, right int) {
    if left >= right {
        return
    }
    for left<=right {
        s[left], s[right] = s[right], s[left]
        left++
        right--
    }
}

题目:仅仅反转字母

题目链接:LeetCode-917. 仅仅反转字母

思路分析:左右双指针 + 对向交换字母 + 跳过非字母

复杂度:时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( n ) O(n) O(n)

Go代码

go 复制代码
func reverseOnlyLetters(s string) string {
    arr := []byte(s)
    length := len(arr)
    left, right := 0, length-1
    for left <= right {
        for left <= right && notA2z(arr[left]) {
            left++
        }
        for left <= right && notA2z(arr[right]) {
            right--
        }
        if left <= right {
            arr[left], arr[right] = arr[right], arr[left]
            left++
            right--
        }
    }
    return string(arr)
}

func notA2z (ch byte) bool {
    // 大写字母 A - Z 的 ASCII 码范围为 [65,90]
    // 小写字母 a - z 的 ASCII 码范围为 [97,122]
    if ch < 65 || ch > 122 {
        return true
    }
    if ch > 90 && ch < 97 {
        return true
    }
    return false
}

题目:反转字符串中的单词

题目链接:LeetCode-151. 反转字符串中的单词

思路分析:去除空格 + 全面反转 + K个一组反转思想(K不定长,找到每组首尾索引)

  1. 去除字符串两端的空格
  2. 对整个去除空格后的字符串进行了一次反转
  3. 遍历字符串中的每个单词,将它们进行反转,并拼接成一个新的字符串

    与这个图的思路大致相同,不过我们实现是在 翻转每个单词后 加上 一个空格 存储数组中返回。

复杂度:时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( n ) O(n) O(n)

Go代码

go 复制代码
func reverseWords(s string) string {
    arr := []byte(s)
    length := len(arr)
    left, right := 0, length-1
    // 去除首尾空格
    for {
        if arr[left] == ' ' {
            left++
        } else {
            break
        }
    }
    for {
        if arr[right] == ' ' {
            right--
        } else {
            break
        }
    }
    var arr2 []byte
    if right < length-1 {
        arr2 = arr[left:right+1]
    } else {
        arr2 = arr[left:]
    }
    length = len(arr2)
    reverse(arr2, 0, length-1)
    var arr3 []byte
    left = 0
    for left < length {
        for left < length {
            if arr2[left] == ' ' {
                left++
            } else {
                break
            }
        }
        right = left
        for right < length {
            if arr2[right] == ' ' {
                break
            } else {
                right++
            }
        }
        reverse(arr2, left, right-1)
        arr3 = append(arr3, arr2[left:right]...)
        if right == length {
            break
        }
        arr3 = append(arr3, ' ')
        left = right
    }
    return string(arr3)
}

func reverse(arr []byte, left int, right int) {
    if left >= right {
        return 
    }
    for left <= right {
        arr[left], arr[right] = arr[right], arr[left]
        left++
        right--
    }
}

题目:验证回文串

题目链接:LeetCode-125. 验证回文串

思路分析:只留下有效字符后,左右双指针对向比较值

复杂度:时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( n ) O(n) O(n)

Go代码

go 复制代码
func isPalindrome(s string) bool {
    arr := []rune{}
    for _, v := range s {
        if res, ch := isValid(v); res {
            arr = append(arr, ch)
        }
    }
    length := len(arr)
    left, right := 0, length-1
    for left<=right {
        if arr[left] != arr[right] {
            return false
        }
        left++
        right--
    }
    return true
}

func isValid(ch rune) (bool, rune) {
    if ch >= 'A' && ch <= 'Z' {
        ch = ch | 32
        return true, ch
    }
    if ch >= 'a' && ch <= 'z' {
        return true, ch
    }
    if ch >= '0' && ch <= '9' {
        return true, ch
    }
    return false, ch
}

题目:字符串中的第一个唯一字符

题目链接:LeetCode-387. 字符串中的第一个唯一字符

思路分析:使用哈希表存储字符及其出现次数,遍历找到目标字符

复杂度:时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( n ) O(n) O(n)

Go代码

go 复制代码
func firstUniqChar(s string) int {
    maps := make(map[rune]int, 0)
    for _, v := range s {
        maps[v]++
    }
    for i, v := range s {
        if maps[v] == 1 {
            return i
        }
    }
    return -1
}

题目:有效的字母异位词(判断是否互为字符重排)

题目链接:LeetCode-242. 有效的字母异位词

思路分析:使用哈希表存储字符及其出现次数,遍历另一个字符串对哈希表减值,判断是否<0

复杂度:时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( k ) O(k) O(k)

  • 空间复杂度为 O ( k ) O(k) O(k),其中 k 是字符串中不同字符的数量,即存储在 map 中的键的数量。

Go代码

go 复制代码
func isAnagram(s string, t string) bool {
    if len(s) != len(t) {
        return false
    }
    maps := getMap(s)
    for _, v := range t {
        maps[v]--
        if maps[v] < 0 {
            return false
        }
    }
    return true
}

func getMap(s string) map[rune]int {
    ret := make(map[rune]int, 0)
    for _, v := range s {
        ret[v]++
    }
    return ret
}
相关推荐
迷迭所归处1 分钟前
动态规划 —— 子数组系列-单词拆分
算法·动态规划
爱吃烤鸡翅的酸菜鱼2 分钟前
Java算法OJ(8)随机选择算法
java·数据结构·算法·排序算法
hummhumm23 分钟前
第 25 章 - Golang 项目结构
java·开发语言·前端·后端·python·elasticsearch·golang
寻找码源44 分钟前
【头歌实训:利用kmp算法求子串在主串中不重叠出现的次数】
c语言·数据结构·算法·字符串·kmp
Matlab精灵1 小时前
Matlab科研绘图:自定义内置多款配色函数
算法·matlab
好奇的菜鸟1 小时前
Go语言中的引用类型:指针与传递机制
开发语言·后端·golang
诚丞成1 小时前
滑动窗口篇——如行云流水般的高效解法与智能之道(1)
算法
Alive~o.01 小时前
Go语言进阶&依赖管理
开发语言·后端·golang
带多刺的玫瑰2 小时前
Leecode刷题C语言之统计不是特殊数字的数字数量
java·c语言·算法
爱敲代码的憨仔2 小时前
《线性代数的本质》
线性代数·算法·决策树