Open In App

Minimum length of the sub-string whose characters can be used to form a palindrome of length K

Last Updated : 10 May, 2022
Improve
Improve
Like Article
Like
Save
Share
Report

Given a string str consisting of lowercase English letters and an integer K. The task is to find the minimum length of the sub-string whose characters can be used to form a palindrome of length K. If no such sub-string exists then print -1.
Examples: 
 

Input: str = “abcda”, k = 2 
Output:
In order to form a palindrome of length 2, both the occurrences of ‘a’ are required. 
Hence, the length of the required sub-string will be 5.
Input: str = “abcde”, k = 5 
Output: -1 
No palindromic string of length 5 can be formed from the characters of the given string. 
 

 

Approach: The idea is to use Binary Search. Minimum character needed to form a palindrome of length K is K. So, our search domain gets reduced to [K, length(str)]. Apply binary search in this range and find a sub-string of length X (K ? X ? length(S)) such that using some or all characters of this sub-string a palindromic string of size K can be formed. Minimum X which satisfies the given condition will be the required answer. If no  such sub-string is possible then print -1.
Below is the implementation of the above approach: 
 

C++




// C++ implementation of the approach
#include <bits/stdc++.h>
using namespace std;
 
// Function that returns true if
// a palindrome can be formed using
// exactly k characters
bool isPalindrome(int freq[], int k)
{
    // Variable to check if characters
    // with odd frequency are present
    int flag = 0;
 
    // Variable to store maximum length
    // of the palindrome that can be formed
    int length = 0;
 
    for (int i = 0; i < 26; i++) {
        if (freq[i] == 0)
            continue;
 
        else if (freq[i] == 1)
            flag = 1;
 
        else {
            if (freq[i] & 1)
                flag = 1;
            length += freq[i] / 2;
        }
    }
 
    // If k is odd
    if (k & 1) {
        if (2 * length + flag >= k)
            return true;
    }
 
    // If k is even
    else {
        if (2 * length >= k)
            return true;
    }
 
    // If palindrome of length
    // k cant be formed
    return false;
}
 
// Function that returns true if a palindrome
// of length k can be formed from a
// sub-string of length m
bool check(string str, int m, int k)
{
    // Stores frequency of characters
    // of a substring of length m
    int freq[26] = { 0 };
 
    for (int i = 0; i < m; i++)
        freq[str[i] - 'a']++;
 
    // If a palindrome can be
    // formed from a substring of
    // length m
    if (isPalindrome(freq, k))
        return true;
 
    // Check for all the substrings of
    // length m, if a palindrome of
    // length k can be formed
    for (int i = m; i < str.length(); i++) {
        freq[str[i - m] - 'a']--;
        freq[str[i] - 'a']++;
 
        if (isPalindrome(freq, k))
            return true;
    }
 
    // If no palindrome of length
    // k can be formed
    return false;
}
 
// Function to return the minimum length
// of the sub-string whose characters can be
// used to form a palindrome of length k
int find(string str, int n, int k)
{
    int l = k;
    int h = n;
 
    // To store the minimum length of the
    // sub-string that can be used to form
    // a palindrome of length k
    int ans = -1;
 
    while (l <= h) {
        int m = (l + h) / 2;
        if (check(str, m, k)) {
            ans = m;
            h = m - 1;
        }
        else
            l = m + 1;
    }
 
    return ans;
}
 
// Driver code
int main()
{
    string str = "abcda";
    int n = str.length();
    int k = 2;
    cout << find(str, n, k);
 
    return 0;
}


Java




// Java implementation of the approach
import java.util.*;
 
