Talentd
FleetCode
Make and follow sheets.Sign in

Find And Replace in String solution and explanation

MediumArrayHash TableSortingString6 min read50.9% acceptanceUpdated 9 Apr 2026
Google Coding Interview Question | Leetcode 833 | Find And Replace in StringWorkWithGoogler · 22:49 · 4K viewsWatch on YouTube
5 more videos on this problem
  1. Google Coding Interview Question | Leetcode 833 | Find And Replace in StringWorkWithGoogler · 22:49 · 4K views
  2. LeetCode 833. Find And Replace in String Explanation and Solutionhappygirlzt · 5:10 · 4K views
  3. Leetcode | 833. Find and Replace in String | PythonParth Mathuria · 15:21 · 1K views
  4. Leetcode 833. Find And Replace in String - pythonbbbb · 11:06 · 178 views
  5. No Sound Leetcode 833: Find And Replace in StringExtremeProgrammer · 1:54 · 65 views
  6. LeetCode 833: Find And Replace in StringAlitaCode · 26:02 · 9 views

The problem

You are given a 0-indexed string s that you must perform k replacement operations on. The replacement operations are given as three 0-indexed parallel arrays, indices, sources, and targets, all of length k.

To complete the ith replacement operation:

  1. Check if the substring sources[i] occurs at index indices[i] in the original string s.
  2. If it does not occur, do nothing.
  3. Otherwise if it does occur, replace that substring with targets[i].

For example, if s = "abcd", indices[i] = 0, sources[i] = "ab", and targets[i] = "eee", then the result of this replacement will be "eeecd".

All replacement operations must occur simultaneously, meaning the replacement operations should not affect the indexing of each other. The testcases will be generated such that the replacements will not overlap.

  • For example, a testcase with s = "abc", indices = [0, 1], and sources = ["ab","bc"] will not be generated because the "ab" and "bc" replacements overlap.

Return the resulting string after performing all replacement operations on s.

A substring is a contiguous sequence of characters in a string.

Example 1:

Input: s = "abcd", indices = [0, 2], sources = ["a", "cd"], targets = ["eee", "ffff"]
Output: "eeebffff"
Explanation:
"a" occurs at index 0 in s, so we replace it with "eee".
"cd" occurs at index 2 in s, so we replace it with "ffff".

Example 2:

Input: s = "abcd", indices = [0, 2], sources = ["ab","ec"], targets = ["eee","ffff"]
Output: "eeecd"
Explanation:
"ab" occurs at index 0 in s, so we replace it with "eee".
"ec" does not occur at index 2 in s, so we do nothing.

Constraints:

  • 1 <= s.length <= 1000
  • k == indices.length == sources.length == targets.length
  • 1 <= k <= 100
  • 0 <= indexes[i] < s.length
  • 1 <= sources[i].length, targets[i].length <= 50
  • s consists of only lowercase English letters.
  • sources[i] and targets[i] consist of only lowercase English letters.

Approach overview

Problem Overview: You receive a base string s and three arrays: indices, sources, and targets. For each index i, replace the substring starting at indices[i] with targets[i] only if the substring exactly matches sources[i]. All replacements must behave as if they occur simultaneously.

Approach 1: Simultaneous Replacement using Sorting (O(n + k log k) time, O(n) space)

This approach sorts replacement operations by their starting index so you can scan the string from left to right while applying valid replacements. Pair each index with its corresponding source and target, then sort the pairs by index. While iterating through s, check whether the current position matches the next replacement index. If the substring s[index:index+len(source)] equals the source, append the target to the result and skip ahead by the source length. Otherwise, copy the current character and continue. Sorting ensures replacements are processed in order, preventing conflicts and maintaining the “simultaneous” requirement. This technique mainly uses sequential traversal of the string combined with ordered processing through sorting. Time complexity is O(n + k log k) where k is the number of replacements, and space complexity is O(n) for the result builder.

