Talentd
FleetCode
Make and follow sheets.Sign in

Minimum Deletions to Make String K-Special solution and explanation

MediumCountingGreedyHash TableSorting6 min read67.2% acceptanceUpdated 9 Apr 2026
Minimum Deletions to Make String K-Special | 2 Simple Approaches | Leetcode 3085 | codestorywithMIKcodestorywithMIK · 37:11 · 12K viewsWatch on YouTube
9 more videos on this problem
  1. Minimum Deletions to Make String K-Special | 2 Simple Approaches | Leetcode 3085 | codestorywithMIKcodestorywithMIK · 37:11 · 12K views
  2. 3085. Minimum Deletions to Make String K-Special | DP | Hash TableAryan Mittal · 16:14 · 5K views
  3. 3085. Minimum Deletions to Make String K-Special | Leetcode Daily - PythonLeetcode Daily · 5:19 · 1K views
  4. 3085 Minimum Deletions to Make String K Special | LeetCode | Greedy | HashmapR Sai Siddhu · 15:01 · 1K views
  5. 3085. Minimum Deletions to Make String K-Special | HARDER VERSION | Weekly Leetcode 389codingMohan · 33:29 · 832 views
  6. 3085. Minimum Deletions to Make String K-Special | HashMap | Greedy | String | LeetcodeRapid Syntax · 15:32 · 803 views
  7. 3085. Minimum Deletions to Make String K-Special (Leetcode Medium)Programming Live with Larry · 11:34 · 636 views
  8. 3085. Minimum Deletions to Make String K-Special || Leetcode Weekly Contest 389Ashish Kumar · 13:47 · 501 views
  9. Leetcode 3085 - Minimum Deletions to Make String K-Special | Java Explained with IntuitioncodingX krishna · 22:55 · 297 views
  10. Leetcode 3085. Minimum Deletions to Make String K-Special | Greedy Frequency Reduction ExplainedStatLearn Tech · 16:54 · 273 views

The problem

You are given a string word and an integer k.

We consider word to be k-special if |freq(word[i]) - freq(word[j])| <= k for all indices i and j in the string.

Here, freq(x) denotes the frequency of the character x in word, and |y| denotes the absolute value of y.

Return the minimum number of characters you need to delete to make word k-special.

Example 1:

Input: word = "aabcaba", k = 0

Output: 3

Explanation: We can make word 0-special by deleting 2 occurrences of "a" and 1 occurrence of "c". Therefore, word becomes equal to "baba" where freq('a') == freq('b') == 2.

Example 2:

Input: word = "dabdcbdcdcd", k = 2

Output: 2

Explanation: We can make word 2-special by deleting 1 occurrence of "a" and 1 occurrence of "d". Therefore, word becomes equal to "bdcbdcdcd" where freq('b') == 2, freq('c') == 3, and freq('d') == 4.

Example 3:

Input: word = "aaabaaa", k = 2

Output: 1

Explanation: We can make word 2-special by deleting 1 occurrence of "b". Therefore, word becomes equal to "aaaaaa" where each letter's frequency is now uniformly 6.

Constraints:

  • 1 <= word.length <= 105
  • 0 <= k <= 105
  • word consists only of lowercase English letters.

Approach overview

Problem Overview: You are given a string s and an integer k. A string is k‑special if the difference between the frequencies of any two characters is at most k. You can delete characters from the string. The goal is to compute the minimum deletions required so the remaining character frequencies satisfy this constraint.

Approach 1: Brute Force Search (O(26²) time, O(26) space)

Start by counting the frequency of every character using a hash map or fixed array of size 26. Treat each possible frequency as the baseline minimum frequency you want to keep. For a chosen base f, every character with frequency less than f must be fully deleted, while characters with frequency greater than f + k must be reduced down to f + k. Iterate through all candidate base frequencies and compute the deletions required for each. The smallest deletion count is the answer. This approach works because the alphabet size is small, but it still evaluates many redundant cases.

Approach 2: Hash Map for Quick Lookup (Greedy + Sorting) (O(26 log 26) time, O(26) space)

First count character frequencies using a hash table. Extract the frequency values and sort them using sorting. Now iterate through the sorted frequencies and treat each value as the minimum allowed frequency. For every other frequency, apply a greedy adjustment: delete the entire character if its count is below the baseline, or trim it down to baseline + k if it exceeds the allowed range. Because the list is sorted, you can compute deletions efficiently with simple iteration. The greedy rule works because keeping frequencies within a sliding window of size k minimizes unnecessary deletions.

This strategy combines greedy reasoning with frequency counting. Since there are at most 26 distinct characters, the algorithm is effectively constant time for real inputs while remaining clean and interview-friendly.

Recommended for interviews: Interviewers usually expect the frequency-count + greedy adjustment approach. Showing the brute force baseline demonstrates that you understand the constraint mathematically, but implementing the sorted frequency or hash map optimization shows stronger algorithmic thinking and awareness of counting-based string techniques.

