Given a string str and an integer k, the task is to reduce the string by applying the following operation any number of times until it is no longer possible:
Choose a group of k consecutive identical characters and remove them from the string.
Finally, print the reduced string.
Examples:
Input: K = 2, str = "geeksforgeeks"
Output: gksforgks
Explanation: After removal of both occurrences of the substring "ee", the string reduces to "gksforgks".Input: K = 3, str = "qddxxxd"
Output: q
Explanation: Removal of "xxx" modifies the string to "qddd". Again, removal of "ddd" modifies the string to "q".
Approach: Using a Stack of Pairs - O(n) time and O(n) space
The approach uses a stack to track characters and their consecutive occurrences. As the string is processed, characters are pushed onto the stack with a count of consecutive occurrences. If a character repeats
ktimes, it is skipped. After processing, the remaining characters in the stack are used to build the result string, which is then reversed to maintain the correct order.
#include <iostream>
#include <stack>
#include <string>
#include <algorithm>
using namespace std;
string removeKChar(int k, string str) {
if (k == 1) return "";
string ans = "";
stack<pair<char, int>> stk;
for (int i = 0; i < str.size(); i++) {
if (stk.empty()) {
stk.push(make_pair(str[i], 1));
} else {
if (str[i] == stk.top().first) {
pair<char, int> p = stk.top();
stk.pop();
p.second++;
if (p.second < k) stk.push(p);
} else {
stk.push(make_pair(str[i], 1));
}
}
}
while (!stk.empty()) {
if (stk.top().second > 1) {
int count = stk.top().second;
while (count--) ans += stk.top().first;
} else {
ans += stk.top().first;
}
stk.pop();
}
reverse(ans.begin(), ans.end());
return ans;
}
int main() {
string s = "geeksforgeeks";
int k = 2;
cout << removeKChar(k, s) << "\n";
return 0;
}
import java.util.*;
public class GfG {
static String removeKChar(int k, String str) {
if (k == 1) return "";
StringBuilder ans = new StringBuilder();
Stack<Pair<Character, Integer>> stk = new Stack<>();
for (char c : str.toCharArray()) {
if (stk.isEmpty()) {
stk.push(new Pair<>(c, 1));
} else {
if (c == stk.peek().getKey()) {
Pair<Character, Integer> p = stk.pop();
if (p.getValue() + 1 < k) stk.push(new Pair<>(p.getKey(), p.getValue() + 1));
} else {
stk.push(new Pair<>(c, 1));
}
}
}
while (!stk.isEmpty()) {
Pair<Character, Integer> top = stk.pop();
for (int i = 0; i < top.getValue(); i++) {
ans.append(top.getKey());
}
}
return ans.reverse().toString();
}
public static void main(String[] args) {
String s = "geeksforgeeks";
int k = 2;
System.out.println(removeKChar(k, s));
}
}
class Pair<K, V> {
private K key;
private V value;
public Pair(K key, V value) {
this.key = key;
this.value = value;
}
public K getKey() { return key; }
public V getValue() { return value; }
}
def removeKChar(k, s):
if k == 1:
return ""
ans = ""
stk = []
for char in s:
if not stk:
stk.append((char, 1))
else:
if char == stk[-1][0]:
p = stk.pop()
if p[1] + 1 < k:
stk.append((p[0], p[1] + 1))
else:
stk.append((char, 1))
while stk:
if stk[-1][1] > 1:
count = stk[-1][1]
ans += stk[-1][0] * count
else:
ans += stk[-1][0]
stk.pop()
return ans[::-1]
s = "geeksforgeeks"
k = 2
print(removeKChar(k, s))
using System;
using System.Collections.Generic;
using System.Text;
class Program
{
static string removeKChar(int k, string str)
{
if (k == 1) return "";
StringBuilder ans = new StringBuilder();
Stack<Tuple<char, int>> stk = new Stack<Tuple<char, int>>();
foreach (char c in str)
{
if (stk.Count == 0)
{
stk.Push(Tuple.Create(c, 1));
}
else
{
if (c == stk.Peek().Item1)
{
var p = stk.Pop();
if (p.Item2 + 1 < k)
stk.Push(Tuple.Create(p.Item1, p.Item2 + 1));
}
else
{
stk.Push(Tuple.Create(c, 1));
}
}
}
while (stk.Count > 0)
{
var top = stk.Pop();
ans.Append(top.Item1, top.Item2);
}
char[] result = ans.ToString().ToCharArray();
Array.Reverse(result);
return new string(result);
}
static void Main()
{
string s = "geeksforgeeks";
int k = 2;
Console.WriteLine(removeKChar(k, s));
}
}
function removeKChar(k, str) {
if (k === 1) return "";
let ans = "";
let stk = [];
for (let char of str) {
if (stk.length === 0) {
stk.push([char, 1]);
} else {
if (char === stk[stk.length - 1][0]) {
let p = stk.pop();
if (p[1] + 1 < k) stk.push([p[0], p[1] + 1]);
} else {
stk.push([char, 1]);
}
}
}
while (stk.length > 0) {
let top = stk.pop();
ans += top[0].repeat(top[1]);
}
return ans.split('').reverse().join('');
}
let s = "geeksforgeeks";
let k = 2;
console.log(removeKChar(k, s));
Output
gksforgks
Approach: Using a Single Stack - O(n) time and O(n) space
The approach uses a stack to remove consecutive characters that appear exactly
ktimes. As we iterate through the string, we push each character onto the stack. If the top of the stack matches the current character, we increment a count. When the count reachesk, the characters are effectively removed. After processing the string, the remaining characters in the stack are popped and concatenated to form the final result.
#include <iostream>
#include <stack>
#include <string>
using namespace std;
string removeKChar(int k, string s) {
stack<char> st;
int i = 0;
while (i < s.size()) {
char ch = s[i++];
st.push(ch);
int count = 0;
while (!st.empty() && st.top() == ch) {
count++;
st.pop();
}
if (count == k)
continue;
else {
while (count > 0) {
st.push(ch);
count--;
}
}
}
string result = "";
while (!st.empty()) {
result = st.top() + result;
st.pop();
}
return result;
}
int main() {
int k = 2;
string s = "geeksforgeeks";
string ans = removeKChar(k, s);
cout << ans << endl;
return 0;
}
import java.util.Stack;
public class GfG {
public static String removeKChar(int k, String s) {
Stack<Character> st = new Stack<>();
int i = 0;
while (i < s.length()) {
char ch = s.charAt(i++);
st.push(ch);
int count = 0;
while (!st.isEmpty() && st.peek() == ch) {
count++;
st.pop();
}
if (count == k)
continue;
else {
while (count > 0) {
st.push(ch);
count--;
}
}
}
StringBuilder result = new StringBuilder();
while (!st.isEmpty()) {
result.insert(0, st.pop());
}
return result.toString();
}
public static void main(String[] args) {
int k = 2;
String s = "geeksforgeeks";
String ans = removeKChar(k, s);
System.out.println(ans);
}
}
def removeKChar(k, s):
stack = []
i = 0
while i < len(s):
ch = s[i]
stack.append(ch)
count = 0
while stack and stack[-1] == ch:
count += 1
stack.pop()
if count == k:
continue
else:
stack.extend([ch] * count)
i += 1
return ''.join(stack)
if __name__ == '__main__':
k = 2
s = "geeksforgeeks"
ans = removeKChar(k, s)
print(ans)
using System;
using System.Collections.Generic;
class GfG {
public static string RemoveKChar(int k, string s) {
Stack<char> stack = new Stack<char>();
int i = 0;
while (i < s.Length) {
char ch = s[i++];
stack.Push(ch);
int count = 0;
while (stack.Count > 0 && stack.Peek() == ch) {
count++;
stack.Pop();
}
if (count == k)
continue;
else {
while (count > 0) {
stack.Push(ch);
count--;
}
}
}
char[] result = stack.ToArray();
Array.Reverse(result);
return new string(result);
}
static void Main() {
int k = 2;
string s = "geeksforgeeks";
string ans = RemoveKChar(k, s);
Console.WriteLine(ans);
}
}
function removeKChar(k, s) {
let stack = [];
let i = 0;
while (i < s.length) {
let ch = s[i++];
stack.push(ch);
let count = 0;
while (stack.length > 0 && stack[stack.length - 1] === ch) {
count++;
stack.pop();
}
if (count === k)
continue;
else {
while (count > 0) {
stack.push(ch);
count--;
}
}
}
return stack.join('');
}
let k = 2;
let s = "geeksforgeeks";
let ans = removeKChar(k, s);
console.log(ans);
Output
gksforgks