前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >程序员进阶之算法练习(八十九)leetcode

程序员进阶之算法练习(八十九)leetcode

作者头像
落影
发布2023-11-02 10:40:22
1700
发布2023-11-02 10:40:22
举报
文章被收录于专栏:落影的专栏落影的专栏

题目1 组合总和

题目链接 题目大意: 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

题目解析: 题目要找出所有组合,并且一个数字可以无限选,那么可以用这样的枚举方式: 初始化状态,curTarget=target,记录剩下的数字和; 对于数字a[0],不断选择从curTarget减去a[0],直到curTarget<=0截止; 此时再恢复一个a[0],curTarget+=a[0],然后同样方式枚举a[1]、a[2]...

DFS的方式,中间curTarget=0则表示出现一个解,当前栈数字就是答案。

代码语言:javascript
复制
class Solution {
    vector<vector<int>> ans;
public:
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<int> cur;
        while (!ans.empty()) {
            ans.pop_back();
        }
        dfs(cur, candidates, 0, target);
        return ans;
    }
    
    void dfs(vector<int> &cur, vector<int>& candidates, int index, int left) {
        if (left == 0) {
            ans.push_back(cur);
            return ;
        }
        if (index >= candidates.size()) {
            return ;
        }
        if (left >= candidates[index]) {
            cur.push_back(candidates[index]);
            dfs(cur, candidates, index, left - candidates[index]);
            cur.pop_back();
        }
        dfs(cur, candidates, index + 1, left);
    }
    
}leetcode;

题目2 接雨水

题目链接 题目大意: 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。

示例:

输入: [0,1,0,2,1,0,1,3,2,1,2,1] 输出: 6

题目解析: 先找出一个递增的子序列,直到遇到一个数组的最大值; 如何快速计算两个数字之间能乘的雨水?排除法。 矩形,去掉中间数字的和。

最后反着计算,考虑高度相同的情况即可。

代码语言:javascript
复制
class Solution {
public:
    int trap(vector<int>& height) {
        int curHeight = -1, sum = 0, pos = -1, ans = 0;
        for (int i = 0; i < height.size(); ++i) {
            if (height[i] > curHeight) {
                ans += curHeight * (i - pos - 1) - sum;
                curHeight = height[i];
                sum = 0;
                pos = i;
            }
            else {
                sum += height[i];
            }
        }
        int highPos = pos;
        curHeight = -1, sum = 0,
        pos = height.size();
        for (int i = height.size() - 1; i >= highPos && i >= 0; --i) {
            if (height[i] >= curHeight) {
                ans += curHeight * (pos - i - 1) - sum;
                curHeight = height[i];
                sum = 0;
                pos = i;
            }
            else {
                sum += height[i];
            }
        }
        return ans;
    }
}lc;

题目3 全排列

题目链接 题目大意: 给定一个不含重复数字的数组 nums ,返回其 所有可能的全排列 。你可以 按任意顺序 返回答案。

示例 1: 输入:nums = [1,2,3] 输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] 示例 2: 输入:nums = [0,1] 输出:[[0,1],[1,0]] 示例 3: 输入:nums = [1] 输出:[[1]]

提示: 1 <= nums.length <= 6 -10 <= nums[i] <= 10 nums 中的所有整数 互不相同

题目解析: 只要完成1到n的全排列,那么输出的时候把1到n换成数组元素nums[1]到nums[n]就可以得到全排列; 全排列的做法: 深度优先遍历(DFS),1、2、3、、、n,每个数字有取和不取的选择; 因为数字不相同,所以不会出现不一致的情况;(每一位至少存在不一样的数字) 用递归更容易实现。

代码语言:javascript
复制
class Solution {
public:
    int vis[N];
    vector<vector<int>> permute(vector<int>& nums) {
        vector<vector<int> > ans;
        memset(vis, 0,  sizeof(int) * nums.size());
        vector<int> tmp;
        look(ans, nums, tmp, 0);
        return ans;
    }
    
    void look(vector<vector<int> > &ans, vector<int> &num, vector<int> &tmp, int count) {
        if (count == num.size()) {
            ans.push_back(tmp);
            return ;
        }
        int id;
        for (id = 0; id < num.size(); ++id) {
            if (!vis[id]) {
                vis[id] = 1;
                tmp.push_back(num[id]);
                look(ans, num, tmp, count + 1);
                tmp.pop_back();
                vis[id] = 0;
            }
        }
    }
}leetcode;

题目4 字母异位词分组

题目链接 题目大意: 给定一个字符串数组,将字母异位词组合在一起。字母异位词指字母相同,但排列不同的字符串。

示例:

输入: ["eat", "tea", "tan", "ate", "nat", "bat"] 输出: [ ["ate","eat","tea"], ["nat","tan"], ["bat"] ] 说明:

所有输入均为小写字母。 不考虑答案输出的顺序。

题目解析: 字母异位词相当于每个字符出现的次数一致,那么字符串中位置信息是无用的,可以统计每个字符串中字母的数量,每个字符可以转为长度为26的数组; 接下来用排序的方式,将所有的数组进行排序,这样数组一样的就会变得相邻,最后遍历数组即可。

思考: hash的做法,将每个字符串排序,从小到大,然后用hash的方法将字符串映射为整数;(unorder_map + string)

代码语言:javascript
复制
class Solution {
public:
   vector<vector<string>> groupAnagrams(vector<string>& strs) {
       int n = strs.size();
       Node dot[n];
       for (int i = 0; i < n; ++i) {
           memset(dot[i].cnt, 0, sizeof(dot[i].cnt));
           for (int j = 0; j < strs[i].length(); ++j) {
               dot[i].cnt[strs[i][j] - 'a']++;
           }
           dot[i].index = i;
       }
       sort(dot, dot + n);
       vector<vector<string>> ret;
       vector<string> tmp;
       tmp.push_back(strs[dot[0].index]);
       for (int i = 1; i < n; ++i) {
           if (!dot[i].isEqual(dot[i - 1])) {
               ret.push_back(tmp);
               tmp.clear();
           }
           tmp.push_back(strs[dot[i].index]);
       }
       ret.push_back(tmp);
       return ret;
   }
}leetcode;

题目5 最大子数组和

题目链接 题目大意: 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

子数组 是数组中的一个连续部分。

示例 1:

输入:nums = [-2,1,-3,4,-1,2,1,-5,4] 输出:6 解释:连续子数组 [4,-1,2,1] 的和最大,为 6 。 示例 2:

输入:nums = [1] 输出:1 示例 3:

输入:nums = [5,4,-1,7,8] 输出:23

题目解析: 暴力的做法,枚举每个子区间[i, j],算出每个区间的和,总的复杂度是O(N ^ 2);

动态规划的做法: 1、子问题拆解,dp[i]表示前i个数字中,区间以第i个数字结尾的最大和; 2、状态转移,两个选择,要么取a[i-1]的区间,要么不取前i-1个字数字,得状态转移方程:dp[i] = max(dp[i - 1] + a[i], a[i]); 复杂度为O(N);

代码语言:javascript
复制
class Solution {
public:
    int maxSubArray(vector<int>& nums) {
        int ret = nums[0], n = nums.size();
        vector<int> dp(n);
        dp[0] = nums[0];
        for (int i = 1; i < n; ++i) {
            dp[i] = max(dp[i - 1] + nums[i], nums[i]);
            ret = max(ret, dp[i]);
        }
        return ret;
    }
}leetcode;
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2023-11-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

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

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目1 组合总和
  • 题目2 接雨水
  • 题目3 全排列
  • 题目4 字母异位词分组
  • 题目5 最大子数组和
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档