491. Non-decreasing Subsequences
leetcode medium
Task
Дан массив целых чисел nums. Верните все возможные различные неубывающие подпоследовательности данного массива, содержащие как минимум два элемента. Вы можете вернуть ответ в любом порядке.
Пример:
Input: nums = [4,6,7,7]
Output: [[4,6],[4,6,7],[4,6,7,7],[4,7],[4,7,7],[6,7],[6,7,7],[7,7]]
C# solution
matched/originalpublic class Solution {
public IList<IList<int>> FindSubsequences(int[] nums) {
var result = new HashSet<IList<int>>();
var sequence = new List<int>();
Backtrack(nums, 0, sequence, result);
return result.ToList();
}
private void Backtrack(int[] nums, int index, List<int> sequence, HashSet<IList<int>> result) {
if (index == nums.Length) {
if (sequence.Count >= 2) {
result.Add(new List<int>(sequence));
}
return;
}
if (sequence.Count == 0 || sequence[sequence.Count - 1] <= nums[index]) {
sequence.Add(nums[index]);
Backtrack(nums, index + 1, sequence, result);
sequence.RemoveAt(sequence.Count - 1);
}
Backtrack(nums, index + 1, sequence, result);
}
}C++ solution
auto-draft, review before submit#include <bits/stdc++.h>
using namespace std;
// Auto-generated C++ draft from the C# solution. Review containers, LINQ and helper types before submit.
class Solution {
public:
public IList<vector<int>> FindSubsequences(vector<int>& nums) {
var result = new HashSet<vector<int>>();
var sequence = new List<int>();
Backtrack(nums, 0, sequence, result);
return result.ToList();
}
private void Backtrack(vector<int>& nums, int index, List<int> sequence, HashSet<vector<int>> result) {
if (index == nums.size()) {
if (sequence.size() >= 2) {
result.push_back(new List<int>(sequence));
}
return;
}
if (sequence.size() == 0 || sequence[sequence.size() - 1] <= nums[index]) {
sequence.push_back(nums[index]);
Backtrack(nums, index + 1, sequence, result);
sequence.RemoveAt(sequence.size() - 1);
}
Backtrack(nums, index + 1, sequence, result);
}
}Java solution
matched/originalclass Solution {
private void backtrack(int[] nums, int index, List<Integer> sequence,
Set<List<Integer>> result) {
if (index == nums.length) {
if (sequence.size() >= 2) {
result.add(new ArrayList<>(sequence));
}
return;
}
if (sequence.isEmpty() ||
sequence.get(sequence.size() - 1) <= nums[index]) {
sequence.add(nums[index]);
backtrack(nums, index + 1, sequence, result);
sequence.remove(sequence.size() - 1);
}
backtrack(nums, index + 1, sequence, result);
}
public List<List<Integer>> findSubsequences(int[] nums) {
Set<List<Integer>> result = new HashSet<List<Integer>>();
List<Integer> sequence = new ArrayList<Integer>();
backtrack(nums, 0, sequence, result);
return new ArrayList(result);
}
}JavaScript solution
matched/originalvar findSubsequences = function(nums) {
const result = new Set();
const sequence = [];
backtrack(nums, 0, sequence, result);
return Array.from(result).map(JSON.parse);
};
function backtrack(nums, index, sequence, result) {
if (index === nums.length) {
if (sequence.length >= 2) {
result.add(JSON.stringify(sequence));
}
return;
}
if (sequence.length === 0 || sequence[sequence.length - 1] <= nums[index]) {
sequence.push(nums[index]);
backtrack(nums, index + 1, sequence, result);
sequence.pop();
}
backtrack(nums, index + 1, sequence, result);
}Python solution
matched/originalclass Solution:
def findSubsequences(self, nums: List[int]) -> List[List[int]]:
result = set()
sequence = []
self.backtrack(nums, 0, sequence, result)
return list(result)
def backtrack(self, nums, index, sequence, result):
if index == len(nums):
if len(sequence) >= 2:
result.add(tuple(sequence))
return
if not sequence or sequence[-1] <= nums[index]:
sequence.append(nums[index])
self.backtrack(nums, index + 1, sequence, result)
sequence.pop()
self.backtrack(nums, index + 1, sequence, result)Go solution
matched/originalfunc findSubsequences(nums []int) [][]int {
result := make(map[string][]int)
sequence := []int{}
backtrack(nums, 0, &sequence, result)
res := [][]int{}
for _, v := range result {
res = append(res, v)
}
return res
}
func backtrack(nums []int, index int, sequence *[]int, result map[string][]int) {
if index == len(nums) {
if len(*sequence) >= 2 {
key := fmt.Sprintf("%v", *sequence)
result[key] = append([]int(nil), *sequence...)
}
return
}
if len(*sequence) == 0 || (*sequence)[len(*sequence)-1] <= nums[index] {
*sequence = append(*sequence, nums[index])
backtrack(nums, index+1, sequence, result)
*sequence = (*sequence)[:len(*sequence)-1]
}
backtrack(nums, index+1, sequence, result)
}Explanation
Algorithm
Инициализация и запуск функции обратного отслеживания
Создайте множество для хранения результатов. Создайте список для хранения текущей последовательности. Запустите рекурсивную функцию обратного отслеживания с начальным индексом 0.
Функция обратного отслеживания
Если текущий индекс равен длине массива, проверьте длину текущей последовательности и добавьте её в результат, если она содержит не менее двух элементов. Если текущая последовательность остаётся неубывающей после добавления текущего элемента массива, добавьте этот элемент, вызовите рекурсивную функцию для следующего индекса и удалите элемент из последовательности (обратное отслеживание). Всегда вызывайте рекурсивную функцию для следующего индекса без добавления текущего элемента.
Возврат результата
После завершения всех рекурсивных вызовов преобразуйте множество результатов в список и верните его.
😎