[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
}
相关推荐
wn53124 分钟前
【Go - 类型断言】
服务器·开发语言·后端·golang
青椒大仙KI1127 分钟前
24/9/19 算法笔记 kaggle BankChurn数据分类
笔记·算法·分类
^^为欢几何^^31 分钟前
lodash中_.difference如何过滤数组
javascript·数据结构·算法
豆浩宇31 分钟前
Halcon OCR检测 免训练版
c++·人工智能·opencv·算法·计算机视觉·ocr
浅念同学1 小时前
算法.图论-并查集上
java·算法·图论
何不遗憾呢1 小时前
每日刷题(算法)
算法
立志成为coding大牛的菜鸟.1 小时前
力扣1143-最长公共子序列(Java详细题解)
java·算法·leetcode
鱼跃鹰飞1 小时前
Leetcode面试经典150题-130.被围绕的区域
java·算法·leetcode·面试·职场和发展·深度优先
liangbm31 小时前
数学建模笔记——动态规划
笔记·python·算法·数学建模·动态规划·背包问题·优化问题
潮汐退涨月冷风霜1 小时前
机器学习之非监督学习(四)K-means 聚类算法
学习·算法·机器学习