Palindrome Partitioning II In C,CPP,JAVA,PYTHON,C#,JS

Spread the love
Close-up of a laptop and tablet on a wooden desk, showcasing modern technology.

Problem Statement: Palindrome Partitioning II

Given a string s, you need to partition it such that every substring of the partition is a palindrome. Return the minimum number of cuts required to partition s such that every substring is a palindrome.

Example

Example 1:

Input: s = "aab" Output: 1
Explanation: The palindrome partitioning [“aa”, “b”] could be made with 1 cut.

Example 2:

Input: s = "a" Output: 0
Explanation: The string is already a palindrome, so no cuts are needed.

Example 3:

Input: s = "abac" Output: 1
Explanation: The palindrome partitioning [“aba”, “c”] could be made with 1 cut.

Approach and Algorithm

  1. Dynamic Programming (DP):
    • We will use two dynamic programming tables:
      • dp[i]: Represents the minimum number of cuts needed for the substring s[0...i].
      • palindrome[i][j]: A 2D table where palindrome[i][j] is True if s[i...j] is a palindrome, otherwise False.
  2. Filling palindrome[][]:
    • A single character is always a palindrome (palindrome[i][i] = True).
    • A two-character substring is a palindrome if both characters are the same.
    • For substrings of length greater than 2, s[i...j] is a palindrome if s[i] == s[j] and palindrome[i+1][j-1] is also a palindrome.
  3. Filling dp[]:
    • Start with dp[i] = i (maximum cuts required: cut each character).
    • For each index i, iterate over all possible previous indices j, if s[j+1...i] is a palindrome, then update dp[i] = min(dp[i], dp[j] + 1).
  4. Time Complexity:
    • Constructing the palindrome[][] table takes O(n^2).
    • Filling the dp[] table also takes O(n^2).
    • Thus, the overall time complexity is O(n^2), where n is the length of the string.
  5. Space Complexity:
    • The space complexity is O(n^2) due to the palindrome[][] table.

Code in Multiple Languages

C

#include <stdio.h>
#include <string.h>
#include <stdbool.h>

#define MAX 1000

int minCut(char* s) {
int n = strlen(s);
bool palindrome[n][n];
int dp[n+1];
for (int i = 0; i <= n; i++) dp[i] = i - 1;

memset(palindrome, 0, sizeof(palindrome));

for (int i = n - 1; i >= 0; i--) {
for (int j = i; j < n; j++) {
palindrome[i][j] = (s[i] == s[j]) && (j - i <= 2 || palindrome[i + 1][j - 1]);
}
}

for (int i = 0; i < n; i++) {
if (palindrome[0][i]) dp[i] = 0;
else {
for (int j = 0; j < i; j++) {
if (palindrome[j + 1][i]) dp[i] = (dp[i] < dp[j] + 1) ? dp[i] : dp[j] + 1;
}
}
}

return dp[n - 1];
}

int main() {
char s[] = "aab";
printf("%d\n", minCut(s));
return 0;
}

C++

#include <iostream>
#include <vector>
#include <cstring>
using namespace std;

int minCut(string s) {
int n = s.length();
vector<vector<bool>> palindrome(n, vector<bool>(n, false));
vector<int> dp(n + 1, n);

dp[0] = -1; // no cut needed for empty string

for (int i = n - 1; i >= 0; i--) {
for (int j = i; j < n; j++) {
palindrome[i][j] = (s[i] == s[j]) && (j - i <= 2 || palindrome[i + 1][j - 1]);
}
}

for (int i = 0; i < n; i++) {
if (palindrome[0][i]) dp[i] = 0;
else {
for (int j = 0; j < i; j++) {
if (palindrome[j + 1][i]) dp[i] = min(dp[i], dp[j] + 1);
}
}
}

return dp[n - 1];
}

int main() {
string s = "aab";
cout << minCut(s) << endl;
return 0;
}

Java

public class PalindromePartitioning {
public static int minCut(String s) {
int n = s.length();
boolean[][] palindrome = new boolean[n][n];
int[] dp = new int[n + 1];
for (int i = 0; i <= n; i++) dp[i] = i - 1;

for (int i = n - 1; i >= 0; i--) {
for (int j = i; j < n; j++) {
palindrome[i][j] = (s.charAt(i) == s.charAt(j)) && (j - i <= 2 || palindrome[i + 1][j - 1]);
}
}

for (int i = 0; i < n; i++) {
if (palindrome[0][i]) dp[i] = 0;
else {
for (int j = 0; j < i; j++) {
if (palindrome[j + 1][i]) dp[i] = Math.min(dp[i], dp[j] + 1);
}
}
}

return dp[n - 1];
}

public static void main(String[] args) {
String s = "aab";
System.out.println(minCut(s));
}
}

Python

def minCut(s: str) -> int:
n = len(s)
palindrome = [[False] * n for _ in range(n)]
dp = [i for i in range(-1, n)]

for i in range(n - 1, -1, -1):
for j in range(i, n):
palindrome[i][j] = (s[i] == s[j]) and (j - i <= 2 or palindrome[i + 1][j - 1])

for i in range(n):
if palindrome[0][i]:
dp[i] = 0
else:
for j in range(i):
if palindrome[j + 1][i]:
dp[i] = min(dp[i], dp[j] + 1)

return dp[n - 1]

# Example
s = "aab"
print(minCut(s)) # Output: 1

C#

using System;

public class PalindromePartitioning {
public static int MinCut(string s) {
int n = s.Length;
bool[,] palindrome = new bool[n, n];
int[] dp = new int[n + 1];
for (int i = 0; i <= n; i++) dp[i] = i - 1;

for (int i = n - 1; i >= 0; i--) {
for (int j = i; j < n; j++) {
palindrome[i, j] = (s[i] == s[j]) && (j - i <= 2 || palindrome[i + 1, j - 1]);
}
}

for (int i = 0; i < n; i++) {
if (palindrome[0, i]) dp[i] = 0;
else {
for (int j = 0; j < i; j++) {
if (palindrome[j + 1, i]) dp[i] = Math.Min(dp[i], dp[j] + 1);
}
}
}

return dp[n - 1];
}

public static void Main() {
string s = "aab";
Console.WriteLine(MinCut(s)); // Output: 1
}
}

JavaScript

function minCut(s) {
const n = s.length;
const palindrome = Array.from(Array(n), () => Array(n).fill(false));
const dp = Array.from({ length: n + 1 }, (_, i) => i - 1);

for (let i = n - 1; i >= 0; i--) {
for (let j = i; j < n; j++) {
palindrome[i][j] = (s[i] === s[j]) && (j - i <= 2 || palindrome[i + 1][j - 1]);
}
}

for (let i = 0; i < n; i++) {
if (palindrome[0][i]) dp[i] = 0;
else {
for (let j = 0; j < i; j++) {
if (palindrome[j + 1][i]) dp[i] = Math.min(dp[i], dp[j] + 1);
}
}
}

return dp[n - 1];
}

console.log(minCut("aab")); // Output: 1

Summary

  • Time Complexity: O(n^2), where n is the length of the string.
  • Space Complexity: O(n^2) due to the use of a 2D palindrome[][] table.
  • Algorithm: Use dynamic programming to calculate the minimum cuts needed by iterating over the string, checking if substrings are palindromes and updating the DP table accordingly.