Approach 2: Direct Index Mapping (O(n) time, O(n) space)

A faster strategy builds a direct lookup structure mapping each replacement index to its operation. Create a dictionary or array where map[index] stores the corresponding source and target. Then iterate through the string once. At each position i, check if a replacement begins there using a constant-time hash lookup. If present, verify that the substring matches the source; if it does, append the target and jump forward by the source length. Otherwise append the current character and move forward by one. This eliminates the sorting step and relies on efficient hash table lookups and linear traversal of the array of indices. The algorithm runs in O(n) time with O(n) additional space for the result and mapping.

Recommended for interviews: The direct index mapping approach is typically expected because it achieves linear time with a clean single pass. The sorting approach still demonstrates solid reasoning about ordered operations and is easier to derive during an interview. Showing both communicates strong understanding: sorting proves you can structure the operations correctly, while index mapping shows optimization using hash-based lookup.

Approach 1: Approach 1: Simultaneous Replacement using Sorting

Sort replacement operations based on indices to ensure they are handled in the correct order. This method involves performing a right-to-left replacement such that indices remain unaffected.

def findReplaceString(s: str, indices: List[int], sources: List[str], targets: List[str]) -> str:
    replacements = sorted(zip(indices, sources, targets), reverse=True)
    for i, source, target in replacements:
        if s[i:i + len(source)] == source:
            s = s[:i] + target + s[i + len(source):]
    return s
import java.util.*;

class Pair {
    int index, pos;
    Pair(int index, int pos) {
        this.index = index;
        this.pos = pos;
    }
}

public class Solution {
    public String findReplaceString(String s, int[] indices, String[] sources, String[] targets) {
        int n = indices.length;
        List<Pair> sortedIndices = new ArrayList<>();
        for (int i = 0; i < n; ++i) {
            sortedIndices.add(new Pair(indices[i], i));
        }

        sortedIndices.sort((a, b) -> b.index - a.index);
        StringBuilder result = new StringBuilder(s);

        for (Pair pair : sortedIndices) {
            int i = pair.index;
            int iglobal = pair.pos;
            if (s.startsWith(sources[iglobal], i)) {
                result.replace(i, i + sources[iglobal].length(), targets[iglobal]);
            }
        }
        return result.toString();
    }
}
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

using namespace std;

string findReplaceString(string s, vector<int>& indices, vector<string>& sources, vector<string>& targets) {
    vector<pair<int, int>> sorted_indices;
    int n = indices.size();
    for (int i = 0; i < n; ++i) {
        sorted_indices.push_back({indices[i], i});
    }

    sort(sorted_indices.begin(), sorted_indices.end(), greater<>());
    for (auto& pair : sorted_indices) {
        int i = pair.first;
        int idx = pair.second;
        if (s.substr(i, sources[idx].size()) == sources[idx]) {
            s = s.substr(0, i) + targets[idx] + s.substr(i + sources[idx].size());
        }
    }
    return s;
}
var findReplaceString = function(s, indices, sources, targets) {
    let sortedIndices = [];
    for (let i = 0; i < indices.length; i++) {
        sortedIndices.push([indices[i], i]);
    }
    sortedIndices.sort((a, b) => b[0] - a[0]);

    for (const [index, pos] of sortedIndices) {
        const source = sources[pos];
        const target = targets[pos];
        if (s.substr(index, source.length) === source) {
            s = s.substring(0, index) + target + s.substring(index + source.length);
        }
    }
    return s;
};
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct {
    int index;
    char* source;
    char* target;
} ReplacementInfo;

int compare(const void* a, const void* b) {
    return ((ReplacementInfo*)b)->index - ((ReplacementInfo*)a)->index;
}