Approach 1: Approach 1: Brute Force Search

This approach involves checking all possible combinations to find those that satisfy the conditions of the problem. Although not the most efficient, it ensures all possibilities are covered.

def solve_brute_force(arr):
    n = len(arr)
    for i in range(n):
        for j in range(i + 1, n):
            if arr[i] + arr[j] == TARGET:
                print(f"Pair found: ({arr[i]}, {arr[j]})")
public class Solution {
    public static void solveBruteForce(int[] arr) {
        int n = arr.length;
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                if (arr[i] + arr[j] == TARGET) {
                    System.out.println("Pair found: (" + arr[i] + ", " + arr[j] + ")");
                }
            }
        }
    }
}
#include <iostream>
#include <vector>

void solveBruteForce(std::vector<int>& arr) {
    int n = arr.size();
    for (int i = 0; i < n; i++) {
        for (int j = i + 1; j < n; j++) {
            if (arr[i] + arr[j] == TARGET) {
                std::cout << "Pair found: (" << arr[i] << ", " << arr[j] << ")\n";
            }
        }
    }
}
function solveBruteForce(arr) {
    let n = arr.length;
    for (let i = 0; i < n; i++) {
        for (let j = i + 1; j < n; j++) {
            if (arr[i] + arr[j] === TARGET) {
                console.log(`Pair found: (${arr[i]}, ${arr[j]})`);
            }
        }
    }
}
#include <stdio.h>

void solveBruteForce(int arr[], int n) {
    for (int i = 0; i < n; 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]);
            }
        }
    }
}
using System;

public class Solution {
    public static void SolveBruteForce(int[] arr) {
        int n = arr.Length;
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; j < n; j++) {
                if (arr[i] + arr[j] == TARGET) {
                    Console.WriteLine($"Pair found: ({arr[i]}, {arr[j]})");
                }
            }
        }
    }
}

Python's elegant syntax allows direct iteration over array indices to evaluate all element pairs.

Complexity

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

Try this approach in the editor

Approach 2: Approach 2: Hash Map for Quick Lookup

This approach leverages a hash map to store elements and their indices. By checking for the complement (target - current element) during traversal, we reduce the time complexity significantly.

def solve_with_hash_map(arr):
    hash_map = {}
    for num in arr:
        complement = TARGET - num
        if complement in hash_map:
            print(f"Pair found: ({complement}, {num})")
        hash_map[num] = True
import java.util.HashMap;

public class Solution {
    public static void solveWithHashMap(int[] arr) {
        HashMap<Integer, Boolean> hashMap = new HashMap<>();
        for (int num : arr) {
            int complement = TARGET - num;
            if (hashMap.getOrDefault(complement, false)) {
                System.out.println("Pair found: (" + complement + ", " + num + ")");
            }
            hashMap.put(num, true);
        }
    }
}
#include <iostream>
#include <unordered_map>
#include <vector>

void solveWithHashMap(std::vector<int>& arr) {
    std::unordered_map<int, bool> hashMap;
    for (int num : arr) {
        int complement = TARGET - num;
        if (hashMap[complement]) {
            std::cout << "Pair found: (" << complement << ", " << num << ")\n";
        }
        hashMap[num] = true;
    }
}
function solveWithHashMap(arr) {
    let hashMap = {};
    for (let num of arr) {
        let complement = TARGET - num;
        if (hashMap[complement] !== undefined) {
            console.log(`Pair found: (${complement}, ${num})`);
        }
        hashMap[num] = true;
    }
}
#include <stdio.h>
#include <stdlib.h>

void solveWithHashMap(int arr[], int n) {
    int hashMap[10000] = {0};
    for (int i = 0; i < n; i++) {
        int complement = TARGET - arr[i];
        if (hashMap[complement]) {
            printf("Pair found: (%d, %d)\n", complement, arr[i]);
        }
        hashMap[arr[i]] = 1;
    }
}
using System;
using System.Collections.Generic;

public class Solution {
    public static void SolveWithHashMap(int[] arr) {
        Dictionary<int, bool> hashMap = new Dictionary<int, bool>();
        foreach (int num in arr) {
            int complement = TARGET - num;
            if (hashMap.ContainsKey(complement)) {
                Console.WriteLine($"Pair found: ({complement}, {num})");
            }
            hashMap[num] = true;
        }
    }
}

Python's dictionary allows storage and lookup of complementary elements efficiently.

Complexity

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

Try this approach in the editor

Approach 3: Counting + Enumeration

First, we can count the occurrence of each character in the string and put all the counts into an array nums. Since the string only contains lowercase letters, the length of the array nums will not exceed 26.

Next, we can enumerate the minimum frequency v of characters in the K special strings within the range [0,..n], and then use a function f(v) to calculate the minimum number of deletions to adjust the frequency of all characters to v. The minimum value of all f(v) is the answer.

The calculation method of function f(v) is as follows:

