数据结构与算法----复习Part 12 (字符串初步)

本系列是算法通关手册LeeCode的学习笔记

算法通关手册(LeetCode) | 算法通关手册(LeetCode) (itcharge.cn)

 

目录

一,字符串(String)

二,字符串的比较

三,字符串的存储结构

四,字符串匹配(String Matching)


一,字符串(String)

        简称为串,是由零个或多个字符组成的有限序列。

        字符变量:字符串每一个位置上的元素都是一个字符变量;

        字符串的长度 n :字符串中字符的数目;

        空串:零个字符构成的串也称为【空字符串(Null String)】,长度为0;

        子串:字符串中任意个连续的字符组成的子序列称为该字符串的【子串(Substring)】,

                   有两种特殊字串:

                                起始位置为 0,长度为 k 的子串称为【前缀(Prefix)】;

                                终止位置为 n - 1,长度为 k 的子串称为【后缀(Suffix)】;

        主串:包含子串的字符串称为【主串】。

        可见字符串与数组有很多相似之处,同样使用名称【下标】的方式来访问一个字符。

单独讨论字符串的原因:

        字符串中的数据元素都是字符,结构相对简单,但规模可能比较庞大;

        经常需要把字符串作为一个整体来使用和处理,操作对象一般不是某个数据元素,而是一组数据元素;

        经常需要考虑多个字符串之间的操作,比如:字符串之间的连接、比较操作。

根据字符串的特点,可将字符串问题分为以下几种:

        字符串匹配问题;

        子串相关问题;

        前缀 / 后缀相关问题;

        回文串相关问题;

        子序列相关问题。

二,字符串的比较

        字符串str1, str2 相等:

                1,len(str1) == len(str2);

                2,str1 和 str2 对应位置上的各个字符都相同。

        字符串比较的依据是编码大小,通常为 ASCII 码。

        首先比较对应位置的字符:

                ' abc ' < ' ad '

        后比较长度:

                ' ab ' < ' aba '

三,字符串的存储结构

        字符串的存储结构与线性表相同,分为【顺序存储结构】和【链式存储结构】。

字符串的顺序存储

        字符串的顺序存储结构也是使用一组地址连续的存储单元依次存放串中的各个字符,按照预定义的大小为每个定义的字符串变量分配一个固定长度的存储区域,一般是用定长数组定义。

        字符串顺序存储中每一个字符元素都有自己的下标索引。

字符串的链式存储结构

        字符串的存储也可以采用链式存储结构,即采用一个线性链表来存储一个字符串,字符串的链节点包含一个用于存储字符的 data 变量,和指向下一个链节点的指针变量 next。

        通常情况下,链节点的字符长度为 1 或者 4,这是为了避免浪费空间。当链节点的字符长度为 4 时,由于字符串的长度不一定是 4 的倍数,因此字符串所占用的链节点中最后那个链节点 data 变量可能没有占满,可以使用 # 或其他不属于字符集的特殊字符将其补全。

不同语言中的字符串

        C语言中字符串使用空字符 \0 结尾的字符数组;

        C++ 中引入 string 类型,完全可以代替 C 中的字符数组或字符串指针;        

        Java 语言的标准库中也提供了 String 类作为字符串库;

        Python 语言中使用 str 对象来代表字符串。 str 对象是一种不可变类型对象,即 str 类型创建

        的字符串在对象定义之后无法更改字符串的长度,也无法改变或删除字符串中的字符。

四,字符串匹配(String Matching)

        又称模式匹配(Pattern Matching),可以简单理解为给定字符串 T 和 p,在主串 T 中寻找子串 p。主串又被称为文本串,子串 p 又被称为模式串(Pattern)

        字符串匹配问题可分为【单模式串匹配问题】和【多模式串匹配问题】

        由于两个问题涉及的算法较多,会分篇学习,本篇内容作为字符串初步到此为止,以下附上有关本篇内容的几道例题,由于数组与字符串的相似性,例题中也使用了数组中指针的思想。

125. 验证回文串 - 力扣(LeetCode)

class Solution:
    def isPalindrome(self, s: str) -> bool:
        left = 0
        right = len(s) - 1
        while left < right:
            if not s[left].isalnum():
                left += 1
                continue
            if not s[right].isalnum():
                right -= 1
                continue
            if s[left].lower() == s[right].lower():
                left += 1
                right -= 1
            else:
                return False
        return True

3. 无重复字符的最长子串 - 力扣(LeetCode)

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        left = 0
        right = 0
        window = dict()
        ans = 0
        while right < len(s):
            if s[right] not in window:
                window[s[right]] = 1
            else:
                window[s[right]] += 1
            while window[s[right]] > 1:
                window[s[left]] -= 1
                left += 1
            
            ans = max(ans, right - left + 1)
            right += 1
        return ans

344. 反转字符串 - 力扣(LeetCode)

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        if len(s) < 2:
            return
        left = 0
        right = len(s) - 1
        while left <= right:
            s[left], s[right] = s[right], s[left]
            left += 1
            right -= 1
        return 

415. 字符串相加 - 力扣(LeetCode)

class Solution:
    def addStrings(self, num1: str, num2: str) -> str:
        # num1 位数
        digit1 = len(num1) - 1
        # num2 位数
        digit2 = len(num2) - 1

        # 进位
        carry = 0
        sum = []
        # 逆序相加
        while carry > 0 or digit1 >= 0 or digit2 >= 0:
            # 获取对应位数上的数字
            num1_d = int(num1[digit1]) if digit1 >= 0 else 0
            num2_d = int(num2[digit2]) if digit2 >= 0 else 0
            digit1 -= 1
            digit2 -= 1
            # 计算结果,存储,进位
            num = num1_d+num2_d+carry
            sum.append('%d'%(num%10))
            carry = num // 10
        # 返回计算结果
        return "".join(sum[::-1])

151. 反转字符串中的单词 - 力扣(LeetCode)

class Solution:
    def reverseWords(self, s: str) -> str:
        if len(s) < 2:
            return s
        ss = s.split()
        left = 0
        right = len(ss) - 1
        res = ''
        while left <= right:
            ss[left], ss[right] = ss[right], ss[left]
            left += 1
            right -= 1
        for i in range(len(ss) - 1):
            res += ss[i]
            res += ' '
        return res + ss[-1]

43. 字符串相乘 - 力扣(LeetCode)

class Solution:
    def multiply(self, num1: str, num2: str) -> str:
        if num1 == "0" or num2 == "0":
            return "0"

        len1, len2 = len(num1), len(num2)
        nums = [0 for _ in range(len1 + len2)]

        for i in range(len1 - 1, -1, -1):
            digit1 = int(num1[i])
            for j in range(len2 - 1, -1, -1):
                digit2 = int(num2[j])
                nums[i + j + 1] += digit1 * digit2

        for i in range(len1 + len2 - 1, 0, -1):
            nums[i - 1] += nums[i] // 10
            nums[i] %= 10

        if nums[0] == 0:
            ans = "".join(str(digit) for digit in nums[1:])
        else:
            ans = "".join(str(digit) for digit in nums[:])
        return ans

14. 最长公共前缀 - 力扣(LeetCode)

class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        res = strs[0]
        if len(strs) < 2:
            return res
        for i in range(1, len(strs)):
            for j in range(len(res)):
                if j == len(strs[i]):
                    res = res[0: j]
                    break
                if res[j] != strs[i][j]:
                    if j == 0:
                        return ""
                    res = res[0: j]
                    break
        return res

算法通关手册(LeetCode) | 算法通关手册(LeetCode)

原文内容在这里,如有侵权,请联系我删除。

  • 28
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值