char* findReplaceString(char* s, int* indices, int indicesSize, char** sources, char** targets) {
    int s_len = strlen(s);
    char* result = (char*)malloc(sizeof(char) * (s_len + 1));
    strcpy(result, s);

    ReplacementInfo* replacements = (ReplacementInfo*)malloc(sizeof(ReplacementInfo) * indicesSize);
    for (int i = 0; i < indicesSize; ++i) {
        replacements[i].index = indices[i];
        replacements[i].source = sources[i];
        replacements[i].target = targets[i];
    }

    qsort(replacements, indicesSize, sizeof(ReplacementInfo), compare);

    for (int i = 0; i < indicesSize; ++i) {
        int index = replacements[i].index;
        char* source = replacements[i].source;
        char* target = replacements[i].target;
        if (strncmp(&s[index], source, strlen(source)) == 0) {
            // Perform replacement
            char* temp = (char*)malloc(strlen(result) + strlen(target) - strlen(source) + 1);
            strncpy(temp, result, index);
            temp[index] = '\0';
            strcat(temp, target);
            strcat(temp, &result[index + strlen(source)]);
            free(result);
            result = temp;
        }
    }
    free(replacements);
    return result;
}
using System;
using System.Collections.Generic;

public class Solution {
    public string FindReplaceString(string s, int[] indices, string[] sources, string[] targets) {
        List<(int Index, int Pos)> sortedIndices = new List<(int, int)>();
        for (int i = 0; i < indices.Length; ++i) {
            sortedIndices.Add((indices[i], i));
        }
        sortedIndices.Sort((a, b) => b.Index.CompareTo(a.Index));

        foreach (var (i, pos) in sortedIndices) {
            if (s.Substring(i, sources[pos].Length) == sources[pos]) {
                s = s.Substring(0, i) + targets[pos] + s.Substring(i + sources[pos].Length);
            }
        }

        return s;
    }
}

The Python solution employs a straightforward but effective strategy of sorting the replacements in descending order. This is done using sorted() with zip(), ensuring operations from right to left on string s.

Complexity

Time Complexity: O(n + k log k) where sorting is the most expensive operation.
Space Complexity: O(1) assuming sorting space is negligible.

Try this approach in the editor

Approach 2: Approach 2: Direct Index Mapping

Utilize an array to directly map changes to their respective indices. This way, valid operations can be done directly on the array without affecting others.

def findReplaceString(s: str, indices: List[int], sources: List[str], targets: List[str]) -> str:
    result = list(s)
    for index, source, target in zip(indices, sources, targets):
        if s.startswith(source, index):
            result[index:index+len(source)] = list(target)
    return ''.join(result)
import java.util.*;

public class Solution {
    public String findReplaceString(String s, int[] indices, String[] sources, String[] targets) {
        char[] result = s.toCharArray();
        for (int i = 0; i < indices.length; i++) {
            int index = indices[i];
            String source = sources[i];
            String target = targets[i];
            if (s.startsWith(source, index)) {
                int len = source.length();
                for (int j = 0; j < len; j++) result[index + j] = ' ';
                System.arraycopy(target.toCharArray(), 0, result, index, target.length());
            }
        }
        return new String(result).replaceAll(" ", "");
    }
}
var findReplaceString = function(s, indices, sources, targets) {
    let result = Array.from(s);
    for (let i = 0; i < indices.length; i++) {
        let index = indices[i];
        let source = sources[i];
        let target = targets[i];
        if (s.startsWith(source, index)) {
            result.splice(index, source.length, ...target);
        }
    }
    return result.join('');
};

Utilizing a list to represent the string avoids mutability issues. Each valid replacement modifies the list directly, keeping replacements straightforward and simultaneous.

Complexity

Time Complexity: O(n*k) worst case as each replacement traverses through the string length.
Space Complexity: O(n), determined by the additional list copy of the input string.

Try this approach in the editor

Approach 3: Simulation

We iterate through each replacement operation. For the current k-th replacement operation (i, src), if s[i..i+|src|-1] is equal to src, we record that the string at index i needs to be replaced with the k-th string in targets; otherwise, no replacement is needed.

