当前位置: 首页 > news >正文

Leetcode hot100(day 5)

实现trie(前缀树)

做法:acwing基础课相同,这里由于是在类里面,不能直接创建一个节点在类内,所以可以用this

class Trie {
public:
    vector<Trie*>children;
    bool isend;
    //Trie root;
    Trie* searchprefix(string prefix)
    {
        Trie* node=this;
        for(char ch:prefix)
        {
            ch=ch-'a';
            if(node->children[ch]==nullptr)return nullptr;
            node=node->children[ch];
        }
        return node;
    }
    Trie():children(26),isend(false) {
        
    }
    
    void insert(string word) {
        Trie* node=this;
        for(char ch:word)
        {
            ch=ch-'a';
            if(node->children[ch]==nullptr)node->children[ch]=new Trie();
            node=node->children[ch];
        }
        node->isend=true;
    }
    
    bool search(string word) {
        Trie* node=this->searchprefix(word);
        return node!=nullptr&&node->isend;
    }
    
    bool startsWith(string prefix) {
        return this->searchprefix(prefix)!=nullptr;
    }
};


全排列

做法:非常经典的dfs回溯,刚好练练手

class Solution {
public:
    vector<vector<int>> v;
    void dfs(vector<int>&vec,int k,vector<int>& nums,vector<bool>&st)
    {
        if(k==nums.size())
        {
            v.emplace_back(vec);
            return;
        }
        for(int i=0;i<nums.size();i++)
        {
            if(st[i]==false)
            {
            vec.emplace_back(nums[i]);
            st[i]=true;
            dfs(vec,k+1,nums,st);
            vec.pop_back();
            st[i]=false;
            }
        }
    }
    vector<vector<int>> permute(vector<int>& nums) {
        int sz=nums.size();
        vector<bool> st(sz,false);
        vector<int> vec;
        dfs(vec,0,nums,st);
        return v;
    }
};

子集

做法一:迭代法,如果一共有n个元素的集合,那么包括空集,一共有2^n种状态,恰好对应n位2进制的个数,所以我们遍历二进制即可

class Solution {
public:
    vector<int> t;
    vector<vector<int>> ans;
    vector<vector<int>> subsets(vector<int>& nums) {
        int n=nums.size();
        for(int mask=0;mask<(1<<n);mask++)
        {
            t.clear();
            for(int i=0;i<n;i++)
            {
                if(mask&(1<<i))t.push_back(nums[i]);
            }
            ans.push_back(t);
        }
        return ans;
    }
};

做法二:递归法,递归要设置出口,所以还是和之前一样,在n==size的时候出去,但这时候因为要选择子序列,所以要有选择和不选择两种递归路线

class Solution {
public:
    vector<int> t;
    vector<vector<int>> ans;
    void dfs(int cur,vector<int>& nums)
    {
        if(cur==nums.size())
        {
            ans.push_back(t);
            return;
        }
        t.push_back(nums[cur]);
        dfs(cur+1,nums);
        t.pop_back();
        dfs(cur+1,nums);
    }
    vector<vector<int>> subsets(vector<int>& nums) {
        dfs(0,nums);
        return ans;
    }
};

电话号码的字母组合

做法:递归,和前面没什么区别,只是复杂了一点点而已

class Solution {
public:
    vector<string> ans;
    string path;
    unordered_map<char, string> mp{
            {'2', "abc"},
            {'3', "def"},
            {'4', "ghi"},
            {'5', "jkl"},
            {'6', "mno"},
            {'7', "pqrs"},
            {'8', "tuv"},
            {'9', "wxyz"}
        };
    void dfs(string digits,int cur)
    {
        if(cur==digits.size())
        {
            ans.push_back(path);
            return;
        }
        string letter=mp[digits[cur]];
        for(int i=0;i<letter.size();i++)
        {
            path.push_back(letter[i]);
            dfs(digits,cur+1);
            path.pop_back();
        }
    }
    vector<string> letterCombinations(string digits) {
        if(digits.empty())return {};
        dfs(digits,0);
        return ans;
    }
};

组合总和

做法:回溯秒了。本来想用sort看能不能再剪枝,但最后反而时间更多,所以就采用正常的剪枝了

class Solution {
public:
    vector<vector<int>> ans;

