代码随想录算法训练营第九天|151.翻转字符串里的单词、卡码网:55.右旋转字符串、28. 实现 strStr()、459.重复的子字符串、双指针回顾 |纯小白python

151.翻转字符串里的单词

题目

给你一个字符串 s ,请你反转字符串中 单词 的顺序。

单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。

注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

尝试解答

class Solution(object):
    def reverseWords(self, s):
        """
        :type s: str
        :rtype: str
        """
        words = s.split()
        left=0
        right=len(words)-1
        while left<right:
            words[left],words[right]=words[right],words[left]
            left+=1
            right-=1
        return " ".join(words)

代码随想录的代码 

class Solution:
    def reverseWords(self, s: str) -> str:
        # 删除前后空白
        s = s.strip()
        # 反转整个字符串
        s = s[::-1]
        # 将字符串拆分为单词,并反转每个单词
        s = ' '.join(word[::-1] for word in s.split())
        return s

split函数是拆分字符串的,strip函数是去除空白字符。

卡码网:55.右旋转字符串

题目

字符串的右旋转操作是把字符串尾部的若干个字符转移到字符串的前面。给定一个字符串 s 和一个正整数 k,请编写一个函数,将字符串中的后面 k 个字符移到字符串的前面,实现字符串的右旋转操作。

代码

k = int(input())
s = input()

print(s[-k:] + s[:-k])

28. 实现 strStr()

题目 

给你两个字符串 haystack 和 needle ,请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标(下标从 0 开始)。如果 needle 不是 haystack 的一部分,则返回  -1

代码随想录学习-KMP算法

KMP算法的核心思想是通过预处理模式字符串,构建一个部分匹配表,该表记录了模式字符串自身的重复结构。在匹配过程中,当出现字符不匹配时,利用部分匹配表可以避免重复比较已经匹配好的字符。即KMP算法主要应用在字符串匹配上。

前缀表:用来回退,记录了模式串与主串不匹配时,模式串应该从哪里重新匹配。记录下标之前(包括下标)的字符串中,有多大长度的相同前缀后缀。

最长公共前后缀

前缀是指包含第一个字符但不包括最后一个字符的连续子字符串

后缀是指包含最好一个字符但不包括首字符的连续子字符串

最长公共前后缀就是前后缀字节数相同且最长。

步骤:

1.初始化:定义两个指针i和j,j指向前缀末尾位置,i指向后缀末尾位置。

2.处理前后缀不相同的情况

3.处理前后缀相同的情况

4.更新next

学习复述

KMP算法就是利用前缀表来找匹配字符串。它是从前面已经匹配好的开始。例如主串为aabaabaafa,模式串为aabaaf,当f不匹配,看前面aabaa,它的前缀和后缀完全相同的是aa。所以从后缀的前一个字母开始匹配,即从b再匹配。在写代码中关键是要找到这个最长公共前后缀的长度,这样就可以知道从哪里开始匹配。而具体代码思路,首先需要两个指针i和j,i指向后缀末尾,j指向前缀末尾。同时j也表示最长公共前后缀的长度。next表示每个子字符串的最长前后缀长度。首先是初始化,那么next初始化为0。因为对于第一个字母,前后缀为0。j前缀末尾初始化为0。对于个数为2的子字符串,这样前缀末尾是0,后缀末尾为1。j,i即初始化为0,1。接着分为两种情况,一是前后缀相同,j加1后付给next,i也加1。二是前后缀不相同,前缀末尾往前移直至为0后将0付给next。以上为大致思路。下面看具体代码:

代码1-前缀表-1 

class Solution:
    def getNext(self, next, s):
        j = -1
        next[0] = j
        for i in range(1, len(s)):
            while j >= 0 and s[i] != s[j+1]:
                j = next[j]
            if s[i] == s[j+1]:
                j += 1
            next[i] = j
    
    def strStr(self, haystack: str, needle: str) -> int:
        if not needle:
            return 0
        next = [0] * len(needle)
        self.getNext(next, needle)
        j = -1
        for i in range(len(haystack)):
            while j >= 0 and haystack[i] != needle[j+1]:
                j = next[j]
            if haystack[i] == needle[j+1]:
                j += 1
            if j == len(needle) - 1:
                return i - len(needle) + 1
        return -1

代码2-前缀不减1 

class Solution:
    def getNext(self, next: List[int], s: str) -> None:
        j = 0
        next[0] = 0
        for i in range(1, len(s)):
            while j > 0 and s[i] != s[j]:
                j = next[j - 1]
            if s[i] == s[j]:
                j += 1
            next[i] = j
    
    def strStr(self, haystack: str, needle: str) -> int:
        if len(needle) == 0:
            return 0
        next = [0] * len(needle)
        self.getNext(next, needle)
        j = 0
        for i in range(len(haystack)):
            while j > 0 and haystack[i] != needle[j]:
                j = next[j - 1]
            if haystack[i] == needle[j]:
                j += 1
            if j == len(needle):
                return i - len(needle) + 1
        return -1

然后对于strStr函数,就是当haystack中的字母与needle字母不相同时,needle里的字母跳到next里的前一个,然后继续比对,相等的话就跳到下一个。直至将整个needle遍历完,输出匹配的索引。 

459.重复的子字符串

题目 

给定一个非空的字符串 s ,检查是否可以通过由它的一个子串重复多次构成。

尝试解答

感觉这个也是可以用KMP算法的,但是由next数组判断该字符串是否由子字符串组成还是不会写,还是看一下代码随想录吧

代码随想录的代码

代码

class Solution:
    def repeatedSubstringPattern(self, s: str) -> bool:  
        if len(s) == 0:
            return False
        nxt = [0] * len(s)
        self.getNext(nxt, s)
        if nxt[-1] != 0 and len(s) % (len(s) - nxt[-1]) == 0:
            return True
        return False
    
    def getNext(self, nxt, s):
        nxt[0] = 0
        j = 0
        for i in range(1, len(s)):
            while j > 0 and s[i] != s[j]:
                j = nxt[j - 1]
            if s[i] == s[j]:
                j += 1
            nxt[i] = j
        return nxt

假设字符串s使用多个重复子串构成(这个子串是最小重复单位),重复出现的子字符串长度是x,所以s是由n * x组成。

因为字符串s的最长相同前后缀的长度一定是不包含s本身,所以 最长相同前后缀长度必然是m * x,而且 n - m = 1,(这里如果不懂,看上面的推理)

所以如果 nx % (n - m)x = 0,就可以判定有重复出现的子字符串。

以上是代码随想录的推导,我觉得我的一个错误在于在推这个判断公式的时候我是有点凑数的感觉,看怎么凑才能使得各个数值对的上。但其实应该直接推导。 

双指针回顾 

数组

在移除数组中,为了提高效率,利用快慢指针进行数组的覆盖。

字符串

在反转字符串时,定义左右指针向中间移动,交换元素

链表

在反转链表中,只需要改变链表的next指针的指向,直接将链表反转 ,而不用重新定义一个新的链表。

而在链表中求环,使用快慢指针,分别定义 fast 和 slow指针,从头结点出发,fast指针每次移动两个节点,slow指针每次移动一个节点,如果 fast 和 slow指针在途中相遇 ,说明这个链表有环。

N数之和

对于三数、四数之和,哈希表不适用。因为去重比较困难,而利用指针就直接可以将重复元素跳过。通过前后两个指针不算向中间逼近,在一个for循环下完成两个for循环的工作。四数之和,其实思路是一样的,就是三数之和的基础上再套一层for循环。
 

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值