手把手带你刷LeetCode-------爱学习的饲养员[c++版](算法篇)

算法1.双指针

LeetCode141.环形链表
给定一个链表,判断链表中是否有环。
如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。注意:pos 不作为参数进行传递,仅仅是为了标识链表的实际情况。
如果链表中存在环,则返回 true 。 否则,返回 false 。

进阶:
你能用 O(1)(即,常量)内存解决此问题吗?
示例 1:
在这里插入图片描述
输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

class Solution {
public:
    bool hasCycle(ListNode *head) {
        if(head == NULL){
            return false;
        }
        ListNode *slow = head;
        ListNode *fast = head;
        while(fast != NULL && fast -> next != NULL){
            slow = slow -> next;
            fast = fast -> next -> next;
            if(slow == fast)
                return true;
        }
        return false;
    }
};

LeetCode881.救生艇
第 i 个人的体重为 people[i],每艘船可以承载的最大重量为 limit。
每艘船最多可同时载两人,但条件是这些人的重量之和最多为 limit。
返回载到每一个人所需的最小船数。(保证每个人都能被船载)。

示例 1:
输入:people = [1,2], limit = 3
输出:1
解释:1 艘船载 (1, 2)。

class Solution {
public:
    int numRescueBoats(vector<int>& people, int limit){
        if(people.size() == 0)
            return 0;
        int result = 0;
        sort(people.begin(),people.end());
        int i = 0,j = people.size() - 1;
        while(i <= j){
            if(people[i] + people[j] <= limit){
                i++;
            }
            j--;
            result++;
        }
        return result;
    }
};

算法2.二分查找法

LeetCode704.二分查找
给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1。

示例 1:
输入: nums = [-1,0,3,5,9,12], target = 9
输出: 4
解释: 9 出现在 nums 中并且下标为 4

class Solution {
public:
    int search(vector<int>& nums, int target) {
        if(nums.size() == 0){
            return -1;
        }
        int l = 0,r = nums.size() - 1;
        while(l <= r){
            int mid = l + (r - l) / 2;
            if(nums[mid] == target){
                return mid;
            }else if(nums[mid] > target){
                r = mid - 1;
            }else{
                l = mid + 1;
            }
        }
        return -1;
    }
};

LeetCode35.搜索插入位置
给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。
你可以假设数组中无重复元素。

示例 1:
输入: [1,3,5,6], 5
输出: 2

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        if(nums.size() == 0){
            return 0;
        }
        int l = 0,r = nums.size() - 1,result;
        while(l < r){
            int mid = l + (r - l) / 2;
            if(nums[mid] == target){
                return mid;
            }else if(nums[mid] > target){
                r = mid;
            }else{
                l = mid + 1;
            }
        }
        return nums[l] < target?l + 1:l;
    }
};

LeetCode162. 寻找峰值
峰值元素是指其值大于左右相邻值的元素。
给你一个输入数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。
你可以假设 nums[-1] = nums[n] = -∞ 。

示例 1:
输入:nums = [1,2,3,1]
输出:2
解释:3 是峰值元素,你的函数应该返回其索引 2。

class Solution {
public:
    int findPeakElement(vector<int>& nums) 
    {
        if(nums.size() == 1)
            return 0;
        int left = 0,right = nums.size() - 1,mid;
        while(left < right)
        {
            mid = left + (right - left) / 2;
            if(nums[mid] > nums[mid + 1])
            {
                right = mid;
            }
            else
            {
                left = mid + 1;
            }
        }
        return left;
    }
};

算法3.滑动窗口

LeetCode209.长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。
找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl+1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。

示例 1:
输入:target = 7, nums = [2,3,1,2,4,3]
输出:2
解释:子数组 [4,3] 是该条件下的长度最小的子数组。

class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int i = 0,j = 0,n = nums.size(),result = n + 1,sum = 0;
        while(j < n){
            sum += nums[j];
            while(sum >= target){
                result = min(result,j - i + 1);
                sum -= nums[i];
                i++;
            }
            j++;
        }
        return result == n + 1?0:result;
    }
};

LeetCode1456.定长子串中元音的最大数目
给你字符串 s 和整数 k 。
请返回字符串 s 中长度为 k 的单个子字符串中可能包含的最大元音字母数。
英文中的 元音字母 为(a, e, i, o, u)。

示例 1:
输入:s = "abciiidef", k = 3
输出:3
解释:子字符串 "iii" 包含 3 个元音字母。

