Talentd
FleetCode
Make and follow sheets.Sign in

Find Beautiful Indices in the Given Array I solution and explanation

MediumBinary SearchHash FunctionRolling HashString5 min read41.2% acceptanceUpdated 9 Apr 2026
3006. Find Beautiful Indices in the Given Array I (Leetcode Medium)Programming Live with Larry · 8:33 · 1K viewsWatch on YouTube
9 more videos on this problem
  1. 3006. Find Beautiful Indices in the Given Array I (Leetcode Medium)Programming Live with Larry · 8:33 · 1K views
  2. LeetCode Weekly 380 - 3006 Find Beautiful Indices in the Given Array I - MediumLearn with EmKay · 13:00 · 779 views
  3. Leetcode 3006: Find Beautiful Indices in the Given Array I | Weekly ContestAlgorithms Casts · 17:48 · 774 views
  4. 3006. Find Beautiful Indices in the Given Array I | LEETCODE WEEKLY 380 | STRINGScode Explainer · 5:48 · 547 views
  5. Find Beautiful Indices In The Given Array IOwen Wu · 8:58 · 299 views
  6. 100165 Find Beautiful Indices in the Given Array I || leetcode || contest379 || solved || javaSsquare · 1:08 · 221 views
  7. Leetcode 3006 || Find Beautiful Indices in the Given Array I || Weekly Contest || MediumKomal Pal · 7:57 · 136 views
  8. 3006. Find Beautiful Indices in the Given Array I and II | Leetcode Weekly Contest 380Ashish Kumar · 33:44 · 77 views
  9. Find Beautiful Indices in the Given Array | Part I & II | KMP Algorithm | String Matching AlgorithmAryan Mittal · 1:01:58 · 21K views
  10. Find Beautiful Indices in the Given Array | Part I | Part II | Same Code | KMP | Weekly Contest 380codestorywithMIK · 28:08 · 6K views

The problem

You are given a 0-indexed string s, a string a, a string b, and an integer k.

An index i is beautiful if:

  • 0 <= i <= s.length - a.length
  • s[i..(i + a.length - 1)] == a
  • There exists an index j such that:
    • 0 <= j <= s.length - b.length
    • s[j..(j + b.length - 1)] == b
    • |j - i| <= k

Return the array that contains beautiful indices in sorted order from smallest to largest.

Example 1:

Input: s = "isawsquirrelnearmysquirrelhouseohmy", a = "my", b = "squirrel", k = 15
Output: [16,33]
Explanation: There are 2 beautiful indices: [16,33].
- The index 16 is beautiful as s[16..17] == "my" and there exists an index 4 with s[4..11] == "squirrel" and |16 - 4| <= 15.
- The index 33 is beautiful as s[33..34] == "my" and there exists an index 18 with s[18..25] == "squirrel" and |33 - 18| <= 15.
Thus we return [16,33] as the result.

Example 2:

Input: s = "abcd", a = "a", b = "a", k = 4
Output: [0]
Explanation: There is 1 beautiful index: [0].
- The index 0 is beautiful as s[0..0] == "a" and there exists an index 0 with s[0..0] == "a" and |0 - 0| <= 4.
Thus we return [0] as the result.

Constraints:

  • 1 <= k <= s.length <= 105
  • 1 <= a.length, b.length <= 10
  • s, a, and b contain only lowercase English letters.

Approach overview

Problem Overview: You are given a string s and two substrings a and b. An index i is considered beautiful if substring a starts at i and there exists another index j where substring b starts such that |i - j| ≤ k. The task is to return all beautiful indices in sorted order.

Approach 1: Brute Force String Matching (O(n * m + p * q), Space O(n))

Scan the string and record every index where substring a appears and every index where substring b appears. This uses direct substring comparison while iterating through s. After collecting both index lists, check every a index against every b index and verify whether |i - j| ≤ k. If the condition holds for any j, mark i as beautiful. The method is simple and demonstrates understanding of string matching, but the nested comparison becomes expensive when both lists are large.

Approach 2: Hash Map + Binary Search on Indices (O(n log n), Space O(n))

First iterate through the string once and store all starting indices of substring a and b. The indices where b occurs are kept in a sorted list. For each index i where a appears, perform a binary search on the b index list to locate the closest position to i. Then check whether the nearest index satisfies |i - j| ≤ k. Binary search reduces the comparison from scanning the entire list to O(log n) per check. This pattern is common in problems combining binary search with preprocessed index lists.

The key idea is separating discovery and validation. First find all pattern occurrences using straightforward substring checks (or faster techniques like rolling hash if needed). Then efficiently verify distance constraints using sorted indices. This reduces redundant comparisons and keeps the algorithm scalable even when the string length grows.

Recommended for interviews: The binary search approach is the expected solution. Interviewers want to see that you preprocess substring occurrences and avoid quadratic comparisons. Starting with the brute force method shows understanding of the problem, but transitioning to the optimized method demonstrates stronger algorithmic thinking and familiarity with two pointer or search-based optimizations.

Approach 1: Brute Force Approach

This approach involves directly comparing each element with every other element. This method solves the problem by exploring all possible combinations without utilizing any advanced optimization techniques.

arr = [1, 2, 3, 4, 5]
target = 7

for i in range(len(arr) - 1):
    for j in range(i + 1, len(arr)):
        if arr[i] + arr[j] == target:
            print(f"Pair found: ({arr[i]}, {arr[j]})")
public class Main {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        int target = 7;

        for (int i = 0; i < arr.length - 1; i++) {
            for (int j = i + 1; j < arr.length; j++) {
                if (arr[i] + arr[j] == target) {
                    System.out.println("Pair found: (" + arr[i] + ", " + arr[j] + ")");
                }
            }
        }
    }
}
#include <iostream>
using namespace std;

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int n = sizeof(arr)/sizeof(arr[0]);
    int target = 7;

    for (int i = 0; i < n - 1; i++) {
        for (int j = i + 1; j < n; j++) {
            if (arr[i] + arr[j] == target) {
                cout << "Pair found: (" << arr[i] << ", " << arr[j] << ")\n";
            }
        }
    }
    return 0;
}
const arr = [1, 2, 3, 4, 5];
const target = 7;

for (let i = 0; i < arr.length - 1; i++) {
    for (let j = i + 1; j < arr.length; j++) {
        if (arr[i] + arr[j] === target) {
            console.log(`Pair found: (${arr[i]}, ${arr[j]})`);
        }
    }
}
#include <stdio.h>

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int n = sizeof(arr)/sizeof(arr[0]);
    int target = 7;

    for (int i = 0; i < n - 1; i++) {
        for (int j = i + 1; j < n; j++) {
            if (arr[i] + arr[j] == target) {
                printf("Pair found: (%d, %d)\n", arr[i], arr[j]);
            }
        }
    }
    return 0;
}
using System;

public class Program {
    public static void Main() {
        int[] arr = {1, 2, 3, 4, 5};
        int target = 7;

        for (int i = 0; i < arr.Length - 1; i++) {
            for (int j = i + 1; j < arr.Length; j++) {
                if (arr[i] + arr[j] == target) {
                    Console.WriteLine($"Pair found: ({arr[i]}, {arr[j]})");
                }
            }
        }
    }
}

The Python solution uses a similar nested loop structure to find and print out pairs of numbers that sum to the target value.

Complexity

Time Complexity: O(n^2)
Space Complexity: O(1)

Try this approach in the editor

Approach 2: Hash Map Approach

This approach leverages a hash map to store the elements and checks for the complement required to reach the target as it iterates through the array. This significantly reduces the number of checks needed compared to the brute force method.

arr = [1, 2, 3, 4, 5]
target = 7
hash_table = {}

for value in arr:
    complement = target - value
    if complement in hash_table:
        print(f"Pair found: ({complement}, {value})")
    hash_table[value] = True
import java.util.HashMap;

public class Main {
    public static void main(String[] args) {
        int[] arr = {1, 2, 3, 4, 5};
        int target = 7;

        HashMap<Integer, Boolean> hashMap = new HashMap<>();

        for (int value : arr) {
            int complement = target - value;
            if (hashMap.containsKey(complement)) {
                System.out.println("Pair found: (" + complement + ", " + value + ")");
            }
            hashMap.put(value, true);
        }
    }
}
#include <iostream>
#include <unordered_map>
using namespace std;

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int target = 7;

    unordered_map<int, bool> hashTable;

    for (int i = 0; i < sizeof(arr)/sizeof(arr[0]); i++) {
        int complement = target - arr[i];
        if (hashTable.find(complement) != hashTable.end()) {
            cout << "Pair found: (" << complement << ", " << arr[i] << ")\n";
        }
        hashTable[arr[i]] = true;
    }

    return 0;
}
const arr = [1, 2, 3, 4, 5];
const target = 7;
const hashTable = {};

for (const value of arr) {
    const complement = target - value;
    if (hashTable[complement]) {
        console.log(`Pair found: (${complement}, ${value})`);
    }
    hashTable[value] = true;
}
#include <stdio.h>
#include <stdlib.h>

#define TABLE_SIZE 101

typedef struct HashNode {
    int key;
    int value;
    struct HashNode *next;
} HashNode;

int hash(int key) {
    return abs(key) % TABLE_SIZE;
}

void insert(HashNode **table, int value) {
    int index = hash(value);
    HashNode *newNode = (HashNode *)malloc(sizeof(HashNode));
    newNode->key = value;
    newNode->value = value;
    newNode->next = table[index];
    table[index] = newNode;
}

int search(HashNode **table, int value) {
    int index = hash(value);
    HashNode *temp = table[index];
    while (temp != NULL) {
        if (temp->value == value) {
            return 1;
        }
        temp = temp->next;
    }
    return 0;
}

int main() {
    int arr[] = {1, 2, 3, 4, 5};
    int target = 7;
    int n = sizeof(arr) / sizeof(arr[0]);
    HashNode *hashTable[TABLE_SIZE] = {0};

    for (int i = 0; i < n; i++) {
        int complement = target - arr[i];
        if (search(hashTable, complement)) {
            printf("Pair found: (%d, %d)\n", complement, arr[i]);
        }
        insert(hashTable, arr[i]);
    }

    return 0;
}
using System;
using System.Collections.Generic;

