First Unique Char Index
Less than 1 minuteTC-Medium
First Unique Char Index
Problem
Given a string S, find the first non-repeating character in it and return its index. If it does not exist, return -1.
type A = FirstUniqueCharIndex<'leetcode'> // 0
type B = FirstUniqueCharIndex<'loveleetcode'> // 2
type C = FirstUniqueCharIndex<'aabb'> // -1Solution
Approach: Check if Current Char Appears in Remaining String
For each position, check whether the character appears anywhere else in the string.
type StringIncludes<S extends string, C extends string> =
S extends `${string}${C}${string}` ? true : false
type FirstUniqueCharIndex<
S extends string,
Original extends string = S,
Count extends unknown[] = []
> = S extends `${infer C}${infer Rest}`
? StringIncludes<Rest, C> extends true
? FirstUniqueCharIndex<Rest, Original, [...Count, unknown]>
: StringIncludes<Original extends `${infer Before}${C}${string}` ? Before : never, C> extends true
? FirstUniqueCharIndex<Rest, Original, [...Count, unknown]>
: Count['length']
: -1A simpler approach using Split:
type FirstUniqueCharIndex<
S extends string,
Prefix extends string = '',
Count extends unknown[] = []
> = S extends `${infer C}${infer Rest}`
? `${Prefix}${Rest}` extends `${string}${C}${string}`
? FirstUniqueCharIndex<Rest, `${Prefix}${C}`, [...Count, unknown]>
: Count['length']
: -1How it works:
- Track
Prefix— all characters before the current position. - For character
Cat the current position, check ifCappears inPrefix + Rest. - If not found elsewhere,
Count['length']is the answer. - Otherwise, move
CintoPrefixand continue.
Key Takeaways
- Maintaining a
Prefixaccumulator lets us check both "before" and "after" with a singleincludescheck. ${string}${C}${string}is the template literal pattern for "contains C".- Index tracking via tuple length is the standard approach for positional problems.