class GFG
{
 
// Function that returns true if
// a palindrome can be formed using
// exactly k characters
static boolean isPalindrome(int freq[], int k)
{
    // Variable to check if characters
    // with odd frequency are present
    int flag = 0;
 
    // Variable to store maximum length
    // of the palindrome that can be formed
    int length = 0;
 
    for (int i = 0; i < 26; i++)
    {
        if (freq[i] == 0)
            continue;
 
        else if (freq[i] == 1)
            flag = 1;
 
        else
        {
            if (freq[i] % 2 == 1)
                flag = 1;
            length += freq[i] / 2;
        }
    }
 
    // If k is odd
    if (k % 2 == 1)
    {
        if (2 * length + flag >= k)
            return true;
    }
 
    // If k is even
    else
    {
        if (2 * length >= k)
            return true;
    }
 
    // If palindrome of length
    // k cant be formed
    return false;
}
 
// Function that returns true if a palindrome
// of length k can be formed from a
// sub-string of length m
static boolean check(String str, int m, int k)
{
    // Stores frequency of characters
    // of a substring of length m
    int []freq = new int[26];
 
    for (int i = 0; i < m; i++)
        freq[str.charAt(i) - 'a']++;
 
    // If a palindrome can be
    // formed from a substring of
    // length m
    if (isPalindrome(freq, k))
        return true;
 
    // Check for all the substrings of
    // length m, if a palindrome of
    // length k can be formed
    for (int i = m; i < str.length(); i++)
    {
        freq[str.charAt(i-m) - 'a']--;
        freq[str.charAt(i) - 'a']++;
 
        if (isPalindrome(freq, k))
            return true;
    }
 
    // If no palindrome of length
    // k can be formed
    return false;
}
 
// Function to return the minimum length
// of the sub-string whose characters can be
// used to form a palindrome of length k
static int find(String str, int n, int k)
{
    int l = k;
    int h = n;
 
    // To store the minimum length of the
    // sub-string that can be used to form
    // a palindrome of length k
    int ans = -1;
 
    while (l <= h)
    {
        int m = (l + h) / 2;
        if (check(str, m, k))
        {
            ans = m;
            h = m - 1;
        }
        else
            l = m + 1;
    }
 
    return ans;
}
 
// Driver code
public static void main(String[] args)
{
    String str = "abcda";
    int n = str.length();
    int k = 2;
    System.out.println(find(str, n, k));
    }
}
 
// This code is contributed by Rajput-Ji


Python3




# Python 3 implementation of the approach
 
# Function that returns true if
# a palindrome can be formed using
# exactly k characters
def isPalindrome(freq, k):
     
    # Variable to check if characters
    # with odd frequency are present
    flag = 0
 
    # Variable to store maximum length
    # of the palindrome that can be formed
    length = 0
 
    for i in range(26):
        if (freq[i] == 0):
            continue
 
        elif (freq[i] == 1):
            flag = 1
 
        else:
            if (freq[i] & 1):
                flag = 1
            length += freq[i] // 2
 
    # If k is odd
    if (k & 1):
        if (2 * length + flag >= k):
            return True
 
    # If k is even
    else:
        if (2 * length >= k):
            return True
 
    # If palindrome of length
    # k cant be formed
    return False
 
# Function that returns true if a palindrome
# of length k can be formed from a
# sub-string of length m
def check(str, m, k):
     
    # Stores frequency of characters
    # of a substring of length m
    freq = [0 for i in range(26)]
 
    for i in range(m):
        freq[ord(str[i]) - ord('a')] += 1
 
    # If a palindrome can be
    # formed from a substring of
    # length m
    if (isPalindrome(freq, k)):
        return True
 
    # Check for all the substrings of
    # length m, if a palindrome of
    # length k can be formed
    for i in range(m, len(str), 1):
        freq[ord(str[i - m]) - ord('a')] -= 1
        freq[ord(str[i]) - ord('a')] += 1
 
        if (isPalindrome(freq, k)):
            return True
 
    # If no palindrome of length
    # k can be formed
    return False
 
# Function to return the minimum length
# of the sub-string whose characters can be
# used to form a palindrome of length k
def find(str, n, k):
    l = k
    h = n
 
    # To store the minimum length of the
    # sub-string that can be used to form
    # a palindrome of length k
    ans = -1
 
    while (l <= h):
        m = (l + h) // 2
        if (check(str, m, k)):
            ans = m
            h = m - 1
         
        else:
            l = m + 1
 
    return ans
 
