Bird
Raised Fist0
Interview Preptwo-pointersmediumAmazonFacebook

Remove Duplicates from Sorted Array II

Choose your preparation mode4 modes available
🎯
Remove Duplicates from Sorted Array II
mediumTWO_POINTERAmazonFacebook

Imagine you have a sorted list of customer IDs, but due to system glitches, some IDs appear more than twice. You want to clean this list so that each ID appears at most twice, preserving order and doing it efficiently.

💡 This problem is about modifying a sorted array in-place to limit duplicates. Beginners often struggle because they try to remove duplicates by shifting elements multiple times or using extra space, missing the efficient two-pointer approach that leverages the sorted property.
📋
Problem Statement

Given a sorted integer array nums, remove duplicates in-place such that each element appears at most twice and return the new length. Do not allocate extra space for another array; you must do this by modifying the input array in-place with O(1) extra memory. The relative order of the elements should be kept the same.

1 ≤ nums.length ≤ 10^5-10^4 ≤ nums[i] ≤ 10^4nums is sorted in non-decreasing order
💡
Example
Input"[1,1,1,2,2,3]"
Output5

After removing extra duplicates, the array becomes [1,1,2,2,3]. The length is 5.

Input"[0,0,1,1,1,1,2,3,3]"
Output7

The array after removal is [0,0,1,1,2,3,3]. The length is 7.

  • Array with all identical elements → length should be 2
  • Array with no duplicates → length equals original length
  • Array with exactly two duplicates per element → length equals original length
  • Array with negative and positive numbers → handled correctly
⚠️
Common Mistakes
Not handling the first two elements separately

Incorrectly removing allowed duplicates or index errors

✅ Add condition to allow first two elements unconditionally

Using pop or splice inside loops causing O(n^2) time

Solution times out on large inputs

✅ Use two pointers to overwrite elements instead of removing

Not resetting count when element changes

Count accumulates incorrectly, allowing too many duplicates

✅ Reset count to 1 when current element differs from previous

Modifying array while iterating forward without adjusting indices

Skipping elements or index out of range errors

✅ Use separate read and write pointers to avoid conflicts

🧠
Brute Force (Nested Loops with Shifting)
💡 This approach exists to show the naive way of solving the problem by explicitly removing extra duplicates via shifting elements. It helps beginners understand the problem constraints and why this method is inefficient.

Intuition

Scan the array from left to right, and whenever you find an element that appears more than twice consecutively, remove the extra occurrences by shifting the rest of the array left.

Algorithm

  1. Initialize index i to 0.
  2. While i is less than the length of the array:
  3. Count how many times nums[i] repeats consecutively.
  4. If count > 2, remove extra duplicates by shifting elements left.
  5. Increment i to the next distinct element.
  6. Return the new length after all removals.
💡 The nested loops and shifting make it hard to track indices and understand performance, but it directly implements the problem statement.
</>
Code
def remove_duplicates(nums):
    i = 0
    while i < len(nums):
        count = 1
        while i + count < len(nums) and nums[i + count] == nums[i]:
            count += 1
        if count > 2:
            for _ in range(count - 2):
                nums.pop(i + 2)
        i += 1
    return len(nums)

# Driver code
if __name__ == '__main__':
    arr = [1,1,1,2,2,3]
    length = remove_duplicates(arr)
    print(length)  # Expected: 5
    print(arr[:length])  # Expected: [1,1,2,2,3]
Line Notes
i = 0Initialize pointer to start scanning from the beginning
while i < len(nums)Loop through the array until the end
count = 1Start counting duplicates for current element
while i + count < len(nums) and nums[i + count] == nums[i]Count how many times current element repeats consecutively
if count > 2Check if duplicates exceed allowed limit
for _ in range(count - 2)Remove extra duplicates by popping elements
nums.pop(i + 2)Remove element at position after allowed duplicates
i += 1Move to next element after processing current duplicates
import java.util.*;
public class Solution {
    public static int removeDuplicates(int[] nums) {
        int i = 0;
        int n = nums.length;
        while (i < n) {
            int count = 1;
            while (i + count < n && nums[i + count] == nums[i]) {
                count++;
            }
            if (count > 2) {
                for (int j = i + 2; j < n - (count - 2); j++) {
                    nums[j] = nums[j + (count - 2)];
                }
                n -= (count - 2);
            }
            i++;
        }
        return n;
    }

