diff --git a/java/Backtracking/CombinationsOfSumK.java b/java/Backtracking/CombinationsOfSumK.java new file mode 100644 index 0000000..83b05b1 --- /dev/null +++ b/java/Backtracking/CombinationsOfSumK.java @@ -0,0 +1,33 @@ +import java.util.ArrayList; +import java.util.List; + +public class CombinationsOfSumK { + public List> combinationsOfSumK(int[] nums, int target) { + List> res = new ArrayList<>(); + dfs(new ArrayList<>(), 0, nums, target, res); + return res; + } + + private void dfs(List combination, int startIndex, int[] nums, int target, List> res) { + // Termination condition: If the target is equal to 0, we found a combination + // that sums to 'k'. + if (target == 0) { + res.add(new ArrayList<>(combination)); + return; + } + // Termination condition: If the target is less than 0, no more valid + // combinations can be created by adding it to the current combination. + if (target < 0) { + return; + } + // Starting from start_index, explore all combinations after adding nums[i]. + for (int i = startIndex; i < nums.length; i++) { + // Add the current number to create a new combination. + combination.add(nums[i]); + // Recursively explore all paths that branch from this new combination. + dfs(combination, i, nums, target - nums[i], res); + // Backtrack by removing the number we just added. + combination.remove(combination.size() - 1); + } + } +} diff --git a/java/Backtracking/FindAllPermutations.java b/java/Backtracking/FindAllPermutations.java new file mode 100644 index 0000000..cfaf144 --- /dev/null +++ b/java/Backtracking/FindAllPermutations.java @@ -0,0 +1,34 @@ +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +public class FindAllPermutations { + public List> findAllPermutations(int[] nums) { + List> res = new ArrayList<>(); + backtrack(nums, new ArrayList<>(), new HashSet<>(), res); + return res; + } + + private void backtrack(int[] nums, List candidate, Set used, List> res) { + // If the current candidate is a complete permutation, add it to the + // result. + if (candidate.size() == nums.length) { + res.add(new ArrayList<>(candidate)); + return; + } + for (int num : nums) { + if (!used.contains(num)) { + // Add 'num' to the current permutation and mark it as used. + candidate.add(num); + used.add(num); + // Recursively explore all branches using the updated + // permutation candidate. + backtrack(nums, candidate, used, res); + // Backtrack by reversing the changes made. + candidate.remove(candidate.size() - 1); + used.remove(num); + } + } + } +} diff --git a/java/Backtracking/FindAllSubsets.java b/java/Backtracking/FindAllSubsets.java new file mode 100644 index 0000000..50213ba --- /dev/null +++ b/java/Backtracking/FindAllSubsets.java @@ -0,0 +1,27 @@ +import java.util.ArrayList; +import java.util.List; + +public class FindAllSubsets { + public List> findAllSubsets(int[] nums) { + List> res = new ArrayList<>(); + backtrack(0, new ArrayList<>(), nums, res); + return res; + } + + private void backtrack(int i, List currSubset, int[] nums, List> res) { + // Base case: if all elements have been considered, add the + // current subset to the output. + if (i == nums.length) { + res.add(new ArrayList<>(currSubset)); + return; + } + // Include the current element and recursively explore all paths + // that branch from this subset. + currSubset.add(nums[i]); + backtrack(i + 1, currSubset, nums, res); + // Exclude the current element and recursively explore all paths + // that branch from this subset. + currSubset.remove(currSubset.size() - 1); + backtrack(i + 1, currSubset, nums, res); + } +} diff --git a/java/Backtracking/NQueens.java b/java/Backtracking/NQueens.java new file mode 100644 index 0000000..74a3998 --- /dev/null +++ b/java/Backtracking/NQueens.java @@ -0,0 +1,41 @@ +import java.util.HashSet; +import java.util.Set; + +public class NQueens { + int res = 0; + + public int nQueens(int n) { + dfs(0, new HashSet<>(), new HashSet<>(), new HashSet<>(), n); + return res; + } + + private void dfs(int r, Set diagonalsSet, Set antiDiagonalsSet, Set colsSet, int n) { + // Termination condition: If we have reached the end of the rows, + // we've placed all 'n' queens. + if (r == n) { + res++; + return; + } + for (int c = 0; c < n; c++) { + int currDiagonal = r - c; + int currAntiDiagonal = r + c; + // If there are queens on the current column, diagonal or + // anti-diagonal, skip this square. + if (colsSet.contains(c) || diagonalsSet.contains(currDiagonal) || antiDiagonalsSet.contains(currAntiDiagonal)) { + continue; + } + // Place the queen by marking the current column, diagonal, and + // anti−diagonal as occupied. + colsSet.add(c); + diagonalsSet.add(currDiagonal); + antiDiagonalsSet.add(currAntiDiagonal); + // Recursively move to the next row to continue placing queens. + dfs(r + 1, diagonalsSet, antiDiagonalsSet, colsSet, n); + // Backtrack by removing the current column, diagonal, and + // anti−diagonal from the hash sets. + colsSet.remove(c); + diagonalsSet.remove(currDiagonal); + antiDiagonalsSet.remove(currAntiDiagonal); + } + } +} \ No newline at end of file diff --git a/java/Backtracking/PhoneKeypadCombinations.java b/java/Backtracking/PhoneKeypadCombinations.java new file mode 100644 index 0000000..b77da96 --- /dev/null +++ b/java/Backtracking/PhoneKeypadCombinations.java @@ -0,0 +1,42 @@ +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class PhoneKeypadCombinations { + public List phoneKeypadCombinations(String digits) { + Map keypadMap = new HashMap<>(); + keypadMap.put('2', "abc"); + keypadMap.put('3', "def"); + keypadMap.put('4', "ghi"); + keypadMap.put('5', "jkl"); + keypadMap.put('6', "mno"); + keypadMap.put('7', "pqrs"); + keypadMap.put('8', "tuv"); + keypadMap.put('9', "wxyz"); + List result = new ArrayList<>(); + backtrack(0, new ArrayList<>(), digits, keypadMap, result); + return result; + } + + private void backtrack(int i, List currCombination, String digits, Map keypadMap, List result) { + // Termination condition: if all digits have been considered, add the + // current combination to the output list. + if (currCombination.size() == digits.length()) { + StringBuilder sb = new StringBuilder(); + for (char c: currCombination) { + sb.append(c); + } + result.add(sb.toString()); + return; + } + for (char letter: keypadMap.get(digits.charAt(i)).toCharArray()) { + // Add the current letter. + currCombination.add(letter); + // Recursively explore all paths that branch from this combination. + backtrack(i + 1, currCombination, digits, keypadMap, result); + // Backtrack by removing the letter we just added. + currCombination.remove(currCombination.size() - 1); + } + } +}