# Driver code
if __name__ == '__main__':
    str = "abcda"
    n = len(str)
    k = 2
    print(find(str, n, k))
 
# This code is contributed by
# Surendra_Gangwar


C#




// C# implementation of the approach
using System;
 
class GFG
{
 
// Function that returns true if
// a palindrome can be formed using
// exactly k characters
static Boolean isPalindrome(int []freq, int k)
{
    // Variable to check if characters
    // with odd frequency are present
    int flag = 0;
 
    // Variable to store maximum length
    // of the palindrome that can be formed
    int length = 0;
 
    for (int i = 0; i < 26; i++)
    {
        if (freq[i] == 0)
            continue;
 
        else if (freq[i] == 1)
            flag = 1;
 
        else
        {
            if (freq[i] % 2 == 1)
                flag = 1;
            length += freq[i] / 2;
        }
    }
 
    // If k is odd
    if (k % 2 == 1)
    {
        if (2 * length + flag >= k)
            return true;
    }
 
    // If k is even
    else
    {
        if (2 * length >= k)
            return true;
    }
 
    // If palindrome of length
    // k cant be formed
    return false;
}
 
// Function that returns true if a palindrome
// of length k can be formed from a
// sub-string of length m
static Boolean check(String str, int m, int k)
{
    // Stores frequency of characters
    // of a substring of length m
    int []freq = new int[26];
 
    for (int i = 0; i < m; i++)
        freq[str[i] - 'a']++;
 
    // If a palindrome can be
    // formed from a substring of
    // length m
    if (isPalindrome(freq, k))
        return true;
 
    // Check for all the substrings of
    // length m, if a palindrome of
    // length k can be formed
    for (int i = m; i < str.Length; i++)
    {
        freq[str[i - m] - 'a']--;
        freq[str[i] - 'a']++;
 
        if (isPalindrome(freq, k))
            return true;
    }
 
    // If no palindrome of length
    // k can be formed
    return false;
}
 
// Function to return the minimum length
// of the sub-string whose characters can be
// used to form a palindrome of length k
static int find(String str, int n, int k)
{
    int l = k;
    int h = n;
 
    // To store the minimum length of the
    // sub-string that can be used to form
    // a palindrome of length k
    int ans = -1;
 
    while (l <= h)
    {
        int m = (l + h) / 2;
        if (check(str, m, k))
        {
            ans = m;
            h = m - 1;
        }
        else
            l = m + 1;
    }
 
    return ans;
}
 
// Driver code
public static void Main(String[] args)
{
    String str = "abcda";
    int n = str.Length;
    int k = 2;
    Console.WriteLine(find(str, n, k));
}
}
 
// This code is contributed by PrinciRaj1992


PHP




<?php
// PHP implementation of the approach
 
// Function that returns true if
// a palindrome can be formed using
// exactly k characters
function isPalindrome($freq, $k)
{
    // Variable to check if characters
    // with odd frequency are present
    $flag = 0;
 
    // Variable to store maximum length
    // of the palindrome that can be formed
    $length = 0;
 
    for ($i = 0; $i < 26; $i++)
    {
        if ($freq[$i] == 0)
            continue;
 
        else if ($freq[$i] == 1)
            $flag = 1;
 
        else
        {
            if ($freq[$i] & 1)
                $flag = 1;
                 
            $length += floor($freq[$i] / 2);
        }
    }
 
    // If k is odd
    if ($k & 1)
    {
        if (2 * $length + $flag >= $k)
            return true;
    }
 
    // If k is even
    else
    {
        if (2 * $length >= $k)
            return true;
    }
 
    // If palindrome of length
    // k cant be formed
    return false;
}
 