Traverse each element x in the array nums. If x < v, it means that we need to delete all characters with a frequency of x, and the number of deletions is x. If x > v + k, it means that we need to adjust all characters with a frequency of x to v + k, and the number of deletions is x - v - k. The sum of all deletion counts is the value of f(v).

The time complexity is O(n times |\Sigma|), and the space complexity is O(|\Sigma|). Here, n is the length of the string, and |\Sigma| is the size of the character set. In this problem, |\Sigma| = 26.

function minimumDeletions(word: string, k: number): number {
    const freq: number[] = Array(26).fill(0);
    for (const ch of word) {
        ++freq[ch.charCodeAt(0) - 97];
    }
    const nums = freq.filter(x => x > 0);
    const f = (v: number): number => {
        let ans = 0;
        for (const x of nums) {
            if (x < v) {
                ans += x;
            } else if (x > v + k) {
                ans += x - v - k;
            }
        }
        return ans;
    };
    return Math.min(...Array.from({ length: word.length + 1 }, (_, i) => f(i)));
}
func minimumDeletions(word string, k int) int {
	freq := [26]int{}
	for _, c := range word {
		freq[c-'a']++
	}
	nums := []int{}
	for _, v := range freq {
		if v > 0 {
			nums = append(nums, v)
		}
	}
	f := func(v int) int {
		ans := 0
		for _, x := range nums {
			if x < v {
				ans += x
			} else if x > v+k {
				ans += x - v - k
			}
		}
		return ans
	}
	ans := len(word)
	for i := 0; i <= len(word); i++ {
		ans = min(ans, f(i))
	}
	return ans
}
impl Solution {
    pub fn minimum_deletions(word: String, k: i32) -> i32 {
        let mut freq = [0; 26];
        for c in word.chars() {
            freq[(c as u8 - b'a') as usize] += 1;
        }
        let mut nums = vec![];
        for &v in freq.iter() {
            if v > 0 {
                nums.push(v);
            }
        }
        let n = word.len() as i32;
        let mut ans = n;
        for i in 0..=n {
            let mut cur = 0;
            for &x in nums.iter() {
                if x < i {
                    cur += x;
                } else if x > i + k {
                    cur += x - i - k;
                }
            }
            ans = ans.min(cur);
        }
        ans
    }
}
Try this approach in the editor

Complexity comparison

ApproachComplexity
Approach 1: Brute Force Search

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

Approach 2: Hash Map for Quick Lookup

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

Counting + Enumeration–

Complexity analysis

ApproachTimeSpaceWhen to Use
Brute Force Search over FrequenciesO(26²)O(26)Good for understanding the constraint and testing every possible baseline frequency
Hash Map + Greedy Adjustment with SortingO(26 log 26)O(26)Best general solution; efficient frequency analysis with simple greedy trimming

Frequently asked questions

Is Minimum Deletions to Make String K-Special easy or hard?

Minimum Deletions to Make String K-Special is rated Medium. The challenge is identifying that you should operate on character frequencies rather than the string itself, then apply greedy trimming so all frequencies stay within a difference of k.

Minimum Deletions to Make String K-Special Python/Java solution

The typical Python or Java implementation builds a frequency map using a dictionary or array of size 26, extracts the counts, sorts them, and evaluates the minimum deletions for each candidate baseline frequency. Both languages implement the same greedy trimming logic and run in O(n) overall time.

How to solve Minimum Deletions to Make String K-Special in O(n)?

First compute the frequency of each character in O(n). Then iterate through possible baseline frequencies and calculate deletions by removing characters below the baseline and trimming those above baseline + k. Since the alphabet size is fixed (26), the additional work is constant, making the effective complexity linear in the string length.

What is the best approach for Minimum Deletions to Make String K-Special?

The best approach counts character frequencies with a hash map, sorts the frequency list, and greedily enforces the constraint that all frequencies stay within a window of size k. For each possible baseline frequency, characters below it are removed and characters above baseline + k are trimmed. Because there are at most 26 characters, this runs in about O(26 log 26) time and O(26) space.

Is Minimum Deletions to Make String K-Special asked at Google/Amazon/Meta?

Problems involving frequency balancing, greedy deletions, and hash-map counting frequently appear in interviews at companies like Amazon, Google, and Meta. Variants of this problem test understanding of string frequency constraints and greedy optimization.

What data structure is used in Minimum Deletions to Make String K-Special?

A hash table or fixed-size frequency array is used to count how many times each character appears. After counting, an array or list of frequencies is processed with sorting and greedy adjustments to enforce the k-difference constraint.

What is the time complexity of Minimum Deletions to Make String K-Special?

The optimal solution runs in O(n + 26 log 26) time where n is the string length. O(n) is used to count frequencies, and sorting at most 26 character counts costs O(26 log 26). Space complexity is O(26) for the frequency table.

Comments

Now write it yourselfClose this page and solve Minimum Deletions to Make String K-Special in the editor, without looking.
Practise Minimum Deletions to Make String K-Special