Facebook Pixel

3794. Reverse String Prefix

EasyTwo PointersString
LeetCode ↗

Problem Description

You are given a string s and an integer k.

Your task is to reverse the first k characters of s and return the resulting string. The characters from index k onward should remain in their original order.

In other words, take the substring made up of the first k characters of s, reverse it, and then attach the rest of the string (from index k to the end) unchanged.

Example:

If s = "abcdefg" and k = 3:

  • The first k = 3 characters are "abc".
  • Reversing them gives "cba".
  • The remaining characters "defg" stay the same.
  • The result is "cba" + "defg" = "cbadefg".
Quick Interview Experience
Help others by sharing your interview experience
Have you seen this problem before?

How We Pick the Algorithm

Why Two pointers?

This problem maps to Two pointers through a short path in the full flowchart.

Two-pointerscan fromends?yesO(1)memoryconstraint?yesTwo pointers

Reversing the first k characters of a string in place uses two pointers swapping characters from the ends of the prefix.

Open in Flowchart

Intuition

The key observation is that the problem can be naturally split into two independent parts: the portion that needs to be reversed and the portion that stays untouched.

We can think of the string s as being divided at index k:

  • The first part is s[:k], which contains the first k characters that we need to reverse.
  • The second part is s[k:], which contains all the remaining characters that should stay in their original order.

Once we see this split, the solution becomes straightforward. We only need to reverse the first part using slicing s[:k][::-1], and then concatenate it with the second part s[k:]. This directly follows the description of the problem, simulating exactly what is being asked.

A nice detail is that Python slicing handles edge cases gracefully. If k is larger than the length of s, then s[:k] simply returns the entire string and s[k:] returns an empty string, so the code still works correctly without any special handling.

Pattern Learn more about Two Pointers patterns.

Solution Approach

Solution 1: Simulation

We reverse the first k characters of the string according to the problem description, and then concatenate them with the remaining characters.

The implementation follows directly from the split idea discussed earlier:

  1. Extract and reverse the prefix: We use slicing s[:k] to grab the first k characters, and then apply [::-1] to reverse this substring. The expression s[:k][::-1] produces the reversed prefix in a single, concise step.

  2. Extract the remaining part: We use s[k:] to obtain all characters starting from index k to the end of the string. These characters keep their original order.

  3. Concatenate the two parts: Finally, we join the reversed prefix with the unchanged suffix using the + operator, giving us the final result s[:k][::-1] + s[k:].

This approach relies on Python's built-in string slicing, which makes both the reversal and the splitting operations very clean. No extra data structures are needed beyond the temporary substrings created during slicing.

In terms of complexity, the time complexity is O(n), where n is the length of the string s, since slicing and concatenation each process the characters once. The space complexity is also O(n), because we build a new string of the same length as the original.

Example Walkthrough

Let's trace through a small example to see how the Simulation approach works step by step.

Suppose we are given:

  • s = "hello"
  • k = 2

Step 1: Extract and reverse the prefix

We first grab the first k = 2 characters using slicing:

  • s[:2]"he"

Then we reverse this substring using [::-1]:

  • "he"[::-1]"eh"

So the reversed prefix is "eh".

Step 2: Extract the remaining part

Next, we take everything from index k = 2 onward, which should stay unchanged:

  • s[2:]"llo"

This suffix keeps its original order.

Step 3: Concatenate the two parts

Finally, we join the reversed prefix with the unchanged suffix using +:

  • "eh" + "llo""ehllo"

Result: "ehllo"

