题目:
题解:
- 暴力搜索所有子序列
- 判断子序列是否递增
- 判断子序列是否重复
class Solution {
private List<List<Integer>> resultList = new ArrayList<>();
private LinkedList<Integer> pathList = new LinkedList<>();
private Set<String> existSubSet = new HashSet<>();
public List<List<Integer>> findSubsequences(int[] nums) {
for (int i = 2; i <= nums.length; i++) {
dfsForSubsets(nums, i, 0);
}
return resultList;
}
private void dfsForSubsets(int[] nums, int n, int start) {
if (pathList.size() == n && isIncremental(pathList)) {
String uniqueKey = generateUniqueKey(pathList);
if (!existSubSet.contains(uniqueKey)) {
resultList.add(new ArrayList<>(pathList));
existSubSet.add(uniqueKey);
}
return;
}
for (int i = start; i < nums.length; i++) {
pathList.add(nums[i]);
dfsForSubsets(nums, n, i+1);
pathList.removeLast();
}
}
private boolean isIncremental(LinkedList<Integer> list) {
for (int i = 1; i < list.size(); i++) {
if (list.get(i-1) > list.get(i)) {
return false;
}
}
return true;
}
private String generateUniqueKey(List<Integer> list) {
return list.stream().map(String::valueOf).collect(Collectors.joining("-"));
}
}
剪枝:在搜索的时候判断当前元素是否大于等于前一元素,如果小于前一元素就不必再继续搜索。
class Solution {
private List<List<Integer>> resultList = new ArrayList<>();
private LinkedList<Integer> pathList = new LinkedList<>();
private Set<String> existSubSet = new HashSet<>();
public List<List<Integer>> findSubsequences(int[] nums) {
for (int i = 2; i <= nums.length; i++) {
dfsForSubsets(nums, i, 0);
}
return resultList;
}
private void dfsForSubsets(int[] nums, int n, int start) {
if (pathList.size() == n) {
String uniqueKey = generateUniqueKey(pathList);
if (!existSubSet.contains(uniqueKey)) {
resultList.add(new ArrayList<>(pathList));
existSubSet.add(uniqueKey);
}
return;
}
for (int i = start; i < nums.length; i++) {
if (!isGreaterThanPre(nums[i], pathList.peekLast())) {
continue;
}
pathList.add(nums[i]);
dfsForSubsets(nums, n, i+1);
pathList.removeLast();
}
}
private boolean isGreaterThanPre(Integer current, Integer pre) {
if (pre == null) {
return true;
}
return current.compareTo(pre) >= 0;
}
private String generateUniqueKey(List<Integer> list) {
return list.stream().map(String::valueOf).collect(Collectors.joining("-"));
}
}
去重:搜索每一层子序列时,使用哈希表记录已出现的元素,如果当前层已使用过该元素,后面搜索时需要跳过,从而实现去重目的。
public class FindSubsequences {
private List<List<Integer>> resultList = new ArrayList<>();
private LinkedList<Integer> pathList = new LinkedList<>();
public List<List<Integer>> findSubsequences(int[] nums) {
for (int i = 2; i <= nums.length; i++) {
dfsForSubsets(nums, i, 0);
}
return resultList;
}
private void dfsForSubsets(int[] nums, int n, int start) {
if (pathList.size() == n) {
resultList.add(new ArrayList<>(pathList));
return;
}
Set<Integer> usedSet = new HashSet<>();
for (int i = start; i < nums.length; i++) {
if (usedSet.contains(nums[i]) || !isGreaterThanPre(nums[i], pathList.peekLast())) {
continue;
}
pathList.add(nums[i]);
usedSet.add(nums[i]);
dfsForSubsets(nums, n, i+1);
pathList.removeLast();
}
}
private boolean isGreaterThanPre(Integer current, Integer pre) {
if (pre == null) {
return true;
}
return current.compareTo(pre) >= 0;
}
}
时间复杂度:O()