Partition the string in two parts such that both parts have at least k different characters
Last Updated :
25 Sep, 2023
Given a string of lowercase English alphabets and an integer 0 < K <= 26. The task is to divide the string into two parts (also print them) such that both parts have at least k different characters. If there are more than one answers possible, print one having the smallest left part. If there is no such answers, print “Not Possible”.
Examples:
Input : str = “geeksforgeeks”, k = 4
Output : geeks , forgeeks
The string can be divided into two parts as “geeks” and “forgeeks”. Since “geeks” has four different characters ‘g’, ‘e’, ‘k’ and ‘s’ and this is the smallest left part, “forgeeks” has also at least four different characters.
Input : str = “aaaabbbb”, k = 2
Output :Not Possible
Approach:
- Idea is to count the number of distinct characters using a Hashmap.
- If the count of the distinct variable becomes equal to k, then the left part of the string is found so store this index, break the loop and unmark all the characters.
- Now run a loop from where the left string ends to end of the given string and repeat the same process as it was done to find the left string.
- If count is greater than or equal to k, then right string could be found otherwise print “Not Possible”.
- If it is possible , then print the left string and right string.
Below is the implementation of the above approach
C++
#include <iostream>
#include <map>
using namespace std;
void division_of_string(string str, int k)
{
int n = str.size();
map< char , bool > has;
int ans, cnt = 0, i = 0;
while (i < n) {
if (!has[str[i]]) {
cnt++;
has[str[i]] = true ;
}
if (cnt == k) {
ans = i;
break ;
}
i++;
}
i++;
has.clear();
cnt = 0;
while (i < n) {
if (!has[str[i]]) {
cnt++;
has[str[i]] = true ;
}
if (cnt == k) {
break ;
}
i++;
}
if (cnt < k) {
cout << "Not possible" << endl;
}
else {
i = 0;
while (i <= ans) {
cout << str[i];
i++;
}
cout << endl;
while (i < n) {
cout << str[i];
i++;
}
cout << endl;
}
cout << endl;
}
int main()
{
string str = "geeksforgeeks" ;
int k = 4;
division_of_string(str, k);
return 0;
}
|
Java
import java.util.*;
class GFG {
static void division_of_string( char [] str, int k)
{
int n = str.length;
Map<Character, Boolean> has = new HashMap<>();
int ans = 0 , cnt = 0 , i = 0 ;
while (i < n) {
if (!has.containsKey(str[i])) {
cnt++;
has.put(str[i], true );
}
if (cnt == k) {
ans = i;
break ;
}
i++;
}
i++;
has.clear();
cnt = 0 ;
while (i < n) {
if (!has.containsKey(str[i])) {
cnt++;
has.put(str[i], true );
}
if (cnt == k) {
break ;
}
i++;
}
if (cnt < k) {
System.out.println( "Not possible" );
}
else {
i = 0 ;
while (i <= ans) {
System.out.print(str[i]);
i++;
}
System.out.println( "" );
while (i < n) {
System.out.print(str[i]);
i++;
}
System.out.println( "" );
}
System.out.println( "" );
}
public static void main(String[] args)
{
String str = "geeksforgeeks" ;
int k = 4 ;
division_of_string(str.toCharArray(), k);
}
}
|
Python3
def division_of_string(string, k):
n = len (string)
has = {}
cnt = 0
i = 0
while (i < n):
if string[i] not in has:
cnt + = 1
has[string[i]] = True
if (cnt = = k):
ans = i
break
i + = 1
i + = 1
has.clear()
cnt = 0
while (i < n):
if (string[i] not in has):
cnt + = 1
has[string[i]] = True
if (cnt = = k):
break
i + = 1
if (cnt < k):
print ( "Not possible" , end = "")
else :
i = 0
while (i < = ans):
print (string[i], end = "")
i + = 1
print ()
while (i < n):
print (string[i], end = "")
i + = 1
print ()
if __name__ = = "__main__" :
string = "geeksforgeeks"
k = 4
division_of_string(string, k)
|
C#
using System;
using System.Collections.Generic;
class GFG {
static void division_of_string( char [] str, int k)
{
int n = str.Length;
Dictionary< char , bool > has
= new Dictionary< char , bool >();
int ans = 0, cnt = 0, i = 0;
while (i < n) {
if (!has.ContainsKey(str[i])) {
cnt++;
has.Add(str[i], true );
}
if (cnt == k) {
ans = i;
break ;
}
i++;
}
i++;
has.Clear();
cnt = 0;
while (i < n) {
if (!has.ContainsKey(str[i])) {
cnt++;
has.Add(str[i], true );
}
if (cnt == k) {
break ;
}
i++;
}
if (cnt < k) {
Console.WriteLine( "Not possible" );
}
else {
i = 0;
while (i <= ans) {
Console.Write(str[i]);
i++;
}
Console.WriteLine( "" );
while (i < n) {
Console.Write(str[i]);
i++;
}
Console.WriteLine( "" );
}
Console.WriteLine( "" );
}
public static void Main(String[] args)
{
String str = "geeksforgeeks" ;
int k = 4;
division_of_string(str.ToCharArray(), k);
}
}
|
Javascript
<script>
function division_of_string(str, k)
{
let n = str.length;
let has = new Map();
let ans = 0, cnt = 0, i = 0;
while (i < n)
{
if (!has.has(str[i]))
{
cnt++;
has.set(str[i], true );
}
if (cnt == k)
{
ans = i;
break ;
}
i++;
}
i++;
has.clear();
cnt = 0;
while (i < n)
{
if (!has.has(str[i]))
{
cnt++;
has.set(str[i], true );
}
if (cnt == k)
{
break ;
}
i++;
}
if (cnt < k)
{
document.write( "Not possible" + "<br/>" );
}
else
{
i = 0;
while (i <= ans)
{
document.write(str[i]);
i++;
}
document.write( "" + "<br/>" );
while (i < n)
{
document.write(str[i]);
i++;
}
document.write( "" + "<br/>" );
}
document.write( "" + "<br/>" );
}
let str = "geeksforgeeks" ;
let k = 4;
division_of_string(str.split(''), k);
</script>
|
Time Complexity: O(N) where N is the length of the given string.
Auxiliary Space: O(k) where k is the number of distinct characters in the first substring
Efficient Approach: Instead of using hashmap, we can create a frequency array which keep track of frequency which will be constant and doesnot depend on the size of the string.
Step by step algorithm:
- Initialize left pointer to 0, right pointer to 0, mid to -1, and an array of size 26 to store frequency of each character.
- While k > 0 and right < n, increment frequency of the character at the right pointer, and decrement k if the frequency is 1.
- If k is still greater than 0, return “Not possible”.
- Set mid to right – 1.
- Move left pointer to the right until mid and the frequency of the character at the left pointer is greater than 1.
- Print the first substring from index 0 to mid and the second substring from index mid+1 to the end of the string.
C++
#include <iostream>
#include <cstring>
using namespace std;
void division_of_string(string str, int k) {
int n = str.size();
int left = 0, right = 0, mid = -1;
int freq[26];
memset (freq, 0, sizeof (freq));
while (right < n && k > 0) {
if (freq[str[right]- 'a' ] == 0) {
k--;
}
freq[str[right]- 'a' ]++;
right++;
}
if (k > 0) {
cout << "Not possible" << endl;
return ;
}
mid = right - 1;
while (left < mid && freq[str[left]- 'a' ] > 1) {
freq[str[left]- 'a' ]--;
left++;
}
cout << str.substr(0, mid+1) << endl << str.substr(mid+1) << endl;
}
int main() {
string str = "geeksforgeeks" ;
int k = 4;
division_of_string(str, k);
return 0;
}
|
Java
import java.util.HashMap;
public class GFG {
public static void divisionOfString(String str, int k) {
int n = str.length();
int left = 0 , right = 0 , mid = - 1 ;
int [] freq = new int [ 26 ];
HashMap<Character, Integer> charCount = new HashMap<>();
while (right < n && k > 0 ) {
char ch = str.charAt(right);
if (charCount.getOrDefault(ch, 0 ) == 0 ) {
k--;
}
charCount.put(ch, charCount.getOrDefault(ch, 0 ) + 1 );
right++;
}
if (k > 0 ) {
System.out.println( "Not possible" );
return ;
}
mid = right - 1 ;
while (left < mid && charCount.get(str.charAt(left)) > 1 ) {
char ch = str.charAt(left);
charCount.put(ch, charCount.get(ch) - 1 );
left++;
}
System.out.println(str.substring( 0 , mid + 1 ));
System.out.println(str.substring(mid + 1 ));
}
public static void main(String[] args) {
String str = "geeksforgeeks" ;
int k = 4 ;
divisionOfString(str, k);
}
}
|
Python
def GFG(s, k):
n = len (s)
left = 0
right = 0
mid = - 1
freq = [ 0 ] * 26
while right < n and k > 0 :
if freq[ ord (s[right]) - ord ( 'a' )] = = 0 :
k - = 1
freq[ ord (s[right]) - ord ( 'a' )] + = 1
right + = 1
if k > 0 :
print ( "Not possible" )
return
mid = right - 1
while left < mid and freq[ ord (s[left]) - ord ( 'a' )] > 1 :
freq[ ord (s[left]) - ord ( 'a' )] - = 1
left + = 1
print (s[:mid + 1 ])
print (s[mid + 1 :])
def main():
s = "geeksforgeeks"
k = 4
GFG(s, k)
if __name__ = = "__main__" :
main()
|
C#
using System;
class GFG {
static void DivisionOfString( string str, int k)
{
int n = str.Length;
int left = 0, right = 0, mid = -1;
int [] freq = new int [26];
while (right < n && k > 0) {
if (freq[str[right] - 'a' ] == 0) {
k--;
}
freq[str[right] - 'a' ]++;
right++;
}
if (k > 0) {
Console.WriteLine( "Not possible" );
return ;
}
mid = right - 1;
while (left < mid && freq[str[left] - 'a' ] > 1) {
freq[str[left] - 'a' ]--;
left++;
}
Console.WriteLine(str.Substring(0, mid + 1));
Console.WriteLine(str.Substring(mid + 1));
}
static void Main()
{
string str = "geeksforgeeks" ;
int k = 4;
DivisionOfString(str, k);
}
}
|
Javascript
function divisionOfString(str, k) {
const n = str.length;
let left = 0, right = 0, mid = -1;
const freq = new Array(26).fill(0);
while (right < n && k > 0) {
if (freq[str.charCodeAt(right) - 'a' .charCodeAt()] === 0) {
k--;
}
freq[str.charCodeAt(right) - 'a' .charCodeAt()]++;
right++;
}
if (k > 0) {
console.log( "Not possible" );
return ;
}
mid = right - 1;
while (left < mid && freq[str.charCodeAt(left) - 'a' .charCodeAt()] > 1) {
freq[str.charCodeAt(left) - 'a' .charCodeAt()]--;
left++;
}
console.log(str.substring(0, mid + 1));
console.log(str.substring(mid + 1));
}
const str = "geeksforgeeks" ;
const k = 4;
divisionOfString(str, k);
|
Time complexity: O(n), where n is the length of the string.
Auxiliary Space: O(1), since we are using a fixed-size array of 26 integers to keep track of character frequencies, which is independent of the length of the string.
Share your thoughts in the comments
Please Login to comment...