力扣题解17-18

17 电话号码的字母组合

中等题
在这里插入图片描述
一道排列组合的题目。很容易发现每次都是在上次的结果上循环,只是可供选择的字母数可能是3或4。此类明显带有“这次是结果是在上次基础上完成的”特征的题目,通常都能用动态规划解决,因为明显告诉了递推关系。
动态规划问三个问题:

  1. 状态。这题使用一维数组存储即可,dp[i]表示输入i个字母后所有的排列组合情况的数组。
  2. 递推表达式。已知dp[i],求dp[i+1]就是把dp[i]中的组合分别加上第i+1个数字可能表示的字母。
  3. 初始值。dp[0]表示没有数字进来,应该是空数组。不过为了后面方便遍历,可以存一个空字符串。

按照以上思路编写代码,只是我不太会C++的数组动态分配,用循环需要一开始开辟大数组,索性直接递归了,反正要循环的次数是少不了的。

#include <iostream>
#include <vector>

using namespace std;

class Solution {
public:
    vector<string> letterCombinations(string digits) {
        vector<vector<string>> key = {
        {""}, //0
        {""}, //1
        {"a","b","c"}, //2
        {"d","e","f"}, //3
        {"g","h","i"}, //4
        {"j","k","l"}, //5
        {"m","n","o"}, //6
        {"p","q","r","s"}, //7
        {"t","u","v"}, //8
        {"w","x","y","z"} //9
        };
        if(digits=="") return vector<string>();
        return constituten(key,digits,digits.size());
    }

    vector<string> constituten(vector<vector<string>> key, string digits, int loc){
        if(loc == 0) return vector<string>({string()});
        vector<string> res;
        vector<string> prv = constituten(key,digits,loc-1);
        int num = digits[loc-1] - 48;
        for(int i=0; i<key[num].size(); i++){
            for(int j=0; j<prv.size(); j++){
                res.push_back(prv[j]+key[num][i]);
            }
        }
        return res;
    }
};


int main(){
    string digits = "";
    Solution st;
    vector<string> vt;

    vt=st.letterCombinations(digits);  
    return 0;
}

官解给出回溯法,是使用搜索的思想吧,个人觉得在这题没有那么明显,下次遇到再分析吧。

18 四数之和

中等题
在这里插入图片描述
三数找完找四数,我的精神内耗都这几个叔治好啦。
解题思路和三数完全一样,多一层循环,也是双指针。测试用例里非要搞个溢出,那就补上处理溢出操作。

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

class Solution {
public:
    vector<vector<int>> fourSum(vector<int>& nums, int target) {
        int len = nums.size();
        vector<vector<int>> res = {};
        if(len<4) return res;
        sort(nums.begin(),nums.end()); //排序
        for(int first=0; first<len-3; first++){
            //一层循环
            if(first!=0 && nums[first-1] == nums[first]) continue;
            for(int second=first+1; second<len-2; second++){
                //二层循环
                if(second!=first+1 && nums[second-1] == nums[second]) continue;
                int forth = len-1;
                for(int third = second+1; third<len-1; third++){
                    //三重循环
                    if(third!=second+1 && nums[third-1] == nums[third]) continue;
                    while(third<forth){
                        long half = (long)target-nums[first]-nums[second];
                        if(nums[third]+nums[forth] == half){
                            res.push_back(vector<int>({nums[first],nums[second],nums[third],nums[forth]}));
                            break;
                        }
                        if(nums[third]+nums[forth] > target-nums[first]-nums[second]) forth--;
                        else break;
                    }
                }
            }
        }
        return res;
    }
};

int main(){
    Solution st;
    vector<int> vt = {1,0,-1,0,-2,2};
    int target = 0;
    vector<vector<int>> res;
    
    res = st.fourSum(vt,target);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值