【算法题】递归树+哈希表+分治异或+双指针


1.vector与spring的结合

17. 电话号码的字母组合https://leetcode.cn/problems/letter-combinations-of-a-phone-number/

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

题解:

方法一:

复制代码
class Solution {
public:
    vector<string> letterCombinations(string digits) {
       // 1. 映射表定义
       string map[] = {
            "", "", "abc", "def", "ghi", "jkl",
            "mno", "pqrs", "tuv", "wxyz"
        };
        int num=0;
        // 2. 初始化结果容器
        vector<string> vv(1);
        vector<string> tmp;
        
        // 3. 遍历输入数字字符串
        for(auto e:digits)
        {
            tmp.clear();
            num=e-'0';
            
            // 4. 遍历当前数字对应的字母
            for(auto ee:map[num])
            {
                // 5. 将当前字母与已有组合合并
                for(string eee:vv)
                {
                    tmp.push_back(eee+ee);
                }
            }
            // 6. 更新结果
            vv=tmp;
        }
        return vv;
    }
};

思考:

1.为什么这里要重新定义一个tmp?

2.容器为什么初始化?

3.tmp为什么要clear?

方法二(递归树):

复制代码
class Solution {
public:
    string a[10]={"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};
    vector<string> v;
    int n;
    string s;
    void dfs(int dep,string t){ //除了深度,加一个变量t用于保存每层拼接的字符串
        if(dep==n){
            v.push_back(t);
            return;
        }
        for(char c:a[s[dep]-'0']){ //第i层深度取字符串第i个数字  
            dfs(dep+1,t+c); //t+c会直接拼接
        }
    }//2345
    vector<string> letterCombinations(string digits) {
        n=digits.size();
        s=digits;
        dfs(0,"");
        return v;
    }
};
相同逻辑,不同写法:
复制代码
class Solution {
public:
    vector<string> res;

