最新要闻

广告

手机

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

iphone11大小尺寸是多少?苹果iPhone11和iPhone13的区别是什么?

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

警方通报辅警执法直播中被撞飞:犯罪嫌疑人已投案

家电

天天日报丨【算法训练营day29】LeetCode491. 递增子序列 LeetCode46. 全排列 LeetCode47. 全排列II

来源:博客园


(相关资料图)

LeetCode491. 递增子序列

题目链接:491. 递增子序列

独上高楼,望尽天涯

难点在于如何在无法排序的情况下去重,核心思路是同层中同一父节点下使用过的元素就不能再使用了。

class Solution {private:    vector> result;    vector path;    void backtracking(vector& nums, int start_index) {        if (path.size() > 1) {            result.push_back(path);        }        for (int i = start_index; i < nums.size(); i++) {            // 这是我的去重方法,比较原始            bool if_con = false;            for(int j = start_index; j < i; j++) {                if (nums[j] == nums[i]) {                    if_con = true;                }            }            if (if_con) {                continue;            }            if (path.size() == 0 || nums[i] >= path.back()) {                path.push_back(nums[i]);                backtracking(nums, i + 1);                path.pop_back();            }        }    }public:    vector> findSubsequences(vector& nums) {        backtracking(nums, 0);        return result;    }};

慕然回首,灯火阑珊

思路一样,题解的实现方法更好,用的是数组作为哈希表去重。

class Solution {private:    vector> result;    vector path;    void backtracking(vector& nums, int startIndex) {        if (path.size() > 1) {            result.push_back(path);        }        int used[201] = {0}; // 这里使用数组来进行去重操作,题目说数值范围[-100, 100]        for (int i = startIndex; i < nums.size(); i++) {            if ((!path.empty() && nums[i] < path.back()) // vector判空的技巧                    || used[nums[i] + 100] == 1) {                    continue;            }            used[nums[i] + 100] = 1; // 记录这个元素在本层用过了,本层后面不能再用了            path.push_back(nums[i]);            backtracking(nums, i + 1);            path.pop_back();        }    }public:    vector> findSubsequences(vector& nums) {        result.clear();        path.clear();        backtracking(nums, 0);        return result;    }};

LeetCode46. 全排列

题目链接:46. 全排列

独上高楼,望尽天涯

每使用一个元素后,直接在nums数组中删除已经使用过的元素,从而达到排列的效果。

class Solution {private:    vector> result;    vector path;    void backtracking(vector& nums) {        if (nums.empty()) {            result.push_back(path);            return;        }        for (int i = 0; i < nums.size(); i++) {            int temp = nums[i];            path.push_back(temp);            nums.erase(nums.begin() + i); // 直接在nums数组中删除已经使用过的元素            backtracking(nums);            nums.insert(nums.begin() + i, temp); // 回溯过程            path.pop_back();        }    }public:    vector> permute(vector& nums) {        backtracking(nums);        return result;    }};

慕然回首,灯火阑珊

思路一样,但是实现上使用了used数组,用来记录path上已经使用过的元素。

class Solution {public:    vector> result;    vector path;    void backtracking (vector& nums, vector& used) {        // 此时说明找到了一组        if (path.size() == nums.size()) {            result.push_back(path);            return;        }        for (int i = 0; i < nums.size(); i++) {            if (used[i] == true) continue; // path里已经收录的元素,直接跳过            used[i] = true;            path.push_back(nums[i]);            backtracking(nums, used);            path.pop_back();            used[i] = false;        }    }    vector> permute(vector& nums) {        result.clear();        path.clear();        vector used(nums.size(), false);        backtracking(nums, used);        return result;    }};

LeetCode47. 全排列II

题目链接:47. 全排列II

独上高楼,望尽天涯

和之前的去重方法一样,举一反三即可。

class Solution {private:    vector> result;    vector path;    void backtracking(vector& nums) {        if (nums.empty()) {            result.push_back(path);            return;        }        for (int i = 0; i < nums.size(); i++) {            if (i != 0 && nums[i] == nums[i - 1]) { // 去重过程                continue;            }            int temp = nums[i];            path.push_back(temp);            nums.erase(nums.begin() + i);            backtracking(nums);            nums.insert(nums.begin() + i, temp);            path.pop_back();        }    }public:    vector> permuteUnique(vector& nums) {        sort(nums.begin(), nums.end());        backtracking(nums);        return result;    }};

慕然回首,灯火阑珊

思路一样。

一般来说:组合问题和排列问题是在树形结构的叶子节点上收集结果,而子集问题就是取树上所有节点的结果

class Solution {private:    vector> result;    vector path;    void backtracking (vector& nums, vector& used) {        // 此时说明找到了一组        if (path.size() == nums.size()) {            result.push_back(path);            return;        }        for (int i = 0; i < nums.size(); i++) {            // used[i - 1] == true,说明同一树枝nums[i - 1]使用过            // used[i - 1] == false,说明同一树层nums[i - 1]使用过             // 如果同一树层nums[i - 1]使用过则直接跳过            if (i > 0 && nums[i] == nums[i - 1] && used[i - 1] == false) {                continue;            }            if (used[i] == false) {                used[i] = true;                path.push_back(nums[i]);                backtracking(nums, used);                path.pop_back();                used[i] = false;            }        }    }public:    vector> permuteUnique(vector& nums) {        result.clear();        path.clear();        sort(nums.begin(), nums.end()); // 排序        vector used(nums.size(), false);        backtracking(nums, used);        return result;    }};

关键词: 灯火阑珊 独上高楼望 独上高楼