To confirm the edge-case behavior mentioned in the intuition, imagine instead that k = 10 (larger than the length of s):

  • s[:10]"hello" (the entire string)
  • "hello"[::-1]"olleh"
  • s[10:]"" (empty string)
  • "olleh" + """olleh"

The whole string is simply reversed, and no special handling is required—Python's slicing manages the out-of-range index gracefully.

Solution Implementation

1class Solution:
2    def reversePrefix(self, s: str, k: int) -> str:
3        # Reverse the first k characters of the string, then append the rest unchanged.
4        # s[:k]      -> take the prefix of length k
5        # [::-1]     -> reverse that prefix
6        # s[k:]      -> take the remaining suffix as is
7        return s[:k][::-1] + s[k:]
8```
9
10A couple of notes on this solution:
11
121. **Naming**: The parameters `s` (the input string) and `k` (the number of leading characters to reverse) are already concise and conventional for this kind of problem, so they remain unchanged. The method name `reversePrefix` is preserved as required.
13
142. **Behavior with edge cases**: Python slicing is forgiving here. If `k` exceeds `len(s)`, `s[:k]` simply returns the whole string and `s[k:]` returns an empty string, so the code won't raise an error.
15
16If you prefer a version closer to the typical LeetCode framing of this task (where you reverse from the start up to the first occurrence of a target character), here is an alternative perspective:
17
18```python3
19class Solution:
20    def reversePrefix(self, word: str, ch: str) -> str:
21        # Find the first index of the target character.
22        idx = word.find(ch)
23        # If not found, return the word unchanged.
24        if idx == -1:
25            return word
26        # Reverse the segment up to and including idx, then append the rest.
27        return word[:idx + 1][::-1] + word[idx + 1:]
28
1class Solution {
2    /**
3     * Reverses the first {@code k} characters of the input string
4     * and appends the remaining unchanged suffix.
5     *
6     * @param input    the original string to process
7     * @param prefixLen the number of leading characters to reverse
8     * @return a new string with its prefix reversed
9     */
10    public String reversePrefix(String input, int prefixLen) {
11        // Extract the prefix [0, prefixLen) and build it into a mutable buffer
12        StringBuilder prefixBuilder = new StringBuilder(input.substring(0, prefixLen));
13
14        // Reverse the prefix in place
15        String reversedPrefix = prefixBuilder.reverse().toString();
16
17        // Concatenate the reversed prefix with the untouched suffix [prefixLen, end)
18        return reversedPrefix + input.substring(prefixLen);
19    }
20}
21
1class Solution {
2public:
3    string reversePrefix(string s, int k) {
4        // Extract the prefix consisting of the first k characters
5        string prefix = s.substr(0, k);
6
7        // Reverse the extracted prefix in place
8        reverse(prefix.begin(), prefix.end());
9
10        // Concatenate the reversed prefix with the remaining part of the string
11        return prefix + s.substr(k);
12    }
13};
14
1/**
2 * Reverses the first k characters of the string and appends the remaining characters unchanged.
3 *
4 * @param s - The input string to process.
5 * @param k - The number of leading characters to reverse.
6 * @returns A new string with its first k characters reversed.
7 */
8function reversePrefix(s: string, k: number): string {
9    // Extract the prefix of length k, reverse it, and rebuild it into a string.
10    const reversedPrefix: string = s.slice(0, k).split('').reverse().join('');
11
12    // Extract the remaining portion of the string starting from index k.
13    const remainingSuffix: string = s.slice(k);
14
15    // Concatenate the reversed prefix with the unchanged suffix.
16    return reversedPrefix + remainingSuffix;
17}
18

Time and Space Complexity

  • Time Complexity: O(n), where n is the length of the string s.

    • s[:k] creates a substring containing the first k characters, which takes O(k) time.
    • [::-1] reverses that substring, taking O(k) time.
    • s[k:] creates a substring of the remaining n - k characters, taking O(n - k) time.
    • The concatenation + combines the two parts, taking O(n) time.
    • Summing these operations gives O(k) + O(k) + O(n - k) + O(n) = O(n).
  • Space Complexity: O(n), where n is the length of the string s.

    • The sliced substrings s[:k], the reversed result, and s[k:] collectively require O(n) extra space.
    • The final concatenated string also occupies O(n) space.
    • Therefore, the overall space complexity is O(n).

Pattern Learn more about how to find time and space complexity quickly.

Common Pitfalls

Pitfall: Off-by-One When Reversing "Up To" a Character

The most frequent mistake comes from confusing the two framings of this problem. In the index-based version, k tells you how many characters to reverse, so you slice s[:k]. But in the character-based version (the actual LeetCode 2000 variant), you reverse the segment up to and including the first occurrence of a target character ch.

A very common bug is writing word[:idx] instead of word[:idx + 1]:

# WRONG: this excludes the target character from the reversal
idx = word.find(ch)
return word[:idx][::-1] + word[idx:]

For word = "abcdefd" and ch = "d", idx = 3. The correct answer reverses "abcd" to get "dcba" + "efd" = "dcbaefd". The buggy version reverses only "abc" and produces "cbadefd", silently giving the wrong result.

Solution: Always include the + 1 so the target character is part of the reversed prefix:

return word[:idx + 1][::-1] + word[idx + 1:]

Pitfall: Forgetting the "Character Not Found" Case

When using str.find, if ch does not exist in word, find returns -1. Plugging -1 directly into slicing leads to a subtle, hard-to-spot bug rather than a crash:

idx = word.find(ch)            # idx == -1 when not found
return word[:idx + 1][::-1] + word[idx + 1:]

Here idx + 1 becomes 0, so word[:0][::-1] is "" and word[0:] is the whole word — which happens to return the word unchanged by luck. However, relying on this accidental behavior is fragile, and if you ever wrote word[:idx] (without the +1), word[:-1] would chop off the last character incorrectly.

Solution: Handle the not-found case explicitly so the intent is clear and the code stays robust:

idx = word.find(ch)
if idx == -1:
    return word
return word[:idx + 1][::-1] + word[idx + 1:]

Pitfall: Assuming Negative k Behaves Like the Positive Case

For the index-based version, the code assumes k is non-negative. A negative k silently produces incorrect output because Python interprets it as an index from the end:

s = "abcdefg"
k = -2
# s[:-2] -> "abcde", s[-2:] -> "fg"
# result -> "edcbafg"  (not what "reverse first k" implies)

Solution: If negative or out-of-range input is possible in your context, clamp k before slicing:

k = max(0, min(k, len(s)))
return s[:k][::-1] + s[k:]

Pitfall: Trying to Reverse In-Place on a Python str

Coming from languages like C++ or Java, you might attempt to swap characters in place:

s[0], s[k-1] = s[k-1], s[0]   # TypeError: 'str' object does not support item assignment

Python strings are immutable, so this raises a TypeError.

Solution: Either use slicing as shown in the main solution, or convert to a list first if you truly need a two-pointer swap approach:

chars = list(s)
left, right = 0, k - 1
while left < right:
    chars[left], chars[right] = chars[right], chars[left]
    left, right = left + 1, right - 1
return "".join(chars)

This still runs in O(n) time and O(n) space, but makes the in-place mutation explicit and avoids the immutability trap.

Ready to land your dream job?

Unlock your dream job with a 5-minute quiz for a personalized study roadmap!

Get My Roadmap
Discover Your Strengths and Weaknesses: Take Our 5-Minute Quiz to Get a Personalized Study Roadmap:

Which of the following uses divide and conquer strategy?


Recommended Readings

Want a Structured Path to Master System Design Too? Don’t Miss This!

Load More