// Function that returns true if a palindrome
// of length k can be formed from a
// sub-string of length m
function check($str, $m, $k)
{
    // Stores frequency of characters
    // of a substring of length m
    $freq = array_fill(0, 26, 0);
 
    for ($i = 0; $i < $m; $i++)
        $freq[ord($str[$i]) - ord('a')]++;
 
    // If a palindrome can be
    // formed from a substring of
    // length m
    if (isPalindrome($freq, $k))
        return true;
 
    // Check for all the substrings of
    // length m, if a palindrome of
    // length k can be formed
    for ($i = $m; $i < strlen($str); $i++)
    {
        $freq[ord($str[$i - $m]) - ord('a')] -= 1;
        $freq[ord($str[$i]) - ord('a')] += 1;
 
        if (isPalindrome($freq, $k))
            return true;
    }
 
    // If no palindrome of length
    // k can be formed
    return false;
}
 
// Function to return the minimum length
// of the sub-string whose characters can be
// used to form a palindrome of length k
function find($str, $n, $k)
{
    $l = $k;
    $h = $n;
 
    // To store the minimum length of the
    // sub-string that can be used to form
    // a palindrome of length k
    $ans = -1;
 
    while ($l <= $h)
    {
        $m = floor(($l + $h) / 2);
        if (check($str, $m, $k))
        {
            $ans = $m;
            $h = $m - 1;
        }
        else
            $l = $m + 1;
    }
 
    return $ans;
}
 
// Driver code
$str = "abcda";
$n = strlen($str);
$k = 2;
 
echo find($str, $n, $k);
 
// This code is improved by Ryuga
?>


Javascript




<script>
    // Javascript implementation of the approach
     
    // Function that returns true if
    // a palindrome can be formed using
    // exactly k characters
    function isPalindrome(freq, k)
    {
     
        // Variable to check if characters
        // with odd frequency are present
        let flag = 0;
 
        // Variable to store maximum length
        // of the palindrome that can be formed
        let length = 0;
 
        for (let i = 0; i < 26; i++)
        {
            if (freq[i] == 0)
                continue;
 
            else if (freq[i] == 1)
                flag = 1;
 
            else
            {
                if (freq[i] % 2 == 1)
                    flag = 1;
                length += parseInt(freq[i] / 2, 10);
            }
        }
 
        // If k is odd
        if (k % 2 == 1)
        {
            if (2 * length + flag >= k)
                return true;
        }
 
        // If k is even
        else
        {
            if (2 * length >= k)
                return true;
        }
 
        // If palindrome of length
        // k cant be formed
        return false;
    }
 
    // Function that returns true if a palindrome
    // of length k can be formed from a
    // sub-string of length m
    function check(str, m, k)
    {
        // Stores frequency of characters
        // of a substring of length m
        let freq = new Array(26);
        freq.fill(0);
 
        for (let i = 0; i < m; i++)
            freq[str[i].charCodeAt() - 'a'.charCodeAt()]++;
 
        // If a palindrome can be
        // formed from a substring of
        // length m
        if (isPalindrome(freq, k))
            return true;
 
        // Check for all the substrings of
        // length m, if a palindrome of
        // length k can be formed
        for (let i = m; i < str.length; i++)
        {
            freq[str[i - m].charCodeAt() - 'a'.charCodeAt()]--;
            freq[str[i].charCodeAt() - 'a'.charCodeAt()]++;
 
            if (isPalindrome(freq, k))
                return true;
        }
 
        // If no palindrome of length
        // k can be formed
        return false;
    }
 
    // Function to return the minimum length
    // of the sub-string whose characters can be
    // used to form a palindrome of length k
    function find(str, n, k)
    {
        let l = k;
        let h = n;
 
        // To store the minimum length of the
        // sub-string that can be used to form
        // a palindrome of length k
        let ans = -1;
 
        while (l <= h)
        {
            let m = parseInt((l + h) / 2, 10);
            if (check(str, m, k))
            {
                ans = m;
                h = m - 1;
            }
            else
                l = m + 1;
        }
        return ans;
    }
     
    let str = "abcda";
    let n = str.length;
    let k = 2;
    document.write(find(str, n, k));
     
    // This code is contributed by divyeshrbadiya07.
</script>


Output: 

5

 



Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads