回环句

标签: 字符串

难度: Easy

句子 是由单个空格分隔的一组单词,且不含前导或尾随空格。

  • 例如,"Hello World""HELLO""hello world hello world" 都是符合要求的句子。

单词 由大写和小写英文字母组成。且大写和小写字母会视作不同字符。

如果句子满足下述全部条件,则认为它是一个 回环句

  • 单词的最后一个字符和下一个单词的第一个字符相等。
  • 最后一个单词的最后一个字符和第一个单词的第一个字符相等。

例如,"leetcode exercises sound delightful""eetcode""leetcode eats soul" 都是回环句。然而,"Leetcode is cool""happy Leetcode""Leetcode""I like Leetcode" 是回环句。

给你一个字符串 sentence ,请你判断它是不是一个回环句。如果是,返回 true ;否则,返回 false

示例 1:

输入:sentence = "leetcode exercises sound delightful"
输出:true
解释:句子中的单词是 ["leetcode", "exercises", "sound", "delightful"] 。
- leetcode 的最后一个字符和 exercises 的第一个字符相等。
- exercises 的最后一个字符和 sound 的第一个字符相等。
- sound 的最后一个字符和 delightful 的第一个字符相等。
- delightful 的最后一个字符和 leetcode 的第一个字符相等。
这个句子是回环句。

示例 2:

输入:sentence = "eetcode"
输出:true
解释:句子中的单词是 ["eetcode"] 。
- eetcode 的最后一个字符和 eetcode 的第一个字符相等。
这个句子是回环句。

示例 3:

输入:sentence = "Leetcode is cool"
输出:false
解释:句子中的单词是 ["Leetcode", "is", "cool"] 。
- Leetcode 的最后一个字符和 is 的第一个字符  相等。 
这个句子  是回环句。

提示:

  • 1 <= sentence.length <= 500
  • sentence 仅由大小写英文字母和空格组成
  • sentence 中的单词由单个空格进行分隔
  • 不含任何前导或尾随空格

Submission

运行时间: 26 ms

内存: 16.0 MB

class Solution:
    def isCircularSentence(self, sentence: str) -> bool:
        words = sentence.split()  # 将句子拆分成单词列表
        n = len(words)
        
        # 检查最后一个单词的最后一个字符和第一个单词的第一个字符是否相等
        if words[-1][-1] != words[0][0]:
            return False
        
        # 检查相邻单词之间的字符是否相等
        for i in range(n - 1):
            if words[i][-1] != words[i + 1][0]:
                return False
        
        return True

solution = Solution()
print(solution.isCircularSentence("leetcode exercises sound delightful"))  # 输出: True
print(solution.isCircularSentence("eetcode"))  # 输出: True
print(solution.isCircularSentence("Leetcode is cool"))  # 输出: False

Explain

此题解的思路首先是将给定的句子拆分成单词列表。之后,首先检查句子的第一个单词的首字母与最后一个单词的末字母是否相等。如果不相等,则直接返回 false,因为这不满足回环句的定义。接着,代码会遍历单词列表,确保每个单词的最后一个字母与下一个单词的第一个字母相等。如果所有检查都通过,则句子是一个回环句,否则不是。

时间复杂度: O(n)

空间复杂度: O(n)

class Solution:
    def isCircularSentence(self, sentence: str) -> bool:
        words = sentence.split()  # 将句子拆分成单词列表
        n = len(words)
        
        # 检查最后一个单词的最后一个字符和第一个单词的第一个字符是否相等
        if words[-1][-1] != words[0][0]:
            return False
        
        # 检查相邻单词之间的字符是否相等
        for i in range(n - 1):
            if words[i][-1] != words[i + 1][0]:
                return False
        
        return True

solution = Solution()
print(solution.isCircularSentence("leetcode exercises sound delightful"))  # 输出: True
print(solution.isCircularSentence("eetcode"))  # 输出: True
print(solution.isCircularSentence("Leetcode is cool"))  # 输出: False

Explore

是的,算法考虑了只有一个单词的情况。对于只有一个单词的句子,因为没有其他单词与之进行比较,所以只需要检查这个单词的最后一个字符是否与其自身的第一个字符相等。根据代码,即使是只有一个单词,也会执行 words[-1][-1] != words[0][0] 的比较,由于它们是同一个单词的首尾字符,通常会相等,因此函数会返回 True。

如果句子为空,即没有单词,那么在尝试访问 words[-1] 或 words[0] 时,代码将引发 IndexError,因为 words 列表将是空的。对于非常短的句子,如只有一个字符的单词,该方法仍然有效,因为这种情况下首尾字符相同。然而,对于空句子的情况,代码需要添加特定的错误处理逻辑,以避免运行时错误。

对于包含大量单词且每个单词只有一个字符的句子,该算法的时间复杂度为 O(n),其中 n 是单词的数量。每个单词仅需与相邻的单词进行一次比较。虽然这种情况下算法已经相当高效,但对于极大规模的数据,常规的字符比较可能会变得耗时。一种可能的优化是在处理前预先验证输入的合理性(如检查输入长度),或者使用并行处理技术分担字符比较的工作。不过,对于大多数实用场景,现有的线性时间复杂度算法已经足够高效。

Python 的 str.split() 函数在没有指定分隔符的情况下,默认会使用空白字符(包括空格、换行符、制表符等)作为分隔符,并且会忽略字符串开头和结尾的空白字符。如果两个单词之间有多个空格,split() 会自动处理这些空格,只将单词作为分割后的元素,不会在结果列表中包含空字符串。因此,多个空格不会影响单词的分割,代码可以正确地将句子分割成单词列表。