    void dfs(vector<int>& nums,int k,int target,vector<int>& vec)
    {
        if(k==nums.size())return;
        if(target==0){ans.emplace_back(vec);return;}
        dfs(nums,k+1,target,vec);
        if(target-nums[k]>=0)
        {
            vec.emplace_back(nums[k]);
            dfs(nums,k,target-nums[k],vec);
            vec.pop_back();
        }
    }
    vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
        vector<int> vec;
        dfs(candidates,0,target,vec);
        return ans;
    }
};

括号生成

做法:回溯,一共有2*n个括号,左括号<=n,右括号小于左括号,不然无法匹配,按照这个规则匹配即可。

class Solution {
public:
    void dfs(vector<string>& ans,string& cur,int open,int close,int n)
    {
        if(cur.size()==n*2)
        {
            ans.push_back(cur);
            return;
        }
        if(open<n)
        {
            cur.push_back('(');
            dfs(ans,cur,open+1,close,n);
            cur.pop_back();
        }
        if(close<open)
        {
            cur.push_back(')');
            dfs(ans,cur,open,close+1,n);
            cur.pop_back();
        }
    }
    vector<string> generateParenthesis(int n) {
        vector<string> ans;
        string cur;
        dfs(ans,cur,0,0,n);
        return ans;
    }
};

单词搜索

做法:非优化版本,做一个标记数组,然后搜寻整个图,开始遍历即可,不知道为啥自己写的一直有问题,先不整了

