Welcome to Subscribe On Youtube

Formatted question description: https://leetcode.ca/all/491.html

491. Increasing Subsequences (Medium)

Given an integer array, your task is to find all the different possible increasing subsequences of the given array, and the length of an increasing subsequence should be at least 2 .

Example:

Input: [4, 6, 7, 7]
Output: [[4, 6], [4, 7], [4, 6, 7], [4, 6, 7, 7], [6, 7], [6, 7, 7], [7,7], [4,7,7]]

Note:

  1. The length of the given array will not exceed 15.
  2. The range of integer in the given array is [-100,100].
  3. The given array may contain duplicates, and two equal integers should also be considered as a special case of increasing sequence.

Solution 1

Use a set<vector<int>> ans to hold the results and to keep the sub-sequences being unique, which initially hold one empty vector<int>.

For each number in nums, for each vector seq in ans, if the number is greater or equal to the last number in seq, seq concatenated with the number should be inserted into ans.

Finally, remove all the vectors holding only one number from ans.

// OJ: https://leetcode.com/problems/increasing-subsequences
// Time: O(2^N)
// Space: O(2^N)
class Solution {
public:
  vector<vector<int>> findSubsequences(vector<int>& nums) {
    set<vector<int>> ans;
    ans.insert(vector<int>());
    for (int i = 0; i < nums.size(); ++i) {
      set<vector<int>> newAns = ans;
      for (auto it = ans.begin(); it != ans.end(); ++it) {
        vector<int> seq = *it;
        if (seq.size() && nums[i] < seq.back()) continue;
        seq.push_back(nums[i]);
        newAns.insert(seq);
      }
      ans = newAns;
    }
    for (auto it = ans.begin(); it != ans.end(); ) {
      if (it->size() <= 1) it = ans.erase(it);
      else ++it;
    }
    return vector<vector<int>>(ans.begin(), ans.end());
  }
};

Solution 2. DFS

Use a set<vector<int>> s to hold the results and to keep the sub-sequences being unique.

DFS starts at index start (being 0 at the first call). For each number indexed at/after start, attempt to add it into the sub-sequence.

Add any subsequences of length greater than 1.

// OJ: https://leetcode.com/problems/permutations-ii
// Time: O(2^N)
// Space: O(2^N)
class Solution {
private:
  set<vector<int>> s;
  void dfs(vector<int> &nums, int start, vector<int> &seq) {
    if (seq.size() > 1) s.insert(seq);
    for (int i = start; i < nums.size(); ++i) {
      if (seq.size() && nums[i] < seq.back()) continue;
      seq.push_back(nums[i]);
      dfs(nums, i + 1, seq);
      seq.pop_back();
    }
  }
public:
  vector<vector<int>> findSubsequences(vector<int>& nums) {
    vector<int> seq;
    dfs(nums, 0, seq);
    return vector<vector<int>>(s.begin(), s.end());
  }
};

Solution 3. DFS

set<vector<int>> is time-consuming when comparing the items. To remove it, consider the fact that, in solution 2, for one DFS call, if one number is visited already, the following occurrance of that number should be omitted. To achieve it, unordered_set<int> is enough.