    vector<string> letterCombinations(string digits) {
        if(digits == "") return {};
        dfs(digits,0);
        return res;
    }
    void dfs(string digits,int index){
        if(index == digits.length()){
            res.push_back(digits);
            return;
        }
        switch(digits[index]){
            case '2': digits[index] = 'a'; dfs(digits,index+1);
                      digits[index] = 'b'; dfs(digits,index+1);  
                      digits[index] = 'c'; dfs(digits,index+1);
                      break;
            case '3': digits[index] = 'd'; dfs(digits,index+1);
                      digits[index] = 'e'; dfs(digits,index+1);  
                      digits[index] = 'f'; dfs(digits,index+1);
                      break;  
            case '4': digits[index] = 'g'; dfs(digits,index+1);
                      digits[index] = 'h'; dfs(digits,index+1);  
                      digits[index] = 'i'; dfs(digits,index+1);
                      break;  
            case '5': digits[index] = 'j'; dfs(digits,index+1);
                      digits[index] = 'k'; dfs(digits,index+1);  
                      digits[index] = 'l'; dfs(digits,index+1);
                      break; 
            case '6': digits[index] = 'm'; dfs(digits,index+1);
                      digits[index] = 'n'; dfs(digits,index+1);  
                      digits[index] = 'o'; dfs(digits,index+1);
                      break;  
            case '7': digits[index] = 'p'; dfs(digits,index+1);
                      digits[index] = 'q'; dfs(digits,index+1);  
                      digits[index] = 'r'; dfs(digits,index+1);
                      digits[index] = 's'; dfs(digits,index+1);
                      break;  
            case '8': digits[index] = 't'; dfs(digits,index+1);
                      digits[index] = 'u'; dfs(digits,index+1);  
                      digits[index] = 'v'; dfs(digits,index+1);
                      break;  
            case '9': digits[index] = 'w'; dfs(digits,index+1);
                      digits[index] = 'x'; dfs(digits,index+1);  
                      digits[index] = 'y'; dfs(digits,index+1);
                      digits[index] = 'z'; dfs(digits,index+1);
                      break;   
        }
    }
};

方法三:(队列)

复制代码
class Solution 
{
private:
    unordered_map<char,string> letter_map{
        {'2',"abc"}, {'3',"def"}, {'4',"ghi"},
        {'5',"jkl"}, {'6',"mno"}, {'7',"pqrs"},
        {'8',"tuv"}, {'9',"wxyz"}
    };
    vector<string> res;
public:
    vector<string> letterCombinations(string digits) 
    {
        if(digits.empty())
            return res;
        
        queue<string> que;
        for(int i=0;i<digits.size();++i)
        {
            string letters = letter_map[digits[i]]; //数字对应的字符集
            if(0==i)
            {
                // 如果是第一个数字,就将第一个数字对应的字符集依次加入队列中去
                string temp;
                for(int j=0;j<letters.size();++j)
                {
                    temp = letters[j];
                    que.push(temp);
                }
            }
            else
            {
                int size = que.size(); //队列长度
                //计算出队列长度后,将队列中的每个元素挨个拿出来
                for(int j=0;j<size;++j)
                {
                    string temp = que.front();
                    que.pop();
                    //然后跟当前数字对应的字符集拼接,并再次放到队列中
                    for(int k=0;k<letters.size();++k)
                    {
                        que.push(temp+letters[k]);
                    }
                }
            }
        }
        while(!que.empty())
        {
            res.emplace_back(que.front());
            que.pop();
        }

        return res;
    }
}

2.双指针法

11. 盛最多水的容器https://leetcode.cn/problems/container-with-most-water/

给定一个长度为 n 的整数数组 height 。有 n 条垂线,第 i 条线的两个端点是 (i, 0)(i, height[i])

找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

返回容器可以储存的最大水量。

说明:你不能倾斜容器

题解:

复制代码
class Solution {
public:
    int maxArea(vector<int>& height) {
        int left=0,right=height.size()-1;
        int maxi;
        while(left<right)
        {    
            if(height[right]>height[left])
            {
            maxi=max(maxi,(right-left)*height[left]);
            left++;
            }
            else{
            maxi=max(maxi,(right-left)*height[right]);
            right--;
            }
        }
        return maxi;
    }
};

思考:

会不会出现漏失数据的现象?为什么可以双指针?


3.找单身狗lll

260. 只出现一次的数字 IIIhttps://leetcode.cn/problems/single-number-iii/

给你一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。 找出只出现一次的那两个元素。你可以按 任意顺序 返回答案。

你必须设计并实现线性时间复杂度的算法且仅使用常量额外空间来解决此问题。

题解:

方法一:(分治异或法)

复制代码
class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        if(nums.size()==2)
        return  nums;
        int val=0;
        for(int i=0;i<nums.size();i++)
        {
            val^=nums[i];//x1^x2
        }
        int index=getFirst1(val);
        int num1=0,num2=0;
        for(auto ch:nums)
        {
            if(((ch>>index)&1)==0)
            num1^=ch;
            else
            num2^=ch;
        }
        return {num1,num2};
        
    }
    int getFirst1(int val) {
    int index=0;
    while (((val&1)==0&&index<32))
    {
        val>>=1;// val=val/2
        index++;
    }
        return index;
    }
};

方法二:(哈希表)

复制代码
class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) {
        unordered_map<int, int> freq;
        for (int num: nums) {
            ++freq[num];
        }
        vector<int> ans;
        for (const auto& [num, occ]: freq) {
            if (occ == 1) {
                ans.push_back(num);
            }
        }
        return ans;
    }
};

相关推荐
yugi9878381 小时前
经典三维表面重建算法(C语言实现)
c语言·开发语言·算法
Hello:CodeWorld1 小时前
高性能多线程数据采集与持久化方案设计与实现
开发语言·c++
程序猿编码1 小时前
Linux 高负载场景下 Web 服务访问日志极速定位工具实现解析(C/C++代码实现)
linux·服务器·c语言·前端·c++
无限进步_1 小时前
【C++】智能指针族谱:auto_ptr、unique_ptr、shared_ptr
java·开发语言·数据结构·c++·算法
LuminousCPP1 小时前
C 语言文件操作全攻略:从基础读写到随机访问与缓冲区原理
c语言·经验分享·笔记·文件操作
Brilliantwxx1 小时前
【C++】Stack和Queue(初认识和算法题OJ)
开发语言·c++·笔记·算法
ch.ju1 小时前
Java Programming Chapter 3——If the array is out of range
java·开发语言
枫叶丹41 小时前
【HarmonyOS 6.0】Desktop Extension Kit 正式接棒原状态栏服务,API 引用路径全面更新
开发语言·华为·harmonyos