leetcode第311场周赛题解

最小偶倍数

最小偶倍数
给你一个正整数 n ,返回 2 和 n 的最小公倍数(正整数)。

思路:当n是奇数的时候最小公倍数等于2 * n,否则为n。

也可以用lcm模板来写,代码如下:

int gcd(int a, int b)
{
    if(!b) return a;
    return gcd(b, a % b);
}

class Solution {
public:
    int smallestEvenMultiple(int n) {
        return 2 * n / gcd(2, n);
    }
};

最长的字母序连续子字符串

最长的字母序连续子字符串

考点:遍历。注意:这不是双指针算法,双指针一般指维护一段滑动窗口的算法。

思路:不断枚举起点,然后统计这个起点的最长属性。统计完后跳过这段区间。
在这里插入图片描述

ac代码:

class Solution {
public:
    int longestContinuousSubstring(string s) {
        int res = 0;
        for(int i = 0; i < s.size(); i++)
        {
            int j = i + 1;//终点
            while(j < s.size() && s[j - 1] + 1 == s[j]) j++;//满足性质,j终点往后移动
            res = max(res, j - i);//i - j - 1的长度,实际上就是j - 1 - i + 1
            i = j - 1;//起点跳到终点
        }
        return res;
    }
};

翻转奇数层二叉树

翻转奇数层二叉树

考点:dfs搜索/bfs搜索。注意:这里的翻转指的是镜像翻转,也就是reverse。
比如123456变成654321,而不是214354

bfs方法:可以用层序遍历的方法,当遍历到奇数层,那么就进行reverse操作。如果是偶数层就不管。

bfs的ac代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void bfs(TreeNode* a)
    {
        int levels = 0;
        queue<TreeNode*> q;
        q.push(a);
        while(!q.empty())
        {
        	由于这里要知道是否到达下一层,因此要记录一下一层的大小
            int sz = q.size();
            vector<TreeNode*> v;用来存这一层的所有结点
            for(int i = 0; i < sz; i++)
            {
                TreeNode* t = q.front();
                q.pop();
                if(t->left) q.push(t->left), v.push_back(t->left);
                if(t->right) q.push(t->right), v.push_back(t->right);
            }
            levels++;
            if(levels % 2)
            {
                int l = 0, r = v.size() - 1;
                while(l < r)
                {
                    swap(v[l]->val, v[r]->val);
                    l++, r--;
                }
            }
        }
    }
    TreeNode* reverseOddLevels(TreeNode* root) {
        bfs(root);
        return root;
    }
};

dfs思路:和翻转二叉树思路一样,在这基础上加上是奇数层才翻转这个条件。

注意:翻转的时候由于要达到reverse的效果,因此应该是a的左子树和b的右子树交换,a的右子树和b的左子树交换。
在这里插入图片描述

ac代码:

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode() : val(0), left(nullptr), right(nullptr) {}
 *     TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
 *     TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
 * };
 */
class Solution {
public:
    void dfs(TreeNode* a, TreeNode* b, int level)
    {
        if(!a) return;

        if(level % 2) swap(a->val, b->val);

        dfs(a->left, b->right, level + 1);
        dfs(a->right, b->left, level + 1);
    }
    TreeNode* reverseOddLevels(TreeNode* root) {
        dfs(root->left, root->right, 1);
        return root;
    }
};

两种方法效率差不多。

字符串的前缀分数和

字符串的前缀分数和述

考点:trie树。trie树是以字符串前缀来储存大量字符串的。是一种能够高效存储和查找字符串集合的数据结构。

看到字符串前缀可以考虑使用trie。

案例演示:
在这里插入图片描述
若以每一个字符当成结束标志,用trie分析:数字代表以当前字母结尾的字符串有多少个。 比如ab=2代表以ab为前缀的字符串有两个。分别是ab和abc。又比如a=2代表以a为前缀的字符串有两个,分别是ab和abc。
在这里插入图片描述

如果用trie本身的结束标志来解释的话,就是当前以该字母的字符串出现了多少次。而出现了一次就代表它肯定是作为了某一个字符串的前缀出现了,因此以它为前缀的次数可以加1

ac代码:

const int N = 1000010;

struct Node
{
    Node* ne[26];
    int cnt;

    Node()
    {
        memset(ne, 0, sizeof ne);
        cnt = 0;
    }
};

class Solution {
public:
    vector<int> sumPrefixScores(vector<string>& words) {
        Node *root = new Node;

        for(auto word : words)
        {
            Node* p = root;
            for(auto ch : word)
            {
                if(!p->ne[ch - 'a']) p->ne[ch - 'a'] = new Node;
                p = p->ne[ch - 'a'];
                每个字符都要cnt++
                p->cnt++;
            }
        }

        vector<int> v;
        for(auto word : words)
        {
            Node* p = root;
            int res = 0;
            for(auto ch : word)
            {
                p = p->ne[ch - 'a'];
                res += p->cnt;
            }
            v.push_back(res);
        }
        return v;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
引用\[1\]:这段代码是一个解决LeetCode上某个题目的C++实现,具体是一个双指针的解法。该题目是计算一个数组中的积水量。代码中使用了两个指针分别指向数组的左右边界,然后通过比较左右指针所指向的元素的大小,来确定当前位置的积水量。具体的计算方法是,如果左指针所指向的元素小于右指针所指向的元素,则对左指针的左边进行操作,如果左指针所指向的元素大于等于右指针所指向的元素,则对右指针的右边进行操作。在每一次操作中,都会更新左边的最大值和右边的最大值,并计算当前位置的积水量。最后返回总的积水量。\[1\] 引用\[2\]:这段代码是另一个解决LeetCode上某个题目的C++实现,具体是一个深度优先搜索的解法。该题目是计算一个二维网格中从起点到终点的可行路径数量。代码中使用了递归的方式进行深度优先搜索,从起点开始,每次向下或向右移动一步,直到到达终点。在每一步移动中,会判断当前位置是否有障碍物,如果有障碍物则返回0,如果到达终点则返回1,否则继续递归搜索下一步的位置。最后返回总的可行路径数量。\[2\] 引用\[3\]:这段代码是另一个解决LeetCode上某个题目的C++实现,具体是一个动态规划的解法。该题目是计算一个数组中的积水量。代码中使用了动态规划的思想,通过遍历数组中的每个元素,分别计算该元素左边和右边的最大值,并计算当前位置的积水量。最后返回总的积水量。\[3\] 综上所述,这三段代码分别是解决LeetCode上不同题目的C++实现,分别使用了双指针、深度优先搜索和动态规划的方法来解决问题。 #### 引用[.reference_title] - *1* *3* [Leetcode 热题100 42.接雨水(C++ 多种解法,错过可惜)](https://blog.csdn.net/qq_51933234/article/details/124637883)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [[C++]Leetcode 不同路径 || 解题思路及详解](https://blog.csdn.net/weixin_62712365/article/details/123951736)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down28v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值