前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >链表、DFS-LeetCode 216、213、148、202(链表归并排序,组合数问题)

链表、DFS-LeetCode 216、213、148、202(链表归并排序,组合数问题)

作者头像
算法工程师之路
发布2019-11-14 15:48:40
4800
发布2019-11-14 15:48:40
举报

链表、DFS:LeetCode #216 213 148 202

1

编程题

【LeetCode #216】组合总和III

找出所有相加之和为 n 的 k 个数的组合。组合中只允许含有 1 - 9 的正整数,并且每种组合中不存在重复的数字。

说明:

  • 所有数字都是正整数。
  • 解集不能包含重复的组合。

示例 1:

输入: k = 3, n = 7 输出: [[1,2,4]]

解题思路:

组合数求和问题,一般都能想到回溯法,其中在递归中一共有5个变量,其中k和n全程值不改变,因此主要的变量就是sum、num、start. sum用来标记回溯过程中tmp数组中数字之和,而num则标记tmp数组中数字个数,由于题目中要求在tmp数组中不能够重复,因此使用start标记每个子问题的起始循环数字,每进入一个子问题,起始值加 1, 从而永远不会重复!

代码语言:javascript
复制
class Solution {
public:
    vector<vector<int>> res;
    vector<int> tmp;
    void dfs(int sum, int num, int start, int k, int n){
        if(sum > n)  return;
        if(sum == n){
            if(num == k){
                res.push_back(tmp);
                return;
            }
        }
        for(int i = start; i < 10; ++i){
            tmp.push_back(i);
            dfs(sum+i, num+1, i+1, k, n);
            tmp.pop_back();
        }
    }

    vector<vector<int>> combinationSum3(int k, int n) {
        if(k <= 0 || n <= 0){
            return res;
        }
        dfs(0, 0, 1, k, n);
        return res;
    }
};

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/combination-sum-iii

【LeetCode #213】打家劫舍II

你是一个专业的小偷,计划偷窃沿街的房屋,每间房内都藏有一定的现金。这个地方所有的房屋都围成一圈,这意味着第一个房屋和最后一个房屋是紧挨着的。同时,相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。 给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。

示例 1: 输入: [2,3,2] 输出: 3 解释: 你不能先偷窃 1 号房屋(金额 = 2),然后偷窃 3 号房屋(金额 = 2), 因为他们是相邻的。

解题思路:

在前几天推送的打家劫舍I中,其递推式为dp[i] = max(dp[i-1], dp[i-2]+nums[i]); 而在这道题目中,其主要的变化是,这些房子连成了一个圈,也就是说对于第一个屋子和最后一个屋子只能选择其中一个来偷。 那么问题就变得简单了,可以分为两种情况,第一种是偷第一家,第二种是不偷第一家,然后分别使用打家劫舍I中的方法求这两种问题的最大值,而两个值得最大值也就是本题的解了!

代码语言:javascript
复制
class Solution {
public:
    int rob(vector<int>& nums) {
        if(nums.size() == 0)  return 0;
        if(nums.size() == 1) return nums[0];
        vector<int> dp1(nums.size(), 0), dp2(nums.size(), 1);
        dp1[0] = 0, dp1[1] = nums[0];
        dp2[0] = 0, dp2[1] = nums[1];
        for(int i = 2; i < nums.size(); i++){
            dp1[i] = max(dp1[i-1], dp1[i-2]+nums[i-1]);
        }
        for(int i = 2; i < nums.size(); i++){
            dp2[i] = max(dp2[i-1], dp2[i-2]+nums[i]);
        }
        return max(dp1[nums.size()-1], dp2[nums.size()-1]);
    }
};

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/house-robber-ii

【LeetCode #148】排序链表

在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序。

示例 1: 输入: 4->2->1->3 输出: 1->2->3->4 示例 2: 输入: -1->5->3->4->0 输出: -1->0->3->4->5

解题思路:

对链表进行归并排序,但是由于使用了递归算法,因此不满足题意中的常数空间!不过可以将归并排序的思想复习一遍,如何用到链表上!

代码语言:javascript
复制
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     ListNode *next;
 *     ListNode(int x) : val(x), next(NULL) {}
 * };
 */
class Solution {
public:
    ListNode* sortList(ListNode* head) {
        return head == nullptr ? nullptr : mergeSort(head);
    }
private:
    ListNode* mergeSort(ListNode* head){
        if(head->next == nullptr){
            return head;
        }
        // 快慢指针获取链表中心点
        ListNode* slow = head, *fast = head, *pre = nullptr;
        while(fast != nullptr){
            pre = slow;
            slow = slow->next;
            fast = fast->next ? fast->next->next : fast->next;
        }
        pre->next = nullptr;
        ListNode* l = mergeSort(head);
        ListNode* r = mergeSort(slow);
        return merge(l, r);
    }
    ListNode* merge(ListNode* l, ListNode* r){
        ListNode* dummy = new ListNode(0);
        ListNode* cur = dummy;
        while(l != nullptr && r != nullptr){
            if(l->val <= r->val){
                cur->next = l;
                cur = cur->next;
                l = l->next;
            }else{
                cur->next = r;
                cur = cur->next;
                r = r->next;
            }
        }
        if(l != nullptr){
            cur->next = l;
        }
        if(r != nullptr){
            cur->next = r;
        }
        return dummy->next;
    }
};

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/sort-list

【LeetCode #202】快乐数

编写一个算法来判断一个数是不是“快乐数”。

一个“快乐数”定义为:对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和,然后重复这个过程直到这个数变为 1,也可能是无限循环但始终变不到 1。如果可以变为 1,那么这个数就是快乐数。

示例: 输入: 19 输出: true 解释: 12 + 92 = 82 82 + 22 = 68 62 + 82 = 100 12 + 02 + 02 = 1

解题思路:

利用哈希表,建立一个位数求平方和的函数,将每次得到的中间数存入哈希表,快乐的时候,在循环计算时会出现数字 1,从而判断为快乐数,如果不快乐,那必定从某个数开始一直循环,从而while循环的条件就是每个位数平方和的结果会不会出现两次,如果是并且没有为 1 的数,那么必定不快乐!

代码语言:javascript
复制
class Solution {
public:
    bool isHappy(int n) {
        unordered_set<int> set;
        int res;
        res = sumsquare(n);
        while(set.count(res) == 0){
            set.insert(res);
            res = sumsquare(res);
            if(res == 1) return true;
        }
        return false;
    }
    int sumsquare(int num){
        int sum = 0;
        while(num){
            sum += (num%10)*(num%10);
            num /= 10;
        }
        return sum;
    }
};

来源:力扣(LeetCode) 链接:https://leetcode-cn.com/problems/happy-number

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-11-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 算法工程师之路 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档