class Program {
    public static void Main() {
        int[] arr = { 1, 2, 3, 4, 5 };
        int target = 7;

        Dictionary<int, bool> hashTable = new Dictionary<int, bool>();

        foreach (int value in arr) {
            int complement = target - value;
            if (hashTable.ContainsKey(complement)) {
                Console.WriteLine($"Pair found: ({complement}, {value})");
            }
            hashTable[value] = true;
        }
    }
}

The Python version utilizes a dictionary to store numbers encountered during array traversal, allowing fast checks for the required complement.

Complexity

Time Complexity: O(n)
Space Complexity: O(n)

Try this approach in the editor

Approach 3: Default Approach

func beautifulIndices(s string, a string, b string, k int) []int {

	s_len := len(s)
	a_len := len(a)
	b_len := len(b)

	final := make([]int, 0)
	lps_a := make([]int, a_len)
	lps_b := make([]int, b_len)
	a_index := make([]int, 0)
	b_index := make([]int, 0)

	var pat func(lps []int, s_l int, pattern string)

	pat = func(lps []int, s_l int, pattern string) {

		l := 0
		lps[0] = 0
		i := 1

		for i < s_l {
			if pattern[i] == pattern[l] {
				l++
				lps[i] = l
				i++
			} else {
				if l != 0 {
					l = lps[l-1]
				} else {
					lps[i] = l
					i++
				}
			}
		}
	}

	pat(lps_a, a_len, a)
	pat(lps_b, b_len, b)

	var kmp func(pat string, pat_l int, lps []int, index *[]int)

	kmp = func(pat string, pat_l int, lps []int, index *[]int) {
		i := 0
		j := 0
		for s_len-i >= pat_l-j {
			if s[i] == pat[j] {
				i++
				j++
			}
			if j == pat_l {
				*index = append(*index, i-pat_l)
				j = lps[j-1]
			} else if s[i] != pat[j] {
				if j != 0 {
					j = lps[j-1]
				} else {
					i++
				}
			}
		}
	}

	kmp(a, a_len, lps_a, &a_index)
	kmp(b, b_len, lps_b, &b_index)

	// fmt.Println(a_index, b_index)

	i := 0
	j := 0

	for i < len(a_index) && j < len(b_index) {
		if a_index[i]+k >= b_index[j] && a_index[i]-k <= b_index[j] {
			final = append(final, a_index[i])
			i++
		} else if a_index[i]-k > b_index[j] {
			j++
		} else {
			i++
		}
	}

	return final
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Brute Force Approach

Time Complexity: O(n^2)
Space Complexity: O(1)

Hash Map Approach

Time Complexity: O(n)
Space Complexity: O(n)

Default Approach–

Complexity analysis

ApproachTimeSpaceWhen to Use
Brute Force String MatchingO(n * m + p * q)O(n)Good for understanding the problem or when input size is small
Hash Map + Binary SearchO(n log n)O(n)Best general solution when substring occurrences must be checked within a distance constraint

Frequently asked questions

Is Find Beautiful Indices in the Given Array I easy or hard?

The problem is typically rated Medium because it combines substring matching with an efficient search constraint. The logic is straightforward once you realize that preprocessing the indices and using binary search avoids quadratic comparisons.

How to solve Find Beautiful Indices in the Given Array I in O(n)?

An O(n) style solution can be approximated by scanning the string once to record occurrences of substrings a and b, then using two pointers over the sorted index lists to maintain the distance constraint. This avoids repeated binary searches and keeps checks linear after preprocessing.

Find Beautiful Indices in the Given Array I Python or Java solution

In Python or Java, iterate through the string and collect indices of substring a and b using substring comparison. Store b indices in a list, then use binary search (bisect in Python or Collections.binarySearch in Java) to locate the nearest index within distance k.

What is the best approach for Find Beautiful Indices in the Given Array I?

The most efficient approach stores all indices where substring b appears and then checks each occurrence of substring a using binary search. This allows you to quickly find the closest b index and verify whether the distance is within k. The overall complexity becomes O(n log n) with O(n) extra space.

What data structure is used in Find Beautiful Indices in the Given Array I?

The main structure is a list or array storing all indices where substring b appears. Because the indices are naturally sorted during traversal, binary search can be applied efficiently to find the closest match for each a occurrence.

What is the time complexity of Find Beautiful Indices in the Given Array I?

The brute force method can reach O(n^2) behavior when every occurrence of substring a is compared with every occurrence of substring b. The optimized approach uses binary search on sorted indices of b and runs in O(n log n) time with O(n) space.

Is Find Beautiful Indices in the Given Array I asked at Google, Amazon, or Meta?

Problems involving substring matching with distance constraints are common in interviews at companies like Amazon, Google, and Meta. They test knowledge of string processing, index preprocessing, and efficient searching techniques such as binary search or two pointers.

Comments

Now write it yourselfClose this page and solve Find Beautiful Indices in the Given Array I in the editor, without looking.
Practise Find Beautiful Indices in the Given Array I