diff --git a/src/PalindromePartitioning.java b/src/PalindromePartitioning.java new file mode 100644 index 00000000..37410bc1 --- /dev/null +++ b/src/PalindromePartitioning.java @@ -0,0 +1,88 @@ +import java.util.ArrayList; +import java.util.List; +/* + * TIME COMPLEXITY: + * Exponential in worst case (many partitions, e.g., "aaaa..."). + * Plus palindrome checks which cost up to O(n) each. + * + * SPACE COMPLEXITY: + * Recursion depth O(n) + output size. + */ + +public class PalindromePartitioning { + List> res; + + public List> partition(String s) { + this.res = new ArrayList<>(); + + // Pick ONE: + forLoopHelper(s, 0, new ArrayList<>()); // for-loop based + //chooseNoChooseHelper(s, 0, 0, new ArrayList<>()); // choose / no-choose based + + return res; + } + + // FOR-LOOP BASED + public void forLoopHelper(String s, int start, List path) { + if (start == s.length()) { + res.add(new ArrayList<>(path)); + return; + } + + for (int end = start; end < s.length(); end++) { + String sub = s.substring(start, end + 1); + if (isPalindrome(sub)) { + path.add(sub); // choose + forLoopHelper(s, end + 1, path); // recurse + path.remove(path.size() - 1); // backtrack + } + } + } + + // CHOOSE / NO-CHOOSE BASED + // State: (start, end) + // - noChoose: extend end + // - choose: cut at [start..end] if palindrome, then restart at next index + public void chooseNoChooseHelper(String s, int start, int end, List path) { + // If we've partitioned the whole string + if (start == s.length()) { + res.add(new ArrayList<>(path)); + return; + } + + // If end reached beyond string, cannot extend further + if (end == s.length()) return; + + // NO-CHOOSE: don't cut yet, extend the substring + chooseNoChooseHelper(s, start, end + 1, path); + + // CHOOSE: cut here if palindrome + String sub = s.substring(start, end + 1); + if (isPalindrome(sub)) { + path.add(sub); + // next substring starts at end+1; end resets to end+1 + chooseNoChooseHelper(s, end + 1, end + 1, path); + path.remove(path.size() - 1); // backtrack + } + } + + private boolean isPalindrome(String str) { + int l = 0, r = str.length() - 1; + while (l < r) { + if (str.charAt(l) != str.charAt(r)) return false; + l++; + r--; + } + return true; + } + // TESTS + public static void main(String[] args) { + PalindromePartitioning sol = new PalindromePartitioning(); + System.out.println("For-loop based: " + sol.partition("aab")); + + PalindromePartitioning sol2 = new PalindromePartitioning(); + sol2.res = new ArrayList<>(); + sol2.chooseNoChooseHelper("aab", 0, 0, new ArrayList<>()); + System.out.println("Choose/No-Choose: " + sol2.res); + } +} diff --git a/src/Subsets.java b/src/Subsets.java new file mode 100644 index 00000000..847b7bb6 --- /dev/null +++ b/src/Subsets.java @@ -0,0 +1,72 @@ +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/* + * Subsets (Power set) + * + * TIME COMPLEXITY: + * - There are 2^n subsets. + * SPACE COMPLEXITY: + * - Recursion depth: O(n) + */ +public class Subsets { + + private List> result; + + public List> subsets(int[] nums) { + result = new ArrayList<>(); + + // Pick ONE approach: + //helperChooseSkip(nums, 0, new ArrayList<>()); // choose/skip + forLoopHelper(nums, 0, new ArrayList<>()); // for-loop style + + return result; + } + // Choose / Skip recursion + private void helperChooseSkip(int[] nums, int start, ArrayList path) { + if (start == nums.length) { + result.add(new ArrayList<>(path)); + return; + } + + // no choose + helperChooseSkip(nums, start + 1, path); + + // choose + path.add(nums[start]); + helperChooseSkip(nums, start + 1, path); + + // backtrack + path.remove(path.size() - 1); + } + // For-loop backtracking (standard) + // Add path at EVERY call so all subset sizes are included + private void forLoopHelper(int[] nums, int start, List path) { + // Add current subset (including empty subset when path is empty) + result.add(new ArrayList<>(path)); + + for (int i = start; i < nums.length; i++) { + List newPath = new ArrayList<>(path); // copy (no backtracking needed) + newPath.add(nums[i]);// choose + forLoopHelper(nums, i + 1, newPath); // move forward + } + } + + // Tests + public static void main(String[] args) { + Subsets sol = new Subsets(); + + int[] nums1 = {1, 2, 3}; + System.out.println("Input: " + Arrays.toString(nums1)); + System.out.println("Output: " + sol.subsets(nums1)); + + int[] nums2 = {}; + System.out.println("\nInput: " + Arrays.toString(nums2)); + System.out.println("Output: " + sol.subsets(nums2)); + + int[] nums3 = {0}; + System.out.println("\nInput: " + Arrays.toString(nums3)); + System.out.println("Output: " + sol.subsets(nums3)); + } +}