Next, we only need to iterate through the original string s and perform the replacements based on the recorded information.

The time complexity is O(L), and the space complexity is O(n), where L is the sum of the lengths of all strings, and n is the length of the string s.

function findReplaceString(
    s: string,
    indices: number[],
    sources: string[],
    targets: string[],
): string {
    const n = s.length;
    const d: number[] = Array(n).fill(-1);
    for (let k = 0; k < indices.length; ++k) {
        const [i, src] = [indices[k], sources[k]];
        if (s.startsWith(src, i)) {
            d[i] = k;
        }
    }
    const ans: string[] = [];
    for (let i = 0; i < n; ) {
        if (d[i] >= 0) {
            ans.push(targets[d[i]]);
            i += sources[d[i]].length;
        } else {
            ans.push(s[i++]);
        }
    }
    return ans.join('');
}
func findReplaceString(s string, indices []int, sources []string, targets []string) string {
	n := len(s)
	d := make([]int, n)
	for k, i := range indices {
		if strings.HasPrefix(s[i:], sources[k]) {
			d[i] = k + 1
		}
	}
	ans := &strings.Builder{}
	for i := 0; i < n; {
		if d[i] > 0 {
			ans.WriteString(targets[d[i]-1])
			i += len(sources[d[i]-1])
		} else {
			ans.WriteByte(s[i])
			i++
		}
	}
	return ans.String()
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Approach 1: Simultaneous Replacement using Sorting

Time Complexity: O(n + k log k) where sorting is the most expensive operation.
Space Complexity: O(1) assuming sorting space is negligible.

Approach 2: Direct Index Mapping

Time Complexity: O(n*k) worst case as each replacement traverses through the string length.
Space Complexity: O(n), determined by the additional list copy of the input string.

Simulation–

Complexity analysis

ApproachTimeSpaceWhen to Use
Simultaneous Replacement using SortingO(n + k log k)O(n)When operations must be processed in order and you want a straightforward implementation.
Direct Index MappingO(n)O(n)Best general solution; avoids sorting and performs replacements in a single pass.

Frequently asked questions

Is Find And Replace in String easy or hard?

Find And Replace in String is considered a medium-level problem. The main challenge is handling replacements simultaneously while maintaining correct indices and avoiding overlapping or incorrect substitutions.

Find And Replace in String Python/Java solution

Python solutions often use a dictionary mapping indices to (source, target) pairs and build the result using a list for efficient concatenation. Java implementations typically use a HashMap with a StringBuilder to construct the final string while iterating through the input.

How to solve Find And Replace in String in O(n)?

Create a hash map that maps each replacement index to its source and target strings. Traverse the original string from left to right. When the current index exists in the map and the source substring matches, append the target and jump ahead by the source length; otherwise append the current character.

What is the best approach for Find And Replace in String?

The direct index mapping approach is typically the best. It stores each replacement operation in a hash map keyed by its starting index, allowing a single pass through the string. Each position performs a constant-time lookup to check for replacements, producing an overall O(n) time complexity.

Is Find And Replace in String asked at Google/Amazon/Meta?

Problems involving simultaneous replacements and indexed string operations appear in interviews at companies like Google, Amazon, and Meta. They test string manipulation, careful indexing, and the ability to design efficient single-pass algorithms.

What data structure is used in Find And Replace in String?

Common solutions use arrays for the indices and a hash table (dictionary) to map indices to replacement operations. The algorithm also relies on sequential string traversal and sometimes sorting to process replacements in order.

What is the time complexity of Find And Replace in String?

The optimal solution runs in O(n) time using an index-to-replacement mapping and a single traversal of the string. A common alternative sorts the replacement operations first, leading to O(n + k log k) time where k is the number of replacements.

Comments

Now write it yourselfClose this page and solve Find And Replace in String in the editor, without looking.
Practise Find And Replace in String