// OJ: https://leetcode.com/problems/permutations-ii
// Time: O(2^N)
// Space: O(N)
class Solution {
private:
  vector<vector<int>> ans;
  void dfs(vector<int> &nums, int start, vector<int> &seq) {
    if (start == nums.size()) return;
    unordered_set<int> visited;
    for (int i = start; i < nums.size(); ++i) {
      int n = nums[i];
      if (visited.count(n) || (seq.size() && seq.back() > n)) continue;
      visited.insert(n);
      seq.push_back(n);
      if (seq.size() > 1) ans.push_back(seq);
      dfs(nums, i + 1, seq);
      seq.pop_back();
    }
  }
public:
  vector<vector<int>> findSubsequences(vector<int>& nums) {
    vector<int> seq;
    dfs(nums, 0, seq);
    return ans;
  }
};
  • class Solution {
        public List<List<Integer>> findSubsequences(int[] nums) {
            List<List<Integer>> increasingSubsequences = new ArrayList<List<Integer>>();
            Set<String> increasingSubsequencesSet = new HashSet<String>();
            Queue<List<Integer>> subsequencesQueue = new LinkedList<List<Integer>>();
            Queue<Integer> indicesQueue = new LinkedList<Integer>();
            int length = nums.length;
            for (int i = 0; i < length - 1; i++) {
                for (int j = i + 1; j < length; j++) {
                    if (nums[i] <= nums[j]) {
                        List<Integer> subsequence = new ArrayList<Integer>();
                        subsequence.add(nums[i]);
                        subsequence.add(nums[j]);
                        String subsequenceStr = subsequence.toString();
                        if (increasingSubsequencesSet.add(subsequenceStr))
                            increasingSubsequences.add(subsequence);
                        subsequencesQueue.offer(subsequence);
                        indicesQueue.offer(j);
                    }
                }
            }
            while (!subsequencesQueue.isEmpty()) {
                List<Integer> subsequence = subsequencesQueue.poll();
                int index = indicesQueue.poll();
                int prevNum = nums[index];
                for (int i = index + 1; i < length; i++) {
                    int num = nums[i];
                    if (prevNum <= num) {
                        List<Integer> newSubsequence = new ArrayList<Integer>();
                        newSubsequence.addAll(subsequence);
                        newSubsequence.add(num);
                        String subsequenceStr = newSubsequence.toString();
                        if (increasingSubsequencesSet.add(subsequenceStr))
                            increasingSubsequences.add(newSubsequence);
                        subsequencesQueue.offer(newSubsequence);
                        indicesQueue.offer(i);
                    }
                }
            }
            return increasingSubsequences;
        }
    }
    
    ############
    
    class Solution {
        private int[] nums;
        private List<List<Integer>> ans;
    
        public List<List<Integer>> findSubsequences(int[] nums) {
            this.nums = nums;
            ans = new ArrayList<>();
            dfs(0, -1000, new ArrayList<>());
            return ans;
        }
    
        private void dfs(int u, int last, List<Integer> t) {
            if (u == nums.length) {
                if (t.size() > 1) {
                    ans.add(new ArrayList<>(t));
                }
                return;
            }
            if (nums[u] >= last) {
                t.add(nums[u]);
                dfs(u + 1, nums[u], t);
                t.remove(t.size() - 1);
            }
            if (nums[u] != last) {
                dfs(u + 1, last, t);
            }
        }
    }
    
  • // OJ: https://leetcode.com/problems/increasing-subsequences
    // Time: O(2^N)
    // Space: O(2^N)
    class Solution {
    public:
      vector<vector<int>> findSubsequences(vector<int>& nums) {
        set<vector<int>> ans;
        ans.insert(vector<int>());
        for (int i = 0; i < nums.size(); ++i) {
          set<vector<int>> newAns = ans;
          for (auto it = ans.begin(); it != ans.end(); ++it) {
            vector<int> seq = *it;
            if (seq.size() && nums[i] < seq.back()) continue;
            seq.push_back(nums[i]);
            newAns.insert(seq);
          }
          ans = newAns;
        }
        for (auto it = ans.begin(); it != ans.end(); ) {
          if (it->size() <= 1) it = ans.erase(it);
          else ++it;
        }
        return vector<vector<int>>(ans.begin(), ans.end());
      }
    };
    
  • class Solution:
        def findSubsequences(self, nums: List[int]) -> List[List[int]]:
            def dfs(u, last, t):
                if u == len(nums):
                    if len(t) > 1:
                        ans.append(t[:])
                    return
                if nums[u] >= last:
                    t.append(nums[u])
                    dfs(u + 1, nums[u], t)
                    t.pop()
                if nums[u] != last:
                    dfs(u + 1, last, t)
    
            ans = []
            dfs(0, -1000, [])
            return ans
    
    ############
    
    class Solution(object):
      def findSubsequences(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        ans = []
    
        def dfs(nums, start, path, ans):
          if len(path) >= 2:
            ans.append(tuple(path + []))
    
          for i in range(start, len(nums)):
            if i != start and nums[i] == nums[i - 1]:
              continue
            if path and nums[i] < path[-1]:
              continue
            path.append(nums[i])
            dfs(nums, i + 1, path, ans)
            path.pop()
    
        dfs(nums, 0, [], ans)
        return list(set(ans))
    
    
  • func findSubsequences(nums []int) [][]int {
    	var ans [][]int
    	var dfs func(u, last int, t []int)
    	dfs = func(u, last int, t []int) {
    		if u == len(nums) {
    			if len(t) > 1 {
    				cp := make([]int, len(t))
    				copy(cp, t)
    				ans = append(ans, cp)
    			}
    			return
    		}
    		if nums[u] >= last {
    			t = append(t, nums[u])
    			dfs(u+1, nums[u], t)
    			t = t[:len(t)-1]
    		}
    		if nums[u] != last {
    			dfs(u+1, last, t)
    		}
    	}
    	var t []int
    	dfs(0, -1000, t)
    	return ans
    }
    

All Problems

All Solutions