privatevoidbacktracking(int[] nums, int startIndex) {
// as the minimum valid sequence contains at least two elements, thus // add those path whose length is greater than 1 if (path.size() > 1) { set.add(newLinkedList<>(path)); }
for (inti= startIndex; i < nums.length; i++) {
/* * actually this kind of remove duplicate is non-sense * as it only function when the given array is like [4 6 7 7] * if it is changed to [4 7 6 7] it still causes duplicates */
// rule out duplicate elements in same level if (i > startIndex && nums[i] == nums[i - 1]){ continue; }
// we are not sure whether this time of calling would // add a element or not ,thus record the previous size intrecordPathSize= path.size();
// for the topest level elements, directly add it if (path.size() == 0) { path.add(nums[i]); }elseif (path.size() > 0) { // if current element is greater and equals to last added element if ( nums[i] >= path.get(path.size() - 1)){ path.add(nums[i]); } }
// recursively call this func backtracking(nums, i + 1);
// if we do add elements into the path, remove it if (path.size() > recordPathSize) { path.remove(path.size() - 1); } } } }
private List<List<Integer>> ans = newLinkedList<>(); private List<Integer> path = newLinkedList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
backtracking(nums, 0); return ans;
}
privatevoidbacktracking(int[] nums, int startIndex) { // when traversing all the tree, add those path whose length is equal // and greater than 2 if (path.size() > 1) { ans.add(newLinkedList<>(path)); }
// number [-100, 100] maps to array ranged [0, 200] // records whether this num has been used int[] used = newint[201];
for (inti= startIndex; i < nums.length; i++) {
// if path is not empty and elment is less than last num or it has been used, skip if ( (!path.isEmpty() && nums[i] < path.get(path.size() - 1)) || used[nums[i] + 100] == 1 ) { continue; }
path.add(nums[i]); used[nums[i] + 100] = 1;
backtracking(nums, i + 1);
// avoid uncertain backtrack, ensure that whichever approach here must be successful add path.remove(path.size() - 1); } } }
public List<List<Integer>> permuteUnique(int[] nums) { Arrays.sort(nums); used = newboolean[nums.length]; backtracking(nums); return ans; }
privatevoidbacktracking(int[] nums) { // exits if (path.size() == nums.length) { ans.add(newLinkedList<>(path)); } for (inti=0; i < nums.length; i++) {
// here is pruning but in a branch level // as used[i - 1] = true means we are in the branch of nums[i -1] // which is less efficient than directly remove this whole branch
// if(used[i] || (i > 0 && used[i - 1] && nums[i] == nums[i - 1])) { // continue; // }; // here is the pruning in level level (the same level on the tree) if(used[i] || (i > 0 && !used[i - 1] && nums[i] == nums[i - 1])) { continue; };