    public static void main(String[] args) {
        int[] arr = {1,1,1,2,2,3};
        int length = removeDuplicates(arr);
        System.out.println(length); // Expected: 5
        for (int i = 0; i < length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}
Line Notes
int i = 0Initialize scanning index
while (i < n)Traverse array until end
int count = 1Count duplicates starting at i
while (i + count < n && nums[i + count] == nums[i])Count consecutive duplicates
if (count > 2)Check if duplicates exceed allowed limit
for (int j = i + 2; j < n - (count - 2); j++)Shift elements left to remove extras
nums[j] = nums[j + (count - 2)]Overwrite element to remove duplicates
n -= (count - 2)Update new length after removals
i++Move to next element
#include <iostream>
#include <vector>
using namespace std;

int removeDuplicates(vector<int>& nums) {
    int i = 0;
    int n = nums.size();
    while (i < n) {
        int count = 1;
        while (i + count < n && nums[i + count] == nums[i]) {
            count++;
        }
        if (count > 2) {
            for (int j = i + 2; j < n - (count - 2); j++) {
                nums[j] = nums[j + (count - 2)];
            }
            n -= (count - 2);
        }
        i++;
    }
    return n;
}

int main() {
    vector<int> arr = {1,1,1,2,2,3};
    int length = removeDuplicates(arr);
    cout << length << endl; // Expected: 5
    for (int i = 0; i < length; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
    return 0;
}
Line Notes
int i = 0Start scanning from beginning
while (i < n)Loop through array elements
int count = 1Count duplicates for current element
while (i + count < n && nums[i + count] == nums[i])Count consecutive duplicates
if (count > 2)Check if duplicates exceed allowed limit
for (int j = i + 2; j < n - (count - 2); j++)Shift elements left to remove extras
nums[j] = nums[j + (count - 2)]Overwrite element to remove duplicates
n -= (count - 2)Update length after removals
i++Move to next element
function removeDuplicates(nums) {
    let i = 0;
    while (i < nums.length) {
        let count = 1;
        while (i + count < nums.length && nums[i + count] === nums[i]) {
            count++;
        }
        if (count > 2) {
            for (let j = 0; j < count - 2; j++) {
                nums.splice(i + 2, 1);
            }
        }
        i++;
    }
    return nums.length;
}

// Test
const arr = [1,1,1,2,2,3];
const length = removeDuplicates(arr);
console.log(length); // Expected: 5
console.log(arr.slice(0, length)); // Expected: [1,1,2,2,3]
Line Notes
let i = 0Initialize pointer to start scanning
while (i < nums.length)Traverse array until end
let count = 1Count duplicates for current element
while (i + count < nums.length && nums[i + count] === nums[i])Count consecutive duplicates
if (count > 2)Check if duplicates exceed allowed limit
for (let j = 0; j < count - 2; j++)Remove extra duplicates by splicing
nums.splice(i + 2, 1)Remove element at position after allowed duplicates
i++Move to next element
⏱
Complexity
TimeO(n^2)
SpaceO(1)

Each removal involves shifting elements left, which can be O(n) per removal, leading to O(n^2) in worst case.

💡 For n=20, this could mean up to 400 operations, which is inefficient for large arrays.
Interview Verdict: TLE / Inefficient for large inputs

This approach is too slow for large inputs but helps understand the problem and why optimization is needed.

🧠
Two Pointers with Count Tracking
💡 This approach introduces the two-pointer technique to efficiently track allowed duplicates while modifying the array in-place, improving performance drastically.

Intuition

Use one pointer to iterate over the array and another to build the result. Keep track of how many times the current number has appeared and only copy it if it appears at most twice.

Algorithm

  1. Initialize two pointers: write_index at 0 and read_index at 0.
  2. Initialize count to 1 for the first element.
  3. Iterate read_index through the array starting from 1.
  4. If current element equals previous, increment count; else reset count to 1.
  5. If count ≤ 2, copy current element to write_index and increment write_index.
  6. Return write_index as the new length.
💡 Tracking count and using two pointers avoids shifting and keeps the array modified in-place efficiently.
</>
Code
def remove_duplicates(nums):
    if len(nums) <= 2:
        return len(nums)
    write_index = 1
    count = 1
    for read_index in range(1, len(nums)):
        if nums[read_index] == nums[read_index - 1]:
            count += 1
        else:
            count = 1
        if count <= 2:
            nums[write_index] = nums[read_index]
            write_index += 1
    return write_index

# Driver code
if __name__ == '__main__':
    arr = [1,1,1,2,2,3]
    length = remove_duplicates(arr)
    print(length)  # Expected: 5
    print(arr[:length])  # Expected: [1,1,2,2,3]
Line Notes
if len(nums) <= 2Handle small arrays where no removal is needed
write_index = 1Position to write next allowed element
count = 1Count occurrences of current element
for read_index in range(1, len(nums))Traverse array from second element
if nums[read_index] == nums[read_index - 1]Check if current equals previous to count duplicates
count += 1Increment count for duplicate
else: count = 1Reset count for new element
if count <= 2Allow up to two duplicates
nums[write_index] = nums[read_index]Copy allowed element to write_index
write_index += 1Move write pointer forward
public class Solution {
    public static int removeDuplicates(int[] nums) {
        if (nums.length <= 2) return nums.length;
        int writeIndex = 1, count = 1;
        for (int readIndex = 1; readIndex < nums.length; readIndex++) {
            if (nums[readIndex] == nums[readIndex - 1]) {
                count++;
            } else {
                count = 1;
            }
            if (count <= 2) {
                nums[writeIndex] = nums[readIndex];
                writeIndex++;
            }
        }
        return writeIndex;
    }

    public static void main(String[] args) {
        int[] arr = {1,1,1,2,2,3};
        int length = removeDuplicates(arr);
        System.out.println(length); // Expected: 5
        for (int i = 0; i < length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}
Line Notes
if (nums.length <= 2)Handle trivial cases quickly
int writeIndex = 1, count = 1Initialize write pointer and count
for (int readIndex = 1; readIndex < nums.length; readIndex++)Traverse array from second element
if (nums[readIndex] == nums[readIndex - 1])Check for duplicate
count++Increment duplicate count
else { count = 1; }Reset count for new element
if (count <= 2)Allow up to two duplicates
nums[writeIndex] = nums[readIndex]Overwrite element at writeIndex
writeIndex++Advance write pointer
#include <iostream>
#include <vector>
using namespace std;

int removeDuplicates(vector<int>& nums) {
    if (nums.size() <= 2) return nums.size();
    int writeIndex = 1, count = 1;
    for (int readIndex = 1; readIndex < nums.size(); readIndex++) {
        if (nums[readIndex] == nums[readIndex - 1]) {
            count++;
        } else {
            count = 1;
        }
        if (count <= 2) {
            nums[writeIndex] = nums[readIndex];
            writeIndex++;
        }
    }
    return writeIndex;
}

int main() {
    vector<int> arr = {1,1,1,2,2,3};
    int length = removeDuplicates(arr);
    cout << length << endl; // Expected: 5
    for (int i = 0; i < length; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
    return 0;
}
Line Notes
if (nums.size() <= 2)Quickly return for small arrays
int writeIndex = 1, count = 1Initialize pointers and count
for (int readIndex = 1; readIndex < nums.size(); readIndex++)Traverse array from second element
if (nums[readIndex] == nums[readIndex - 1])Check for duplicate
count++Increment count for duplicate
else { count = 1; }Reset count for new element
if (count <= 2)Allow up to two duplicates
nums[writeIndex] = nums[readIndex]Overwrite element at writeIndex
writeIndex++Advance write pointer
function removeDuplicates(nums) {
    if (nums.length <= 2) return nums.length;
    let writeIndex = 1, count = 1;
    for (let readIndex = 1; readIndex < nums.length; readIndex++) {
        if (nums[readIndex] === nums[readIndex - 1]) {
            count++;
        } else {
            count = 1;
        }
        if (count <= 2) {
            nums[writeIndex] = nums[readIndex];
            writeIndex++;
        }
    }
    return writeIndex;
}

// Test
const arr = [1,1,1,2,2,3];
const length = removeDuplicates(arr);
console.log(length); // Expected: 5
console.log(arr.slice(0, length)); // Expected: [1,1,2,2,3]
Line Notes
if (nums.length <= 2) return nums.lengthHandle small arrays quickly
let writeIndex = 1, count = 1Initialize pointers and count
for (let readIndex = 1; readIndex < nums.length; readIndex++)Traverse array from second element
if (nums[readIndex] === nums[readIndex - 1])Check for duplicate
count++Increment count for duplicate
else { count = 1; }Reset count for new element
if (count <= 2)Allow up to two duplicates
nums[writeIndex] = nums[readIndex]Overwrite element at writeIndex
writeIndex++Advance write pointer
⏱
Complexity
TimeO(n)
SpaceO(1)

Single pass through the array with constant extra space.

💡 For n=20, this means about 20 operations, which is very efficient.
Interview Verdict: Accepted / Optimal for interview coding

This approach is efficient and easy to implement, making it ideal for interviews.

🧠
Two Pointers with Index Offset Check
💡 This approach leverages the sorted property and a clever index offset check to decide if the current element can be kept, simplifying the count tracking.

Intuition

Since duplicates are allowed at most twice, compare the current element with the element two positions before the write pointer. If different, copy current element; else skip.

Algorithm

  1. Initialize write_index to 0.
  2. Iterate read_index over the array.
  3. If write_index < 2 or nums[read_index] != nums[write_index - 2], copy nums[read_index] to nums[write_index].
  4. Increment write_index when copying.
  5. Return write_index as the new length.
💡 This method uses the sorted property and index offset to implicitly enforce the duplicate limit without counting.
</>
Code
def remove_duplicates(nums):
    write_index = 0
    for read_index in range(len(nums)):
        if write_index < 2 or nums[read_index] != nums[write_index - 2]:
            nums[write_index] = nums[read_index]
            write_index += 1
    return write_index

# Driver code
if __name__ == '__main__':
    arr = [1,1,1,2,2,3]
    length = remove_duplicates(arr)
    print(length)  # Expected: 5
    print(arr[:length])  # Expected: [1,1,2,2,3]
Line Notes
write_index = 0Initialize write pointer at start
for read_index in range(len(nums))Traverse entire array
if write_index < 2 or nums[read_index] != nums[write_index - 2]Allow element if less than two elements written or current differs from element two behind
nums[write_index] = nums[read_index]Copy allowed element
write_index += 1Advance write pointer
public class Solution {
    public static int removeDuplicates(int[] nums) {
        int writeIndex = 0;
        for (int readIndex = 0; readIndex < nums.length; readIndex++) {
            if (writeIndex < 2 || nums[readIndex] != nums[writeIndex - 2]) {
                nums[writeIndex] = nums[readIndex];
                writeIndex++;
            }
        }
        return writeIndex;
    }

    public static void main(String[] args) {
        int[] arr = {1,1,1,2,2,3};
        int length = removeDuplicates(arr);
        System.out.println(length); // Expected: 5
        for (int i = 0; i < length; i++) {
            System.out.print(arr[i] + " ");
        }
    }
}
Line Notes
int writeIndex = 0Initialize write pointer
for (int readIndex = 0; readIndex < nums.length; readIndex++)Traverse array
if (writeIndex < 2 || nums[readIndex] != nums[writeIndex - 2])Check if current element can be kept
nums[writeIndex] = nums[readIndex]Copy element to write position
writeIndex++Increment write pointer
#include <iostream>
#include <vector>
using namespace std;

int removeDuplicates(vector<int>& nums) {
    int writeIndex = 0;
    for (int readIndex = 0; readIndex < nums.size(); readIndex++) {
        if (writeIndex < 2 || nums[readIndex] != nums[writeIndex - 2]) {
            nums[writeIndex] = nums[readIndex];
            writeIndex++;
        }
    }
    return writeIndex;
}

int main() {
    vector<int> arr = {1,1,1,2,2,3};
    int length = removeDuplicates(arr);
    cout << length << endl; // Expected: 5
    for (int i = 0; i < length; i++) {
        cout << arr[i] << " ";
    }
    cout << endl;
    return 0;
}
Line Notes
int writeIndex = 0Initialize write pointer
for (int readIndex = 0; readIndex < nums.size(); readIndex++)Traverse array
if (writeIndex < 2 || nums[readIndex] != nums[writeIndex - 2])Check if current element can be kept
nums[writeIndex] = nums[readIndex]Copy element to write position
writeIndex++Increment write pointer
function removeDuplicates(nums) {
    let writeIndex = 0;
    for (let readIndex = 0; readIndex < nums.length; readIndex++) {
        if (writeIndex < 2 || nums[readIndex] !== nums[writeIndex - 2]) {
            nums[writeIndex] = nums[readIndex];
            writeIndex++;
        }
    }
    return writeIndex;
}

// Test
const arr = [1,1,1,2,2,3];
const length = removeDuplicates(arr);
console.log(length); // Expected: 5
console.log(arr.slice(0, length)); // Expected: [1,1,2,2,3]
Line Notes
let writeIndex = 0Initialize write pointer
for (let readIndex = 0; readIndex < nums.length; readIndex++)Traverse array
if (writeIndex < 2 || nums[readIndex] !== nums[writeIndex - 2])Check if current element can be kept
nums[writeIndex] = nums[readIndex]Copy element to write position
writeIndex++Increment write pointer
⏱
Complexity
TimeO(n)
SpaceO(1)

Single pass with constant extra space, no explicit counting needed.

💡 For n=20, this means about 20 operations, very efficient and clean.
Interview Verdict: Accepted / Optimal and elegant

This approach is often preferred in interviews for its simplicity and clarity.

📊
All Approaches - One-Glance Tradeoffs
💡 In interviews, the two-pointer approaches (2 and 3) are preferred for their efficiency and clarity. Brute force is useful to explain but not to implement.
ApproachTimeSpaceStack RiskReconstructUse In Interview
1. Brute ForceO(n^2)O(1)NoN/AMention only - never code
2. Two Pointers with Count TrackingO(n)O(1)NoN/ACode this if counting duplicates explicitly
3. Two Pointers with Index Offset CheckO(n)O(1)NoN/APreferred approach to code for simplicity and elegance
💼
Interview Strategy
💡 Use this guide to understand the problem deeply, practice coding the optimal approach, and prepare to explain your reasoning clearly during interviews.

How to Present

Step 1: Clarify the problem constraints and ask about allowed duplicates.Step 2: Present the brute force approach to show understanding.Step 3: Explain inefficiencies and introduce the two-pointer technique.Step 4: Code the optimal two-pointer solution with index offset check.Step 5: Test with examples and edge cases.

Time Allocation

Clarify: 2min → Approach: 3min → Code: 8min → Test: 2min. Total ~15min

What the Interviewer Tests

The interviewer tests your ability to optimize in-place array modifications, handle edge cases, and communicate your approach clearly.

Common Follow-ups

  • What if duplicates are allowed at most k times? → Use a generalized index offset or count approach.
  • Can you do this if the array is not sorted? → No, sorting or extra space is needed.
💡 These follow-ups test your ability to generalize the solution and understand problem constraints.
🔍
Pattern Recognition

When to Use

1) Input is sorted array, 2) Need to remove duplicates in-place, 3) Limit number of duplicates allowed, 4) Optimize for O(1) space

Signature Phrases

remove duplicates in-placeeach element appears at most twice

NOT This Pattern When

Problems requiring extra space or unordered arrays are different patterns.

Similar Problems

Remove Duplicates from Sorted Array - simpler version allowing only one duplicateRemove Element - removing all instances of a value in-placePartition Array - rearranging elements based on condition using two pointers

Practice

(1/5)
1. Consider the following code snippet implementing the Dutch National Flag algorithm. Given the input array [2, 0, 1], what is the value of mid after the first swap operation inside the while loop?
easy
A. 3
B. 2
C. 0
D. 1

Solution

  1. Step 1: Trace initial pointers and first iteration

    Initially, low=0, mid=0, high=2, nums=[2,0,1]. Since nums[mid]=2, swap nums[mid] and nums[high]: swap nums[0] and nums[2]. Array becomes [1,0,2], high=1, mid remains 0.
  2. Step 2: Value of mid after first swap

    After swapping 2 and 1, mid is not incremented and remains 0.
  3. Final Answer:

    Option C -> Option C
  4. Quick Check:

    mid does not increment after swapping 2, so mid=0 after first swap [OK]
Hint: mid increments only after swapping 0 [OK]
Common Mistakes:
  • Assuming mid increments after swapping 2
  • Off-by-one on mid pointer
  • Confusing low and mid increments
2. The following code attempts to implement the Dutch National Flag algorithm but contains a subtle bug. Identify the line causing the bug.
medium
A. Line where mid is incremented after swapping 0
B. Line where low is incremented
C. Line where mid is incremented after encountering 1
D. Line where high is decremented after swapping 2

Solution

  1. Step 1: Identify pointer updates after swapping 0

    After swapping nums[low] and nums[mid] when nums[mid]==0, both low and mid must be incremented to avoid infinite loops or incorrect ordering.
  2. Step 2: Locate missing increment

    The code increments low but does not increment mid after swapping 0, causing mid to stay at the same index and potentially reprocessing the same element indefinitely.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Missing mid increment after swapping 0 causes infinite loop or wrong output [OK]
Hint: mid must increment after swapping 0 to progress [OK]
Common Mistakes:
  • Forgetting mid increment after swap
  • Confusing pointer roles
  • Incrementing mid after swapping 2
3. What is the time complexity of the optimal two-pointer palindrome checking algorithm that first preprocesses the string by removing non-alphanumeric characters and converting to lowercase, then uses two pointers to compare characters?
medium
A. O(n) because preprocessing and single pass comparison each take linear time
B. O(n log n) due to sorting characters during preprocessing
C. O(n²) because each character is compared multiple times
D. O(n) for preprocessing but O(n²) for pointer comparisons

Solution

  1. Step 1: Identify preprocessing cost

    Filtering and lowercasing each character is O(n) where n is string length.
  2. Step 2: Analyze two-pointer comparison

    Two pointers move inward once each, total O(n) comparisons.
  3. Final Answer:

    Option A -> Option A
  4. Quick Check:

    Both steps are linear, total O(n) time [OK]
Hint: Preprocessing + one pass comparison = O(n) [OK]
Common Mistakes:
  • Assuming nested loops cause O(n²)
  • Confusing sorting with preprocessing
  • Forgetting that two pointers only scan once
4. Suppose the problem changes: you want to count pairs with absolute difference at most K, but now the array can contain duplicate elements and you want to count pairs where elements can be reused multiple times (i.e., pairs (i, j) with i ≤ j). Which modification to the binary search approach correctly handles this variant?
hard
A. Start binary search from i instead of i + 1 and count pairs where j ≥ i, adjusting count accordingly.
B. Use brute force nested loops to count all pairs with i ≤ j and difference ≤ K, as binary search cannot handle reuse.
C. Use two pointers with left starting at 0 and right starting at 0, moving right pointer forward and counting pairs including i = j.
D. Keep the same code but change bisect_right to bisect_left to include duplicates and allow i ≤ j pairs.

Solution

  1. Step 1: Understand reuse and duplicates impact

    Allowing i ≤ j means pairs with the same element twice are valid; binary search must include current index.
  2. Step 2: Modify binary search start index

    Starting bisect_right from i (not i+1) includes pairs where i == j; counting j ≥ i pairs correctly.
  3. Step 3: Adjust counting logic

    Count pairs as j - i + 1 if including i == j, or carefully count pairs with j ≥ i.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Starting search at i and counting pairs with j ≥ i handles reuse correctly [OK]
Hint: Start binary search at i to include pairs with i == j [OK]
Common Mistakes:
  • Using bisect_left instead of bisect_right incorrectly
  • Ignoring pairs where i == j
  • Assuming two pointers cannot handle reuse
5. Suppose the problem is modified so that the input string can contain Unicode characters beyond ASCII, and you must consider Unicode alphanumeric characters and case folding correctly. Which modification to the palindrome checking algorithm is most appropriate?
hard
A. Preprocess the string using Unicode-aware normalization (e.g., NFC) and case folding (str.casefold()), then apply two-pointer comparison.
B. Use the original two-pointer approach with str.isalnum() and str.lower() as is, since they handle Unicode correctly.
C. Skip preprocessing and compare characters directly using ord() values for Unicode code points.
D. Convert the string to ASCII by removing all non-ASCII characters before applying the original algorithm.

Solution

  1. Step 1: Understand Unicode challenges

    Unicode strings may have composed/decomposed forms and case folding beyond simple lowercasing.
  2. Step 2: Identify correct preprocessing

    Unicode normalization (NFC) and case folding (str.casefold()) handle these issues properly before palindrome check.
  3. Step 3: Apply two-pointer comparison after preprocessing

    After normalization and case folding, two-pointer approach works correctly on Unicode strings.
  4. Final Answer:

    Option A -> Option A
  5. Quick Check:

    Unicode-aware normalization and case folding are required for correct palindrome checks [OK]
Hint: Unicode needs normalization + case folding before two-pointer check [OK]
Common Mistakes:
  • Assuming str.lower() handles all Unicode cases
  • Ignoring Unicode normalization issues
  • Removing non-ASCII characters losing valid data
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard