Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# Problem β€” Palindrome Partitioning II

## Problem Statement
Given a string `s`, partition `s` such that every substring of the partition is a **palindrome**.
Return the **minimum number of cuts** needed to partition `s` in this way.


## Key Insights & Approach

1. **Dynamic Programming over string indices**
- Let `DP[i]` = minimum number of cuts needed for substring `s[0..i]`.
- Transition: for each `j < i`, if `s[j+1..i]` is a palindrome,
`DP[i] = min(DP[i], DP[j] + 1)`.
- If `s[0..i]` itself is a palindrome β†’ `DP[i] = 0`.

2. **Palindrome checking optimization**
- Precompute a **2D boolean table** `isPalindrome[i][j]` to check if `s[i..j]` is palindrome in O(1).
- `isPalindrome[i][j] = true` if `s[i] == s[j]` and (`j - i <= 2` or `isPalindrome[i+1][j-1] == true`).

3. **Final answer**
- `DP[n-1]` gives the **minimum number of cuts** for the entire string `s`.



## Example Cases

| Example | Input | Output | Explanation |
|-------- |------------|--------|------------------------------------------------|
| 1 | `"aab"` | `1` | Partition: `"aa" | "b"` |
| 2 | `"a"` | `0` | Single character is palindrome β†’ no cut needed |
| 3 | `"abccba"` | `0` | The whole string is palindrome β†’ no cut needed |
| 4 | `"abbab"` | `1` | Partition: `"abba" | "b"` |

---

## Time & Space Complexity

| Metric | Complexity | Reasoning |
|-----------|------------|--------------------------------------------------------------------|
| **Time** | O(nΒ²) | Precompute palindrome table O(nΒ²) + DP over n with inner loop O(n) |
| **Space** | O(nΒ²) | 2D table for palindrome check + 1D DP array |

---


### Notes

- This problem is a **classic string DP / interval DP** problem.
- Precomputing the palindrome table allows for O(1) palindrome checks inside the DP transition.
- Keep the solution **atomic** and modular if you plan to use in multiple related problems.
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#include<bits/stdc++.h>
using namespace std;

class Solution {
public:
int minCut(string s) {
// If the string is empty, return 0 cuts.
if (s.empty()) return 0;

int n = s.size();

// isPalindrome[i][j] indicates whether substring s[i...j] is a palindrome
vector<vector<bool>> isPalindrome(n, vector<bool>(n, true));

// Build the palindrome lookup table using dynamic programming
// Start from the end of string and work backwards
for (int start = n - 1; start >= 0; --start) {
for (int end = start + 1; end < n; ++end) {
// A substring is palindrome if:
// 1. First and last characters match
// 2. Inner substring is also a palindrome (or length <= 2)
isPalindrome[start][end] = (s[start] == s[end]) && isPalindrome[start + 1][end - 1];
}
}

// minCuts[i] represents minimum cuts needed for substring s[0...i]
vector<int> minCuts(n);

// Initialize: worst case is to cut between every character
for (int i = 0; i < n; ++i) {
minCuts[i] = i; // Maximum i cuts needed for string of length i+1
}

// Calculate minimum cuts for each position
for (int end = 1; end < n; ++end) {
for (int start = 0; start <= end; ++start) {
// If s[start...end] is a palindrome
if (isPalindrome[start][end]) {
if (start == 0) {
// Entire substring from beginning is palindrome, no cuts needed
minCuts[end] = 0;
} else {
// Add one cut after position (start-1)
minCuts[end] = min(minCuts[end], minCuts[start - 1] + 1);
}
}
}
}

// Return minimum cuts for entire string
return minCuts[n - 1];
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
class Solution
{
public int minCut(String s)
{
// If the string is empty, return 0 cuts.
if (s.length() == 0) return 0;

int n = s.length();

// isPalindrome[i][j] indicates whether substring s[i...j] is a palindrome
boolean[][] isPalindrome = new boolean[n][n];

// Initialize all entries as true
for (boolean[] row : isPalindrome)
{
Arrays.fill(row, true);
}

// Build palindrome table using dynamic programming
// Start from the end and work backwards to ensure smaller subproblems are solved first
for (int start = n - 1; start >= 0; start--)
{
for (int end = start + 1; end < n; end++)
{
// A substring is a palindrome if:
// 1. First and last characters match
// 2. The substring between them is also a palindrome
isPalindrome[start][end] = (s.charAt(start) == s.charAt(end))
&& isPalindrome[start + 1][end - 1];
}
}

// minCuts[i] represents the minimum cuts needed for substring s[0...i]
int[] minCuts = new int[n];

// Initialize with worst case: cut after every character
for (int i = 0; i < n; i++)
{
minCuts[i] = i;
}

// Calculate minimum cuts for each position
for (int end = 1; end < n; end++)
{
// Check all possible starting positions for the last palindrome partition
for (int start = 0; start <= end; start++)
{
// If s[start...end] is a palindrome
if (isPalindrome[start][end])
{
// If the palindrome starts at index 0, no cuts needed for this substring
// Otherwise, we need 1 cut plus the minimum cuts for s[0...start-1]
minCuts[end] = Math.min(minCuts[end],
start > 0 ? 1 + minCuts[start - 1] : 0);
}
}
}

// Return minimum cuts needed for the entire string
return minCuts[n - 1];
}
}