LeetCode 2490 - Circular Sentence

The problem asks us to determine whether a given sentence is circular. A sentence is defined as a string of words separated by a single space, with no leading or trailing spaces. Words contain only uppercase and lowercase English letters.

LeetCode Problem 2490

Difficulty: 🟢 Easy
Topics: String

Solution

Problem Understanding

The problem asks us to determine whether a given sentence is circular. A sentence is defined as a string of words separated by a single space, with no leading or trailing spaces. Words contain only uppercase and lowercase English letters. The key condition for circularity is that each word's last character must match the first character of the next word, and additionally, the last character of the last word must match the first character of the first word.

The input is a string sentence with length between 1 and 500, and the output is a boolean value: true if the sentence is circular, false otherwise. The constraints ensure there are no empty words or extra spaces, so we do not need to handle trimming or multiple spaces.

Important edge cases include sentences with a single word, where the first and last character must be the same, and sentences where the first or last letters of words differ, breaking the circular property.

Approaches

The brute-force approach is straightforward: split the sentence into words, and for each adjacent pair, check if the last character of the first word equals the first character of the next word. Finally, check if the last character of the last word matches the first character of the first word. This approach works correctly but requires iterating over each word and character, which is simple enough for the given constraints, but can be slightly optimized.

The optimal approach uses the same idea but avoids unnecessary complexity by directly accessing the first and last characters of each word without building extra structures. Since words are split by spaces, Python's split() method suffices, and we can iterate with a simple for loop and direct string indexing. This method is efficient because the number of words is bounded by the string length, and each comparison is O(1).

Approach Time Complexity Space Complexity Notes
Brute Force O(n) O(n) Split sentence and compare adjacent words; works but uses extra space for word list
Optimal O(n) O(1) Compare first and last characters directly during iteration; minimal overhead

Algorithm Walkthrough

  1. Split the sentence into words using the space character. This gives a list of words in order.
  2. Iterate through the list from the first word to the second-to-last word.
  3. For each word at index i, compare its last character with the first character of the next word at index i+1.
  4. If any pair does not match, immediately return false as the sentence is not circular.
  5. After completing the iteration, compare the last character of the last word with the first character of the first word.
  6. If this final comparison fails, return false.
  7. If all checks pass, return true, indicating the sentence is circular.

Why it works: By iterating through all adjacent pairs and ensuring the first-last character property holds, and checking the wrap-around from the last word to the first, we ensure the invariant that every consecutive word transition satisfies circularity. This guarantees correctness.

Python Solution

class Solution:
    def isCircularSentence(self, sentence: str) -> bool:
        words = sentence.split()
        for i in range(len(words) - 1):
            if words[i][-1] != words[i + 1][0]:
                return False
        return words[-1][-1] == words[0][0]

The Python solution first splits the sentence into a list of words. It then iterates over the list, comparing the last character of the current word with the first character of the next. If any comparison fails, it returns False immediately. After checking all pairs, it verifies the circular condition between the last and first word, returning True if it passes.

Go Solution

func isCircularSentence(sentence string) bool {
    words := strings.Fields(sentence)
    for i := 0; i < len(words)-1; i++ {
        if words[i][len(words[i])-1] != words[i+1][0] {
            return false
        }
    }
    lastWord := words[len(words)-1]
    firstWord := words[0]
    return lastWord[len(lastWord)-1] == firstWord[0]
}

In Go, the sentence is split into words using strings.Fields, which handles single-space separation. We iterate through each adjacent word, comparing the last and first characters using indexing. The wrap-around check is performed similarly, ensuring the circular condition holds. Unlike Python, Go uses zero-based indexing and len() for string lengths, but the logic remains the same.

Worked Examples

Example 1: "leetcode exercises sound delightful"

Step Current Word Next Word Comparison Result
1 leetcode exercises 'e' == 'e' True
2 exercises sound 's' == 's' True
3 sound delightful 'd' == 'd' True
Final delightful leetcode 'l' == 'l' True

Output: True

Example 2: "eetcode"

Step Current Word Comparison Result
Single word eetcode 'e' == 'e' True

Output: True

Example 3: "Leetcode is cool"

Step Current Word Next Word Comparison Result
1 Leetcode is 'e' == 'i' False

Output: False

Complexity Analysis

Measure Complexity Explanation
Time O(n) We iterate through each character in the sentence once for splitting and comparisons.
Space O(n) Splitting the sentence creates a list of words proportional to input size.

The time complexity is linear because each character is processed at most twice. The space complexity is linear due to storing the words list.

Test Cases

# Provided examples
assert Solution().isCircularSentence("leetcode exercises sound delightful") == True  # standard circular
assert Solution().isCircularSentence("eetcode") == True  # single word circular
assert Solution().isCircularSentence("Leetcode is cool") == False  # non-circular

# Additional cases
assert Solution().isCircularSentence("a a") == True  # two same letters
assert Solution().isCircularSentence("a b") == False  # two different letters
assert Solution().isCircularSentence("abc cba abc") == True  # multiple words circular
assert Solution().isCircularSentence("abc cba ab") == False  # multiple words not circular
assert Solution().isCircularSentence("x") == True  # single character word
assert Solution().isCircularSentence("A a") == False  # case-sensitive mismatch
Test Why
"leetcode exercises sound delightful" Checks multiple words circular condition
"eetcode" Single word circular
"Leetcode is cool" Fails first pair comparison
"a a" Two words with same letters circular
"a b" Two words different letters not circular
"abc cba abc" Multiple words circular sequence
"abc cba ab" Multiple words fails circular
"x" Single-character word
"A a" Case-sensitive check

Edge Cases

One important edge case is a single-word sentence, where circularity depends solely on the first and last character being the same. This is handled by the final comparison in the solution.

A second edge case is case sensitivity, where 'A' and 'a' are considered different. The solution correctly respects this by using direct character comparison.

A third edge case is two-word sentences. A naive implementation might forget to check the wrap-around condition, but this solution handles it naturally with the loop and final comparison.