[Go版]算法通关村第十二关黄金——字符串冲刺题

这篇具有很好参考价值的文章主要介绍了[Go版]算法通关村第十二关黄金——字符串冲刺题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

题目:最长公共前缀

题目链接:LeetCode-14. 最长公共前缀
[Go版]算法通关村第十二关黄金——字符串冲刺题,算法与数据结构,golang,算法,开发语言

解法1:纵向对比-循环内套循环写法

以第一个子字符串为标准,遍历其每个字符时,内嵌遍历其余子字符串的对应字符是否一致。不一致时,则返回当前字符之前的子字符串。

复杂度:时间复杂度 O ( n ∗ m ) O(n*m) O(nm)、空间复杂度 O ( 1 ) O(1) O(1)

  • 时间复杂度:其中 n 是字符串平均长度,m 是字符串数组的长度。

Go代码

func longestCommonPrefix(strs []string) string {
    length := len(strs)
    if length==1 {
        return strs[0]
    }
    chlen := len(strs[0])
    for i:=0; i<chlen; i++ {
        // 用第一个子字符串的字符作为比较
        ch := strs[0][i]
        for j, v := range strs {
            if j == 0 {
                continue
            }
            // 子字符串的长度比第一个短 或者 出现比较字符不同
            if i == len(v) || v[i] != ch {
                return string(strs[0][:i])
            }
        }
    }
    return strs[0]
}

解法2:横向对比-两两对比(类似合并K个数组、合并K个链表)

  1. 先让前两个子字符串对比得到公共前缀
  2. 再将此公共前缀作和下一个子字符串对比得到公共前缀
  3. 如此循环到末尾,返回最后的公共前缀即可
  4. 优化:遍历过程中如果公共前缀已经是空字符串了,则可直接返回空字符串。

相比于解法1的优点:将逻辑分解到两个函数中,使代码更加模块化和可维护。

复杂度:时间复杂度 O ( n ∗ m ) O(n*m) O(nm)、空间复杂度 O ( 1 ) O(1) O(1)

  • 时间复杂度:其中 n 是字符串平均长度,m 是字符串数组的长度。

Go代码

func longestCommonPrefix(strs []string) string {
    length := len(strs)
    if length == 1 {
        return strs[0]
    }
    str := strs[0]
    for i:=1; i<length; i++ {
        str = getCommonPrefix(str, strs[i])
        if str == "" {
            return ""
        }
    }
    return str
}

func getCommonPrefix(str1, str2 string) string {
    length2 := len(str2)
    for i, v := range str1 {
        val := byte(v)
        if i == length2 || val != str2[i] {
            return string(str1[:i])
        }
    }
    return str1
}

题目:压缩字符串

题目链接:LeetCode-443. 压缩字符串
[Go版]算法通关村第十二关黄金——字符串冲刺题,算法与数据结构,golang,算法,开发语言

解法1:读写指针 + 次数统计 + 顺向思维处理次数输出

  1. 安排读写指针,分别指向要写的位置,和读的位置,两指针首先指向第一个字符

  2. 如果是相同时最后一个元素的标记,或者 读指针的字符和写指针不同时

    1. 统计总次数,区分是否 >1
      • 大于1:区分是否 >= 10
        • 小于10:仅追加一个数字
        • 大于10:不断除10,得到可除次数,和除10的最后余数
          1. 追加最后余数
          2. 遍历可除次数,追加数值0
          3. 根据可除次数,用总次数除了10的可除次数次方,得到余数,追加余数
    2. 如果是相同时最后一个元素的标记,到这里直接返回写指针+1即可
    3. 更新对比字符为当前字符,追加对比字符
    4. 总次数还原为1,读指针++
    5. 如果是最后一个元素,到这里直接返回写指针+1即可
  3. 相同时,总次数++

    • 如果是最后一个元素,添加标记(这里只为加上其相同次数)

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

Go代码

