[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
}
相关推荐
卑微的小鬼2 分钟前
golang的var ,make ,new, := 的区别
算法
begei4 分钟前
飞牛os使用ddns-go配合华为云实现内网穿透
开发语言·golang·华为云
01_1 小时前
力扣hot100 ——和为k的子数组 前后缀和(积)各种情况总结
数据结构·算法·leetcode·前后缀和(积)计算
一只码代码的章鱼1 小时前
数据结构与算法-搜索-双向搜索 和 A*算法(字串变换,八数码,第k短路)
算法
咚咚轩1 小时前
算法1-2 排序(快排)
算法
楼台的春风1 小时前
【STM32 基于PID的闭环电机控制系统】
c语言·stm32·单片机·嵌入式硬件·mcu·物联网·算法
卑微的小鬼1 小时前
Go 语言结合 Redis 实现固定窗口、滑动窗口、令牌桶和漏桶限流算法的示例代码
开发语言·redis·golang
老A的AI实验室1 小时前
通俗理解Test time Scaling Law、RL Scaling Law和预训练Scaling Law
人工智能·深度学习·算法·chatgpt·llm·agi·rl
_Itachi__2 小时前
LeetCode 热题 100 206. 反转链表
算法·leetcode·链表
YGGP2 小时前
【Gee】Day5:中间件
中间件·golang