class Solution {
public:
    bool check(vector<vector<char>>& board, vector<vector<int>>& visited, int i, int j, string& s, int k) {
        if (board[i][j] != s[k]) {
            return false;
        } else if (k == s.length() - 1) {
            return true;
        }
        visited[i][j] = true;
        vector<pair<int, int>> directions{{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
        bool result = false;
        for (const auto& dir: directions) {
            int newi = i + dir.first, newj = j + dir.second;
            if (newi >= 0 && newi < board.size() && newj >= 0 && newj < board[0].size()) {
                if (!visited[newi][newj]) {
                    bool flag = check(board, visited, newi, newj, s, k + 1);
                    if (flag) {
                        result = true;
                        break;
                    }
                }
            }
        }
        visited[i][j] = false;
        return result;
    }

    bool exist(vector<vector<char>>& board, string word) {
        int h = board.size(), w = board[0].size();
        vector<vector<int>> visited(h, vector<int>(w));
        for (int i = 0; i < h; i++) {
            for (int j = 0; j < w; j++) {
                bool flag = check(board, visited, i, j, word, 0);
                if (flag) {
                    return true;
                }
            }
        }
        return false;
    }
};


分割回文串

两个做法其实都有一个核心问题。如果假设有串aabd,会进入两种递归[a][a],[aa],然后都会进入对b以及后面回文串得判断,其实这种时候就需要记忆化或者预处理了,这也是两种方法得区别之处

做法一:预处理回文串,然后递归加回溯即可

class Solution {
public:
    vector<vector<int>>f;
    vector<vector<string>>ret;
    vector<string> ans;
    int n;
    void dfs(const string& s,int i)
    {
        if(i==n)
        {
            ret.push_back(ans);
            return;
        }
        for(int j=i;j<n;j++)
        {
            if(f[i][j])
            {
                ans.push_back(s.substr(i,j-i+1));
                dfs(s,j+1);
                ans.pop_back();
            }
        }
    }
    vector<vector<string>> partition(string s) {
        n=s.size();
        f.assign(n,vector<int>(n,true));
        for(int i=n-1;i>=0;i--)
        {
            for(int j=i+1;j<n;j++)f[i][j]=(s[i]==s[j])&&f[i+1][j-1];
        }
        dfs(s,0);
        return ret;
    }
};

做法二:记忆化回溯即可

class Solution {
public:
    vector<vector<int>> f;
    vector<vector<string>>ret;
    vector<string> ans;
    int n;
    void dfs(string &s,int i)
    {
        if(i==n)
        {
            ret.push_back(ans);
            return;
        }
        for(int j=i;j<n;j++)
        {
            if(ispal(s,i,j)==1)
            {
                ans.push_back(s.substr(i,j-i+1));
                dfs(s,j+1);
                ans.pop_back();
            }
        }
    }
    int ispal(string &s,int i,int j)
    {
        if(f[i][j])return f[i][j];
        if(i>=j)return f[i][j]=1;
        return f[i][j]=(s[i]==s[j]?ispal(s,i+1,j-1):-1);
    }
    vector<vector<string>> partition(string s) {
        n=s.size();
        f.assign(n,vector<int>(n));
        dfs(s,0);
        return ret;
    }
};

N皇后

做法:经典经典经典。但也有变化,大一的时候用bool函数写,现在则是用哈希表了

class Solution {
public:
    vector<vector<string>> solveNQueens(int n) {
        vector<vector<string>> solutions;
        vector<int>queens(n,-1);
        unordered_set<int> columns;
        unordered_set<int> diagonals1;
        unordered_set<int> diagonals2;
        dfs(solutions,queens,n,0,columns,diagonals1,diagonals2);
        return solutions;
    }
    void dfs(vector<vector<string>>& solutions,vector<int>& queens,int n,int row,unordered_set<int>& columns,unordered_set<int>&diagonals1,unordered_set<int>& diagonals2)
    {
        if(row==n)
        {
            vector<string> board=generate(queens,n);
            solutions.push_back(board);
        }
        else
        {
            for(int i=0;i<n;i++)
            {
                if(columns.find(i)!=columns.end())continue;
                int diagonal1=row-i;
                if(diagonals1.find(diagonal1)!=diagonals1.end())continue;
                int diagonal2=row+i;
                if(diagonals2.find(diagonal2)!=diagonals2.end())continue;
                queens[row]=i;
                columns.insert(i);
                diagonals1.insert(diagonal1);
                diagonals2.insert(diagonal2);
                dfs(solutions,queens,n,row+1,columns,diagonals1,diagonals2);
                queens[row]=-1;
                columns.erase(i);
                diagonals1.erase(diagonal1);
                diagonals2.erase(diagonal2);
            }
        }
    }
    vector<string> generate(vector<int>& queens,int n)
    {
        vector<string> board;
        for(int i=0;i<n;i++)
        {
            string row=string(n,'.');
            row[queens[i]]='Q';
            board.push_back(row);
        }
        return board;
    }
};

由于今日出游,加上确实不可能一天全部时间all in算法了,所以刷题会变少,希望能提高效率,珍惜时间吧,最好能在清明节后一两天内刷完hot100,然后进行复习

http://www.dtcms.com/a/111748.html

相关文章:

  • 【学Rust写CAD】30 Alpha256结构体补充方法(alpha256.rs)
  • 人工智能在前端开发中的应用探索
  • php8 ?-> nullsafe 操作符 使用教程
  • YOLO目标检测系列
  • 指令补充+样式绑定+计算属性+监听器
  • 鸿蒙 —— 系统图标大全
  • NLP高频面试题(三十六)——深入理解思维链(Chain-of-Thought)提示方法
  • Obsidian按下三个横线不能出现文档属性
  • 鸿蒙 —— 关系型数据库
  • 本节课课堂总结
  • Linux系统编程:进程管理、内存对比与树莓派应用
  • 【AI学习】MCP的简单快速理解
  • 解决backtrader框架下日志ValueError: I/O operation on closed file.报错(jupyternotebook)
  • el-table固定表头,动态计算高度
  • 基础IO(linux)
  • 公司论坛数据构建情感标注数据集思考
  • 使用minio客户端mc工具迁移指定文件到本地
  • C++设计模式-策略模式:从基本介绍,内部原理、应用场景、使用方法,常见问题和解决方案进行深度解析
  • [GN] Python3基本数据类型 -- 与C的差异
  • 灭火器离位检测:智能视觉守护安全
  • Java异步编程实战:线框-管道模型的设计与实现
  • LabVIEW 中数字转字符串常用汇总
  • MoE Align Sort在医院AI医疗领域的前景分析(代码版)
  • Linux错误(6)X64向量指令访问地址未对齐引起SIGSEGV
  • 光流 | Farneback、Horn-Schunck、Lucas-Kanade、Lucas-Kanade DoG四种光流算法对比(附matlab源码)
  • web漏洞靶场学习分享
  • 19685 握手问题
  • 恒盾C#混淆加密卫士 - 混淆加密保护C#程序
  • 基于DrissionPage的Taptap热门游戏数据爬虫实战:从Requests到现代爬虫框架的迁移指南(含完整代码复制)
  • QML输入控件: TextArea的样式定制