func compress(chars []byte) int {
    length := len(chars)
    if length == 0 || length == 1 {
        return length
    }
    left, right := 0, 1 // left写 right读
    num := 1    //次数统计
    ch := chars[0]
    lastone := false
    for lastone || right < length {
        if lastone || chars[right] != chars[left] {
            // 追加长度
            if num > 1 {
                // 要追加多个长度
                if num >= 10 {
                    tmpnum := num
                    count10 := 1
                    // 明确有几个10
                    for tmpnum >= 10 {
                        tmpnum = tmpnum/10
                        if tmpnum >= 10 {
                            count10++
                        }
                    }
                    // 追加大于10的首个数字
                    left++
                    chars[left] = byte(tmpnum + '0')   
                    for i:=1; i<count10; i++ {
                        // 补零
                        left++
                        chars[left] = '0'
                    }
                    // 追加大于等于10时的余数
                    f10 := math.Pow(10, float64(count10))
                    yu := num % int(f10)
                    if yu >= 0 {
                        left++
                        chars[left] = byte(yu + '0')
                    }
                } else {    //只追加一个长度
                    left++
                    chars[left] = byte(num + '0')
                }
            }
            if lastone {
                return left+1
            }
            ch = chars[right]
            // 追加新字符
            left++
            chars[left] = ch
            num = 1
            right++
            // 如果是最后一个元素
            if right == length {
                return left+1
            }
        } else {
            num++
            right++
            if right == length {
                lastone = true
            }
        }
    }
    return left+1
}

解法2:读写起始三指针 + 逆向思维处理次数输出(优化解法1)

优化点:文章来源地址https://www.toymoban.com/news/detail-657183.html

  1. 无需用变量循环时累加统计总次数:让一个起始指针指向当前统计字符的首位置,当遍历到该字符末尾时,尾索引-首索引+1=总次数
  2. 将正向计算追加>10时的最后余数、可除10次数、余数改为:追加依次除10得到的余数,最后反转该段数字区间即可。
  3. 读指针和下一个不同时处理当前,此时包含了最后一个字符的场景。解法1中读指针和写指针不同时处理的逻辑就没法包含最后一个字符,需要考虑最后一个字符时是和之前一致还是不同的情况。

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

Go代码

func compress(chars []byte) int {
    length := len(chars)
    if length == 0 || length == 1 {
        return length
    }
    left, right, start := 0, 0, 0
    for ; right < length; right++ {
        if right == length-1 || chars[right] != chars[right+1] {
            chars[left] = chars[right]
            left++
            count := right-start+1
            site := left
            if count > 1 {
                for count > 0 {
                    n := count%10
                    chars[left] = byte(n + '0')
                    left++
                    count = count/10
                }
                reverse(chars, site, left-1)
            }
            start = right+1
        }
    }
    return left
}
func reverse(chars []byte, left int, right int) {
    if left >= right {
        return
    }
    for left <= right {
        chars[left], chars[right] = chars[right], chars[left]
        left++
        right--
    }
}

