↓Skip to main content
  1. LeetCode/

LeetCode 4019: Merge Close Characters II

·2 mins· ·
LeetCode Medium Hash-Table String
Wei Yi Chung
Author
Wei Yi Chung
Working at the contributing of open source, distributed systems, and data engineering.
Table of Contents

Meta Data
#

Difficulty: medium First Attempt: 2026-09-13

  • Submissions: Wrong Answer → Accepted

Approach
#

Each step picks the close pair with the smallest i, so merging settles from the left: the processed, kept prefix has no close pair and never changes again.

So build the result left to right (String Template 1):

  • Record each character’s last position in the result, last[ch].
  • A new character would land at len(res); if len(res) - last[ch] <= k, it is close to the earlier one and gets merged away.
  • Otherwise append it and update last[ch].

Distances use positions in the result, because the problem renumbers indices after each deletion.

My Attempts
#

Attempt 1 tried converting original indices to current positions by subtracting “recent deletions”, keeping deleted positions in a deque window, but only subtracted deletions inside the window, so distances were wrong. For "ccccca", k = 1 all the cs merge into one, answer "ca"; it returned "cca". Recording positions in the result directly passed.

Solution
#

class Solution:
    def mergeCharacters(self, s: str, k: int) -> str:
        last, res = {}, []
        for ch in s:
            if ch in last and len(res) - last[ch] <= k:
                continue                           # close to an earlier copy, merged
            last[ch] = len(res)
            res.append(ch)
        return "".join(res)

Complexity
#

Time O(n), space O(n).

Mistakes to Avoid
#

  • Indices are renumbered after deletions; measure distance in result positions.

Interview Explanation
#

Since the pair with the smallest i always merges first, the kept prefix never changes. I build the result left to right, recording each character’s last position in it; a new character within k of that position is merged away, otherwise it is appended. Time O(n).

Related

LeetCode 3713: Longest Balanced Substring I
·2 mins
LeetCode Medium Hash-Table String Counting Enumeration
LeetCode 3713 note: fix the start and extend right; “every character has the same count” means “highest count × kinds = length”, an O(1) check per step
LeetCode 3900: Longest Balanced Substring After One Swap
·3 mins
LeetCode Medium Prefix-Sum Hash-Table String
LeetCode 3900 note: equal prefix differences mean balanced; a substring off by 2 also works if a swappable character exists outside, and keeping the two earliest positions per difference is enough
LeetCode 3839: Number of Prefix Connected Groups
·1 min
LeetCode Medium Hash-Table String Counting
LeetCode 3839 note: words sharing the first k characters are connected, so count by word[:k]; exclude words shorter than k
LeetCode 244: Shortest Word Distance II
·2 mins
LeetCode Medium Two-Pointers Design Hash-Table String Array
LeetCode 244 note: precompute each word’s positions (sorted by construction), then answer each query by merging the two position lists with two pointers, always advancing the smaller one
LeetCode 3306: Count of Substrings Containing Every Vowel and K Consonants II
·2 mins
LeetCode Medium Sliding-Window Hash-Table String
LeetCode 3306 note: “exactly k consonants” is not monotonic; compute “all five vowels and at least k consonants” minus “at least k + 1”, both “at least” counting windows
LeetCode 1358: Number of Substrings Containing All Three Characters
·2 mins
LeetCode Medium Sliding-Window Hash-Table String
LeetCode 1358 note: an “at least one each of a, b, c” counting window: keep shrinking while all three are present, then count += left