class Solution {
public:
    int maxVowels(string s, int k) {
        if(s.size() == 0 || s.size() < k){
            return 0;
        }
        unordered_set<char> st = {'a','e','i','o','u'};
        int i,result = 0,count = 0;
        for(i = 0;i < k;i++){
            if(st.find(s[i]) != st.end()){
                count++;
            }
        }
        result = max(result,count);
        for(i = k;i < s.size();i++){
            if(st.find(s[i - k]) != st.end()){
                count--;
            }
            if(st.find(s[i]) != st.end()){
                count++;
            }
            result = max(result,count);
        }
        return result;
    }
};

算法4.递归

LeetCode509.斐波那契数
斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
给你 n ,请计算 F(n) 。

示例 1:
输入:2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1

class Solution {
public:
    int fib(int n) {
        if(n < 2){
            return n == 1?1:0;
        }
        int sum = fib(n - 1) + fib(n - 2);
        return sum;
    }
};

LeetCode206.反转链表
给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:
image

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        if(head == nullptr || head -> next == nullptr){
            return head;
        }
        ListNode* p = reverseList(head -> next);
        head -> next -> next = head;
        head -> next = NULL;
        return p;
    }
};

LeetCode344.反转字符串
编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 char[] 的形式给出。
不要给另外的数组分配额外的空间,你必须原地修改输入数组、使用 O(1) 的额外空间解决这一问题。
你可以假设数组中的所有字符都是 ASCII 码表中的可打印字符。

示例 1:
输入:["h","e","l","l","o"]
输出:["o","l","l","e","h"]

class Solution {
public:
    void recursion(vector<char>& s,int left,int right){
        if(left >= right){
            return;
        }
        recursion(s,left + 1,right - 1);
        int temp = s[left];
        s[left] = s[right];
        s[right] = temp;
    }
    void reverseString(vector<char>& s) {
        if(s.size() == 0){
            return;
        }
        int left = 0,right = s.size() - 1;
        recursion(s,left,right);
    }
};

算法5.分治法

LeetCode169.多数元素
给定一个大小为 n 的数组,找到其中的多数元素。多数元素是指在数组中出现次数 大于 ⌊ n/2 ⌋ 的元素。
你可以假设数组是非空的,并且给定的数组总是存在多数元素。

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

class Solution {
public:
    int majorityElement(vector<int>& nums) 
    {
        return getMajority(nums,0,nums.size() - 1);
    }
    int getMajority(vector<int>&nums,int left,int right)
    {
        if(left == right)
            return nums[left];
        int mid = left + (right - left) / 2;
        int leftMajority = getMajority(nums,left,mid);
        int rightMajority = getMajority(nums,mid + 1,right);
        if(leftMajority == rightMajority)
            return leftMajority;
        int leftcount = 0,rightcount = 0;
        for(int i = left;i <= right;i++)
        {
            if(nums[i] == leftMajority)
            {
                leftcount++;
            }
            else if(nums[i] == rightMajority)
            {
                rightcount++;
            }  
        }
        if(leftcount > rightcount)
        { 
            return leftMajority;
        }
        else
        {
            return rightMajority;
        }
    }
};

LeetCode53.最大子序和
给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

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

class Solution {
private:
    int getMax(vector<int>& nums,int left,int right){
        if(left == right){
            return nums[left];
        }
        int mid = left + (right - left) / 2;
        int leftMax = getMax(nums,left,mid);
        int rightMax = getMax(nums,mid + 1,right);
        int crossMax = getCrossMax(nums,left,right);
        return max(max(leftMax,rightMax),crossMax);
    }
    int getCrossMax(vector<int>& nums,int left,int right){
        int mid = left + (right - left) / 2;
        int leftSum = nums[mid];
        int leftMax = leftSum;
        for(int i = mid - 1;i >= left;i--){
            leftSum +=nums[i];
            leftMax = max(leftMax,leftSum);
        }
    int rightSum = nums[mid + 1];
    int rightMax = rightSum;
    for(int i = mid + 2;i <= right;i++){
        rightSum += nums[i];
        rightMax = max(rightMax,rightSum);
    }
    return leftMax + rightMax;
    }
public:
    int maxSubArray(vector<int>& nums) {
        return getMax(nums,0,nums.size() - 1);
    }
};

算法6.回溯法

LeetCode22. 括号生成
数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

示例 1:
输入:n = 3
输出:["((()))","(()())","(())()","()(())","()()()"]

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

LeetCode78. 子集
给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的子集(幂集)。
解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。

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

三种解法:
1.扩展法

class Solution {
public:
    vector<vector<int>> subsets(vector<int>& nums) {
        vector<vector<int>>result;
        result.push_back(*new vector<int>());
        for(int num:nums){
            vector<vector<int>> subset;
            for(auto res:result){
                vector<int> temp = *new vector<int>(res);
                temp.push_back(num);
                subset.push_back(temp);
            }
            for(auto t:subset){
                result.push_back(t);
                }
        }
        return result;
    }
};

2.回溯法

class Solution {
public:
    vector<vector<int>>result;
    void backtracking(vector<int> nums,int length,int index,vector<int> subset){
        if(subset.size() == length){
            vector<int> temp = *new vector<int>(subset);
            result.push_back(temp);
            return;
        }
        for(int i = index;i < nums.size();i++){
            subset.push_back(nums[i]);
            backtracking(nums,length,i+1,subset);
            subset.pop_back();
        }
    }
    vector<vector<int>> subsets(vector<int>& nums) {
        result.push_back(*new vector<int>());
        for(int i = 1;i <= nums.size();i++){
            backtracking(nums,i,0,*new vector<int>());
        }
        return result;
    }
};

3.dfs

class Solution {
public:
    vector<vector<int>>result;
    vector<vector<int>> subsets(vector<int>& nums) {
        dfs(nums,0,*new vector<int>());
        return result;
    }
    void dfs(vector<int>& nums,int index,vector<int> subset){
        result.push_back(subset);
        if(index == nums.size()){
            return;
        }
        for(int i = index;i < nums.size();i++){
            subset.push_back(nums[i]);
            dfs(nums,i + 1,subset);
            subset.pop_back();
        }
    }
};

算法7.深度优先搜索算法DFS

LeetCode938.二叉搜索树的范围和
给定二叉搜索树的根结点 root,返回值位于范围 [low, high] 之间的所有结点的值的和。

示例 1:
输入:root = [10,5,15,3,7,null,18], low = 7, high = 15
输出:32
1.递归法

class Solution {
public:
    int rangeSumBST(TreeNode* root, int low, int high){
        if(root == nullptr)
            return 0;
        int leftsum = rangeSumBST(root -> left,low,high);
        int rightsum = rangeSumBST(root -> right,low,high);
        int result = leftsum + rightsum;
        if(root -> val >= low && root -> val <= high)
            result = result + root -> val;
        return result;
    }
};

2.BFS

class Solution {
public:
    int rangeSumBST(TreeNode* root, int low, int high) 
    {
        int result = 0;
        queue<TreeNode*>q;
        q.push(root);
        while(q.size()>0)
        {
            int size = q.size();
            while(size > 0)
            {
                auto cur = q.front();
                q.pop();
                if(cur -> val >= low && cur ->val <= high)
                {
                    result += cur -> val;
                }
                if(cur -> left != NULL)
                {
                    q.push(cur -> left);
                }
                if(cur -> right != NULL)
                {
                    q.push(cur -> right);
                }
                size--;
            }
        }
        return result;
    }
};

3.DFS

class Solution {
public:
    int rangeSumBST(TreeNode* root, int low, int high) {
        if(root == nullptr)
            return 0;
        if(root -> val > high)                          //比high值大就去左子树,寻找比high小的值
            return rangeSumBST(root -> left,low,high);
        if(root -> val < low)                           //比low值小就去右子树,寻找比low大的值
            return rangeSumBST(root -> right,low,high);
        return root -> val + rangeSumBST(root -> left,low,high) + rangeSumBST(root -> right,low,high);  //将符合条件的值相加即得结果
    }
};

算法8.广度优先搜索算法BFS

LeetCode102. 二叉树的层序遍历
给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)。
示例:
二叉树:[3,9,20,null,null,15,7],
3
/
9 20
/
15 7
返回其层序遍历结果:

[
[3],
[9,20],
[15,7]
]
1.BFS

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) 
    {
        vector<vector<int>> result;
        if(root == nullptr)
            return result;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty())
        {
            int size = q.size();
            result.push_back(vector<int>());
            for(int i = 0;i < size;i++)
            {
                auto temp = q.front();
                q.pop();
                result.back().push_back(temp -> val);
                if(temp -> left != NULL)
                {
                    q.push(temp -> left);
                }
                if(temp -> right != NULL)
                {
                    q.push(temp -> right);
                }
            }
        }
        return result;
    }
};

2.DFS

class Solution {
public:
    void dfs(TreeNode *node,vector<vector<int>>&result,int level)
    {
        if(node == nullptr)
            return;
        if(level >= result.size())
            result.push_back(vector<int>());
        result[level].push_back(node -> val);
        if(node -> left != NULL)
            dfs(node -> left,result,level + 1);
        if(node -> right != NULL)
            dfs(node -> right,result,level + 1);
    }
    vector<vector<int>> levelOrder(TreeNode* root) 
    {
        vector<vector<int>>result;
        if(root == nullptr)
            return result;
        dfs(root,result,0);
        return result;
    }
};

算法9.并查集

LeetCode200. 岛屿数量
给你一个由 '1'(陆地)和 '0'(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。

示例 1:
输入:grid = [
["1","1","1","1","0"],
["1","1","0","1","0"],
["1","1","0","0","0"],
["0","0","0","0","0"]
]
输出:1
1.DFS

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) 
    {
        if(grid[0][0] == NULL || grid.size() == 0)
        {
            return 0;
        }
        int result = 0;
        int row = grid.size();
        int col = grid[0].size();
        for(int i = 0;i < row;i++)
        {
            for(int j = 0;j < col;j++)
            {
                if(grid[i][j] == '1')
                {
                    result += 1;
                    dfs(grid,i,j,row,col);
                }
            }
        }
        return result;
    }
    void dfs(vector<vector<char>>&grid,int i,int j,int row,int col)
    {
        if(i < 0 || j < 0 || i >= row || j >= col || grid[i][j] == '0')
            return;
        grid[i][j] = '0';
        dfs(grid,i + 1,j,row,col);
        dfs(grid,i - 1,j,row,col);
        dfs(grid,i,j - 1,row,col);
        dfs(grid,i,j + 1,row,col);
    }
};

2.BFS

class Solution {
public:
    int numIslands(vector<vector<char>>& grid) 
    {
        if(grid[0][0] == NULL || grid.size() == 0)
            return 0;
        int result = 0;
        int row = grid.size();
        int col = grid[0].size();
        queue<pair<int,int>> q;
        for(int i = 0;i < row;i++)
        {
            for(int j = 0;j < col;j++)
            {
                if(grid[i][j] == '1')
                {
                    result += 1;
                    q.push({i,j});
                    grid[i][j] = '0';
                    while(!q.empty())
                    {
                        auto cur = q.front();
                        q.pop();
                        int x = cur.first,y = cur.second;
                        if(x - 1 >= 0 && grid[x - 1][y] == '1')
                        {
                            grid[x - 1][y] = '0';
                            q.push({x - 1,y});
                        }
                        if(y - 1 >= 0 && grid[x][y - 1] == '1')
                        {
                            grid[x][y - 1] = '0';
                            q.push({x,y - 1});
                        }
                        if(x + 1 < row && grid[x + 1][y] == '1')
                        {
                            grid[x + 1][y] = '0';
                            q.push({x + 1,y});
                        }
                        if(y + 1 < col && grid[x][y + 1] == '1')
                        {
                            grid[x][y + 1] = '0';
                            q.push({x ,y + 1});
                        }
                    }
                }
            }
        }
        return result;
    }
};

3.并查集

class UnionFind{
    public:
    UnionFind(vector<vector<char>>& grid)
    {
        int row = grid.size();
        int col = grid[0].size();
        count = row * col;
        root = vector<int>(row * col , 0);
        for(int i = 0; i < row*col; i++) 
        {
            root[i] = i;
        } 
    }
    int find(int x)
    {
        if(x == root[x])
        {
            return x;
        }
        else
        {
            root[x] = find(root[x]);
            return root[x];
        }
    }
    void Union(int x,int y)
    {
        int rootx = find(x);
        int rooty = find(y);
        if(rootx != rooty)
        {
            root[rootx] = rooty;
            count--;
        }
    }
    int getCount()
    {
        return count;
    }
private:
vector<int> root;
int count = 0;
};
        
class Solution {
public:
    int numIslands(vector<vector<char>>& grid) 
    {
        if(!grid.size())
        {
            return 0;
        }
        int row = grid.size();
        int col = grid[0].size();
        int water = 0;
        auto uf  = UnionFind(grid);
        for(int i = 0;i < row;i++)
        {
            for(int j = 0;j < col;j++)
            {
                if(grid[i][j] == '0')
                {
                    water++;
                }
                else
                {
                    vector<vector<int>> directions = {{0, 1}, {0, -1}, {1, 0}, {-1, 0}};
                    for(auto d:directions)
                    {
                        int x = i + d[0];
                        int y = j + d[1];
                        if(x >= 0 && x < row && y >= 0 && y < col && grid[x][y] == '1')
                        {
                            uf.Union(x * col + y,i * col + j);
                        }
                    }
                }
            }
        }
        return uf.getCount() - water;
    }
};

算法10.贪心算法

LeetCode322.零钱兑换
给定不同面额的硬币 coins 和一个总金额 amount。编写一个函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 -1。

你可以认为每种硬币的数量是无限的。
示例 1:
输入:coins = [1, 2, 5], amount = 11
输出:3
解释:11 = 5 + 5 + 1
贪心+动态规划:

class Solution {
public:
    int coinChange(vector<int>& coins, int amount) 
    {
        vector<int>dp(amount + 1, -1);
        dp[0] = 0;
        for(int i = 1;i <= amount;i++)
        {
            for(int j = 0;j < coins.size();j++)
            {
                if(coins[j] <= i && dp[i - coins[j]] != -1)
                {
                    if(dp[i] == -1 || dp[i] > dp[i - coins[j]] + 1)
                    {
                        dp[i] = dp[i - coins[j]] + 1;
                    }
                }
            }
        }
        return dp[amount];
    }
};

算法11.动态规划

LeetCode509.斐波那契数
斐波那契数,通常用 F(n) 表示,形成的序列称为 斐波那契数列 。该数列由 0 和 1 开始,后面的每一项数字都是前面两项数字的和。也就是:
F(0) = 0,F(1) = 1
F(n) = F(n - 1) + F(n - 2),其中 n > 1
给你 n ,请计算 F(n) 。

示例 1:
输入:2
输出:1
解释:F(2) = F(1) + F(0) = 1 + 0 = 1

class Solution {
public:
    int fib(int n) {
        if(n < 2){
            return n == 1?1:0;
        }
        int sum = fib(n - 1) + fib(n - 2);
        return sum;
    }
};

LeetCode62.不同路径
一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。
机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。
问总共有多少条不同的路径?
示例 1:

输入:m = 3, n = 7
输出:28

class Solution {
public:
    int uniquePaths(int m, int n) {
        vector<vector<int>> dp(m + 1,vector<int>(n + 1));
        dp[0][0] = 1;
        dp[0][1] = 1;
        for(int i = 1;i <= m;i++)
        {
            for(int j = 1;j <= n;j++)
            {
                dp[i][j] = dp[i - 1][j] + dp[i][j - 1];
            }
        }
        return dp[m][n];
    }
};

算法12.字典树Trie

LeetCode208.实现Trie(前缀树)
Trie(发音类似 "try")或者说 前缀树 是一种树形数据结构,用于高效地存储和检索字符串数据集中的键。这一数据结构有相当多的应用情景,例如自动补完和拼写检查。
请你实现 Trie 类:
Trie() 初始化前缀树对象。
void insert(String word) 向前缀树中插入字符串 word 。
boolean search(String word) 如果字符串 word 在前缀树中,返回 true(即,在检索之前已经插入);否则,返回 false 。
boolean startsWith(String prefix) 如果之前已经插入的字符串 word 的前缀之一为 prefix ,返回 true ;否则,返回 false 。
 
示例:
输入
["Trie", "insert", "search", "search", "startsWith", "insert", "search"]
[[], ["apple"], ["apple"], ["app"], ["app"], ["app"], ["app"]]
输出
[null, null, true, false, true, null, true]

解释
Trie trie = new Trie();
trie.insert("apple");
trie.search("apple"); // 返回 True
trie.search("app"); // 返回 False
trie.startsWith("app"); // 返回 True
trie.insert("app");
trie.search("app"); // 返回 True

class Trie {
private:
    bool isEnd;
    Trie *next[26];
public:
    /** Initialize your data structure here. */
    Trie() {
        isEnd = false;
        memset(next,0,sizeof(next));
    }
    
    /** Inserts a word into the trie. */
    void insert(string word) {
        Trie *node = this;
        for(char c:word){
            if(node -> next[c - 'a'] == NULL){
                node -> next[c - 'a'] = new Trie();
            }
            node = node -> next[c - 'a'];
        }
        node -> isEnd = true;
    }
    
    /** Returns if the word is in the trie. */
    bool search(string word) {
        Trie *node = this;
        for(char c:word){
            node = node -> next[c - 'a'];
            if(node == NULL){
                return false;
            }
        }
        return node -> isEnd;
    }
    
    /** Returns if there is any word in the trie that starts with the given prefix. */
    bool startsWith(string prefix) {
        Trie *node = this;
        for(char c:prefix){
            node = node -> next[c - 'a'];
            if(node == NULL){
                return false;
            }
        }
        return true;
    }
};
posted @ 2021-06-04 11:35  程序员中最好的渔民  阅读(974)  评论(0)    收藏  举报