到了这里,关于[Go版]算法通关村第十二关黄金——字符串冲刺题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 不简单的字符串转换问题(算法村第十二关青铜挑战)

    709. 转换成小写字母 - 力扣(LeetCode) 给你一个字符串 s ,将该字符串中的大写字母转换成相同的小写字母,返回新的字符串。 1 = s.length = 100 解 大写字母和小写字母的值之间存在固定的差异。例如,小写字母 a 的ASCII值为 97 ,而对应的大写字母 A 的ASCII值为 65 ,两者之差恰

    2024年01月25日
    浏览(35)
  • [Go版]算法通关村第十五关黄金——继续研究超大规模数据场景的问题

    在 海量数据 中,此时普通的数组、链表、Hash、树等等结构有无效了 ,因为内存空间放不下了。而常规的递归、排序,回溯、贪心和动态规划等思想也无效了,因为执行都会超时,必须另外想办法。这类问题该如何下手呢?这里介绍三种非常典型的思路: 使用位存储 ,使用

    2024年02月10日
    浏览(27)
  • [Go版]算法通关村第十三关黄金——数字数学问题之数论问题(最大公约数、素数、埃氏筛、丑数)

    题目链接:LeetCode-1979. 找出数组的最大公约数 辗转相除法其核心部分为:若r 是a ÷ b的余数,则 gcd(a, b)=gcd(b, r) 题目链接:LeetCode-204. 计数质数 如果 x 是质数,那么大于 x 的 x 的倍数 2x,3x,… 一定不是质数。 时间复杂度分析: 外层循环的迭代次数是 n-2,即 O ( n ) O(n) O ( n ) 次

    2024年02月11日
    浏览(26)
  • 算法通关村第十六关:黄金挑战:滑动窗口与堆结合

    堆的大小一般是有限的,能直接返回当前位置下的最大值或者最小值 该特征与滑动窗口结合,可以解决一些特定场景的问题 1. 滑动窗口与堆问题的结合 LeetCode239 https://leetcode.cn/problems/sliding-window-maximum/ 思路分析 对于最大值,K个最大这种场景,优先队列(堆)是首先该考虑的

    2024年02月09日
    浏览(27)
  • [Go版]算法通关村第二关——终于学会链表反转了

    题目链接:LeetCode-206. 反转链表 源码地址:GitHub-golang版本 说明:遍历该链表,依次取出当前节点插入到新链表的首位(虚拟头结点紧后)即可, 注意要提前保存当前节点的Next数据 ,否则插入到新链表后就没法继续向下遍历了。 说明:原理和方法1一致,只不过现在没有虚拟

    2024年02月14日
    浏览(30)
  • [Go版]算法通关村第二关青铜——终于学会链表反转了

    题目链接:LeetCode-206. 反转链表 源码地址:GitHub-golang版本 说明:遍历该链表,依次取出当前节点插入到新链表的首位(虚拟头结点紧后)即可, 注意要提前保存当前节点的Next数据 ,否则插入到新链表后就没法继续向下遍历了。 说明:原理和方法1一致,只不过现在没有虚拟

    2024年02月13日
    浏览(24)
  • 【LeetCode】《LeetCode 101》第十二章:字符串

    思路及代码: 242 . 有效的字母异位词 思路及代码: 205. 同构字符串 思路及代码: 647. 回文子串 思路及代码: 696 . 计数二进制子串 思路及代码 : 224. 基本计算器 思路及代码: 227. 基本计算器 II 思路与代码: 28 . 找出字符串中第一个匹配项的下标 思路及代码 :409. 最长回文

    2024年02月10日
    浏览(30)
  • 算法通关村十三关 | 数组字符串加法专题

    题目:LeetCode66,66. 加一 - 力扣(LeetCode) 我们只需要从头到尾依次运算,用常量标记是否进位,需要考虑的特殊情况是digits = [9,9,9]的时候进位,我们组要创建长度加1的数组,首位添加为1即可。         给定两个非负形式的字符串num1和num2,计算他们的和以字符串形式返

    2024年02月11日
    浏览(27)
  • [Go版]算法通关村第十五关青铜——用4KB内存寻找重复元素

    在 海量数据 中,此时普通的数组、链表、Hash、树等等结构有无效了 ,因为内存空间放不下了。而常规的递归、排序,回溯、贪心和动态规划等思想也无效了,因为执行都会超时,必须另外想办法。这类问题该如何下手呢?这里介绍三种非常典型的思路: 使用位存储 ,使用

    2024年02月11日
    浏览(28)
  • 算法通关村第二关——链表反转

    链表反转,就是链表原来是1-2-3-4-5,经过反转处理过后变成5-4-3-2-1 处理链表反转,有两种方式,一个是建立虚拟头结点,一个是直接操作链表反转。  这是执行的流程 最核心的两行就是 直接想我要让她反转,我现在设立了虚拟头结点,那我就要让新加进这个反转链表的结点

    2024年02月13日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包