15届蓝桥杯备赛(2)

文章目录

  • 刷题笔记(2)
    • 二分查找
      • 在排序数组中查找元素的第一个和最后一个位置
      • 寻找旋转排序数组中的最小值
      • 搜索旋转排序数组
    • 链表
      • 反转链表
      • 反转链表II
    • 二叉树
      • 相同的树
      • 对称二叉树
      • 平衡二叉树
      • 二叉树的右视图
      • 验证二叉搜索树
      • 二叉树的最近公共祖先
      • 二叉搜索树的最近公共祖先
      • 二叉树层序遍历
      • 二叉树的锯齿形层序遍历
      • 找树左下角的值

刷题笔记(2)

二分查找

在排序数组中查找元素的第一个和最后一个位置

[传送门]( 34. 在排序数组中查找元素的第一个和最后一个位置 - 力扣(LeetCode) )

class Solution {
public:

    //求出第一个大于等于target的下标
    int ans(vector<int>& nums, int target)
    {
        int left = 0, right = nums.size() - 1, mid;//左闭右闭区间
        while(left <= right)
        {
            mid = left + (right-left)/2;//先减后加防止溢出
            if(nums[mid] < target)
            {
                left = mid + 1;
            }
            else
            {
                right = mid - 1;
            }
        }

        return left;
    }

    vector<int> searchRange(vector<int>& nums, int target) {
        int start = ans(nums, target);
        if(start == nums.size() || nums[start] != target)
        {
            return {-1, -1};
        }
        int end = ans(nums, target+1) - 1;
        return {start, end};
    }
};

看完灵神讲完这题也算是开眼界了,原来二分查找也不仅仅针对找到target值,其实也能找到>=target或<=target的值。题解的ans函数就是找到该数组第一个>=target的下标,然后就是要搞清return的值是哪个,这里return的是left,因为循环结束之后left是在right的右边一个位置,并且小于left下标所表示的值都是小于target的,那么最终left所指的值就是第一个>=target的下标。在ans函数中mid也是值得注意的:java和C++需要考虑到下标可能溢出的问题,就不能mid = (left+right)/2这样写,而应该mid = left + (right-left)/2这样写,一定是先减后加。

再就是主函数if条件是排出了特殊的情况:①数组中所有数都小于target②数组长度为0③数组中所有数都大于target。再就是求end,end表示最后一个>=target的下标,那么可以转化成第一个>=target+1左边的下标,这就是为什么ans函数后面要-1

寻找旋转排序数组中的最小值

[传送门]( 153. 寻找旋转排序数组中的最小值 - 力扣(LeetCode) )

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

从这一题能够看出,采用二分查找法的题目不一定是有序的,二分查找的模板大致都是相同的,难点主要在需要发现合适的判断条件。这里将数组最后一个元素设置为基准,因为它一定是蓝色的(符合条件的),目标值一定在最后一个数或者是它之前的数,所以遍历的区间在[0,n-2]。

搜索旋转排序数组

[传送门]( 33. 搜索旋转排序数组 - 力扣(LeetCode) )

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

        return -1;
    }
};

这道题解决思路比较粗暴,首先按照上一题的解法求出最小元素的下标,然后将最后一个元素与target进行判断,如果target小于nums[n-1]那么再在最小元素的右边二分查找,反之则在最小元素的左边二分查找,所以我的解法使用了两次二分查找,ac了就偷懒每看解析了,解析肯定没这么复杂…

链表

反转链表

[传送门]( 206. 反转链表 - 力扣(LeetCode) )

解法一:双指针迭代

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* cur = head, *pre = nullptr, *temp;
        while(cur != nullptr)
        {
            temp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = temp;
        }
        return pre;
    }
};

三个需要注意的点:①退出循环的条件②循环体第2,3,4条语句的顺序不能变③最后返回的是pre而不是cur,因为cur退出循环变成nullptr了

解法二:头插法

class Solution {
public:
    ListNode* reverseList(ListNode* head) {
        ListNode* res, *pMove = head;
        res = new ListNode();
        if(pMove == nullptr) return nullptr;
        while(pMove != nullptr)
        {
            ListNode* s = new ListNode;
            s->val = pMove->val;
            s->next = res->next;
            res->next = s;
            pMove = pMove->next;
        }
        return res->next;
    }
};

按照实例的意思,它将所有元素都反序了,所以我们可以重新创建一个有头节点的链表采用头插法存取数据就能达到反转链表的效果。

反转链表II

[传送门]( 92. 反转链表 II - 力扣(LeetCode) )

class Solution {
public:
    ListNode* reverseBetween(ListNode* head, int left, int right) {
        ListNode* dummy = new ListNode(0, head), *p0 = dummy;
        for(int i = 0; i < left-1; i++)
        {
            p0 = p0->next;
        }

        ListNode* pre = nullptr, *cur = p0->next, *temp;
        for(int i = 0; i < right-left+1; i++)
        {
            temp = cur->next;
            cur->next = pre;
            pre = cur;
            cur = temp;
        }
        
        p0->next->next = cur;
        p0->next = pre;

        return dummy->next;
    }
};

这一题需要找到几个关键结点:①遍历开始前一个结点p0②遍历结束后cur和pre所指结点③设置一个哨兵结点指向head之前,用来作为返回值。遍历结束后p0->next->next一定指向cur,p0->next一定指向pre,而且两个书写顺序不能改变,题中所给的left和right就是边界值,就是我们循环的次数,中间反转链表与第一题相同采用双指针迭代的方法。最后注意为哨兵开辟空间的方法new ListNode(0, head);

二叉树

相同的树

[传送门]( 100. 相同的树 - 力扣(LeetCode) )

class Solution {
public:
    bool isSameTree(TreeNode* p, TreeNode* q) {
        if(p == nullptr || q == nullptr) return p == q;
        else
        {
            bool left = isSameTree(p->left, q->left);
            bool right = isSameTree(p->right, q->right);
            return p->val == q->val && left && right;
        }
    }
};

递归题还是得加强理解,现在能分析出递归的边界条件和各个限制条件,但是理解不了这些条件应该放在什么位置,这里递归退出条件写的十分妙,如果是其中一个为nullptr那么返回false,如果都为空那么返回true,如果都为真,那么就继续递归,返回的是当前两个结点val是否相等&&左子树是否相等&&右子树是否相等,自己写的时候没有考虑到当前结点的val是否相等就导致的错误。

对称二叉树

[传送门]( 101. 对称二叉树 - 力扣(LeetCode) )

class Solution {
public:

    bool isSameTree(TreeNode* p, TreeNode* q)
    {
        if(p == nullptr || q == nullptr) return p == q;
        return p->val == q->val && isSameTree(p->left, q->right) && isSameTree(p->right, q->left);
    }

    bool isSymmetric(TreeNode* root) {
        return isSameTree(root->left, root->right);
    }
};

其实这一题和上一题十分相似,只是我们需要换个角度思考一下问题,判断两个树是否相等就是判断当前p、q所指val是否相等&&p左子树是否等于q左子树&&p右子树是否等于q右子树。而看一个树是否对称也就是方向的不同,其他与判断两个树是否相等是一个意思。所以判断对称二叉树的条件是:p、q所指val是否相等&&p左子树是否等于q右子树&&p右子树是否等于q左子树。由于该题函数只有一个root参数,所以我们需要另外写一个函数用来调用即可。

平衡二叉树

[传送门]( 110. 平衡二叉树 - 力扣(LeetCode) )

class Solution {
public:

    int getHeight(TreeNode* p)
    {
        if(p == nullptr) return 0;
        return max(getHeight(p->left), getHeight(p->right)) + 1;
    }

    bool isBalanced(TreeNode* root) {
        if(root == nullptr) return true;
        else
        {
            int x = getHeight(root->left)-getHeight(root->right);
            if( x >= -1 && x <= 1) return isBalanced(root->left) && isBalanced(root->right);//abs(x)等价于x >= -1 && x <= 1
            else return false;
        }
    }
};

这道题是自己独立ac的,就没有看其他的解题思路了。说说我的理解:首先平衡二叉树的定义为该树的所有结点的左右子树深度差不超过1,也就是绝对值小于等于1。首先采用递归的写法定义一个求结点深度的函数,然后再在主函数中递归调用。

二叉树的右视图

[传送门]( 199. 二叉树的右视图 - 力扣(LeetCode) )

class Solution {
public:

    vector<int> ans = {};
    void f(TreeNode* root, int depth)
    {
        if(root == nullptr) return;
        else
        {
            if(ans.size() == depth)
            {
                ans.push_back(root->val);
            }
            f(root->right, depth+1);
            f(root->left, depth+1);
        }
    }

    vector<int> rightSideView(TreeNode* root) {
        f(root, 0);
        return ans;
    }
};

真的是看了大神的题解就是能豁然开朗,做题不能仅仅局限于bfs或者dfs,官方就是用这两种解法看起来相当复杂,因为单纯用那两种方法需要考虑的东西太多,理解起来也就费劲。右视图也就是保存这棵树每一层的最右边一个结点,如何将这个问题比较好的转化成代码呢?定义一个存储结点的数组和一个新函数,函数参数包括结点指针和深度,只要在函数体用一条判断数组长度是否等于树深度就能知道这个结点该不该存在数组里,除此之外,必须要保证该函数一定是先递归的右子树再递归左子树,这样才能保证是每一层的最右边结点存入的数组。这里便于理解就将根节点的深度和数组长度都初始化为0。

验证二叉搜索树

[传送门]( 98. 验证二叉搜索树 - 力扣(LeetCode) )

class Solution {
public:

    bool examTree(TreeNode* root, long l_limit, long r_limit)
    {
        if(root == nullptr) return true;
        else
        {
            if(root->val > l_limit && root->val < r_limit)
            {
                return examTree(root->left, l_limit, root->val) && examTree(root->right, root->val, r_limit);
                
            }
            return false;
        }
    }

    bool isValidBST(TreeNode* root) {
        return examTree(root, LONG_MIN, LONG_MAX);
    }
};

首先要仔细解读题目中所给的二叉搜索树的定义,这些定义就是用来限制的条件,所以我们每当访问一个根节点的时候只需要判断其是否在这个范围之内就行。再就是怎么将这个边界往下传,只需定义一个函数参数分别是root指针和左右边界就行了,每次递归左子树就更新右边界、递归右子树就更新左边界,直到遇到了空结点就表明之前的递归都满足条件,那么就返回true。

二叉树的最近公共祖先

[传送门]( 236. 二叉树的最近公共祖先 - 力扣(LeetCode) )

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root == nullptr || root == p || root == q)
        {
            return root;
        }
        TreeNode* l_left = lowestCommonAncestor(root->left, p, q);
        TreeNode* l_right = lowestCommonAncestor(root->right, p, q);
        if(l_left && l_right)
        {
            return root;
        }
        return l_left ? l_left : l_right;
    }
};

这道题没写出来有两个问题:①读题不仔细:没有从给出的代码中发现p和q是指针类型的②这一道题其实能偶通过分类讨论分析出递归的思路。

在这里插入图片描述

还有,我什么时候才能像题解一样写出这么简洁的题解啊555…分类讨论的形式在代码中能很明白的体现出来,这就是大神的威力啊,狠狠膜拜了。

二叉搜索树的最近公共祖先

[传送门]( 235. 二叉搜索树的最近公共祖先 - 力扣(LeetCode) )

class Solution {
public:
    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
        if(root->val < p->val && root->val < q->val)
        {
            return lowestCommonAncestor(root->right, p, q);
        }
        else if(root->val > p->val && root->val > q->val)
        {
            return lowestCommonAncestor(root->left, p, q);
        }
        return root;
    }
};

这一题刚开始看的时候我发现其实跟上一题的解法可以完全相同,然后我就重新默写了一遍上一题的代码而且能ac,但我仔细一想这一题肯定有不同的解法。题干中写到这是一颗二叉搜索树,我就在想二叉搜索树会有什么性质呢?我想到的是它的中序遍历是一个升序的序列,所以我在想是不是只要递归出第一个处于[p->val,q->val]之间的数,那个数对应的root值就是我想要的答案,结果是我写不出代码。。。看了题解之后发现是从另一角度出发思考的:根节点值严格大于左子树的所有值&&根节点值严格小于右子树所有值,又因为题干中给出p和q是一定存在的,所以整个题只需要分三部分考虑:①根节点值都小于p和q的值,递归右子树②根节点值都大于p和q的值,递归左子树③其他情况返回root根节点即可。

二叉树层序遍历

[传送门]( 102. 二叉树的层序遍历 - 力扣(LeetCode) )

class Solution {
public:
    vector<vector<int>> levelOrder(TreeNode* root) {
        if(root == nullptr) return {};//没有考虑特殊情况,测试样例不能通过
        vector<vector<int>> v;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty())
        {
            vector<int> temp;
            int n = q.size();
            for(int i = 0; i < n; i++)
            {
                if(q.front()->left) q.push(q.front()->left);
                if(q.front()->right) q.push(q.front()->right);
                temp.push_back(q.front()->val);
                q.pop();
            }
            v.push_back(temp);
        }
        return v;
    }
};

这一道题唯一卡住我思路的地方就是返回的是一个二维数组,如果是一个一维数组,那很好办用一个队列即可。可是这里的二维数组硬是卡着我不知道怎么打码,仔细点来说就是我不知道如何按层存取二叉树里的元素。看了一眼解决方法我就直到如何写了,脑子就是一时间转不过来,唉。方法就是嵌套循环,外层循环是队列为空退出为条件,内层循环只需遍历该层的个数次就行了。可是这么写少考虑到了一种情况,也就是如果该二叉树为空,循环里面会报错(出现空指针的操作)导致测试用例不能通过,不要问是谁漏了,问就是我漏了。

二叉树的锯齿形层序遍历

[传送门]( 103. 二叉树的锯齿形层序遍历 - 力扣(LeetCode) )

自己写的:

class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        if(root == nullptr) return {};
        deque<TreeNode*> d;
        vector<vector<int>> v;
        d.push_back(root);
        int flag = 1;//1表示从左往右,-1表示从右往左
        while(!d.empty())
        {
            int n = d.size(), i;
            vector<int> temp;
            if(flag == 1)
            {
                for(i = 0; i < n; i++)
                {
                    if(d.front()->left) d.push_back(d.front()->left);
                    if(d.front()->right) d.push_back(d.front()->right);
                    temp.push_back(d.front()->val);
                    d.pop_front();
                }
            }
            else if(flag == -1)
            {
                for(i = 0; i < n; i++)
                {
                    if(d.back()->right) d.push_front(d.back()->right);
                    if(d.back()->left) d.push_front(d.back()->left);
                    temp.push_back(d.back()->val);
                    d.pop_back();
                }
            }
            v.push_back(temp);
            flag = -flag;
        }
        return v;
    }
};

大佬写的:

class Solution {
public:
    vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
        if(root == nullptr) return {};
        vector<vector<int>> v;
        queue<TreeNode*> q;
        q.push(root);
        for(int flag = false; !q.empty(); flag = !flag)
        {
            vector<int> temp;
            for(int i = q.size(); i > 0; i--)
            {
                TreeNode* node = q.front();
                if(node->left) q.push(node->left);
                if(node->right) q.push(node->right);
                temp.push_back(node->val);
                q.pop();
            }
            if(flag) reverse(temp.begin(), temp.end());
            v.push_back(temp);
        }
        return v;
    }
};

大佬写的代码就是简洁高效啊,实在是佩服。我的代码的思路是:想到这题和二叉树层序遍历之间只多了一个遍历顺序的条件,所以我就先按照层序遍历的写法写,flag是用来判断该层是用从左往右还是从右往左,还有,考虑到需要一个数据结构能对其进行两端操作的队列,这里我就用到了双端队列,它能对首尾插入和删除。

再看到优化的代码:第一个循环用的for,这是我从未见过的一种写法,是在是巧妙,就相当于我的while和if条件写在一起了。再就是存取每层数据时它不是对队列进行改变,而是对临时数组进行反转函数reverse,它用一行代替了我两个for循环,天呐这这么想到的…

本人就爱写点发牢骚的话hahahaha反正也没什么人看。

找树左下角的值

[传送门]( 513. 找树左下角的值 - 力扣(LeetCode) )

自己的解法:

class Solution {
public:

    vector<vector<int>> orderResearch(TreeNode* root)
    {
        vector<vector<int>> v;
        queue<TreeNode*> q;
        q.push(root);
        while(!q.empty())
        {
            vector<int> temp;
            for(int i = q.size(); i > 0; i--)
            {
                TreeNode* node = q.front();
                if(node->left) q.push(node->left);
                if(node->right) q.push(node->right);
                temp.push_back(node->val);
                q.pop();
            }
            v.push_back(temp);
        }
        return v;
    }

    int findBottomLeftValue(TreeNode* root) {
        vector<vector<int>> v = orderResearch(root);
        return v[v.size()-1][0];
    }
};

想到前两题返回的都是层序遍历的结果,我就在想,树左下角的值不就是最后一层的第一个值吗,我就重新写了一个层序遍历的函数并返回二维数组,结果就是v[v.size()-1] [0]。v.size()的值表示v的行数

解法二:

class Solution {
public:
    int findBottomLeftValue(TreeNode* root) {
        queue<TreeNode*> q;
        TreeNode* node;
        q.push(root);
        while(!q.empty())
        {
            node = q.front();
            if(node->right) q.push(node->right);
            if(node->left) q.push(node->left);
            q.pop();
        }
        return node->val;
    }
};

看上去就是普通的层序遍历吗?不,这里不同在两个if的顺序,我们正常的层序遍历是从左至右所以是先node->left再node->right,这样最后一个元素是最右下角的元素,该题是要求出最左下角的元素,那么我们只需要改两个if条件的顺序就能达到题目的意思啦

解法三:

class Solution {
public:
    
    vector<int> v = {};

    void func(TreeNode* root, int depth)
    {
        if(root == nullptr) return;
        if(depth == v.size())
        {
            v.push_back(root->val);
        }
        func(root->left, depth+1);
        func(root->right, depth+1);
    }
    
    int findBottomLeftValue(TreeNode* root) {
        func(root, 0);
        return v[v.size()-1];
    }
};

这个解法来自于评论区的朋友,看到了这样的评论"可以考虑二叉树的左视图,然后返回左视图的最后一个元素",左视图?怎么这么熟悉,哦!原来我写过右视图,然后我大脑迅速运转回顾右视图该怎么写,由于参数的限定,这里需要重新定义一个函数和一个全局的数组v并初始化为空,函数的参数为root指针和整形depth表示该层的深度(这个depth是跟着递归的,递归到那一层depth也就跟着更新,这里我写的时候没有想到,我将depth也设置为全局变量结果输出的是树中最后一个元素…还是细节决定成败啊),然后就是先调用root->left再调用root->right因为左视图优先看到的是左子树,所以先遍历左子树哦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.kler.cn/a/274441.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

管道(acwing,蓝桥杯,二分)

题目描述&#xff1a; 有一根长度为 len 的横向的管道&#xff0c;该管道按照单位长度分为 len 段&#xff0c;每一段的中央有一个可开关的阀门和一个检测水流的传感器。 一开始管道是空的&#xff0c;位于 Li的阀门会在 Si 时刻打开&#xff0c;并不断让水流入管道。 对于位…

WRF模型运行教程(ububtu系统)--III.运行WRF模型(官网案例)

零、创建DATA目录 # 1.创建一个DATA目录用于存放数据&#xff08;一般为fnl数据&#xff0c;放在Build_WRF目录下&#xff09;。 mkdir DATA # 2.进入 DATA cd DATA 一、WPS预处理 在模拟之前先确定模拟域&#xff08;即模拟范围&#xff09;,并进行数据预处理&#xff08…

我的尝试:Codigger + Vim

若您愿意耐心投入&#xff0c;学习 Vim 的过程其实远比想象中轻松。我对 Vim 产生兴趣&#xff0c;主要是源于它对提升生产力的巨大潜力。我尝试了 Neovim、NvChad 以及 Codigger Vim 插件&#xff0c;如今我的工作效率已远超从前。 那么&#xff0c;Vim 究竟是什么呢&#xff…

Leetcode 79. 单词搜索

心路历程&#xff1a; 做完这道题才发现是回溯&#xff0c;一开始想的是递归&#xff0c;判断完第i个字符后&#xff0c;只需要挨个判断第i1个字符在不在第i个字符的邻域。后来发现由于不能重复使用元素&#xff0c;所以需要维护一个visited列表&#xff0c;并且在遍历所有可能…

【进阶五】Python实现SDVRP(需求拆分)常见求解算法——自适应大邻域算法(ALNS)

基于python语言&#xff0c;采用经典自适应大邻域算法&#xff08;ALNS&#xff09;对 需求拆分车辆路径规划问题&#xff08;SDVRP&#xff09; 进行求解。 目录 往期优质资源1. 适用场景2. 代码调整3. 求解结果4. 代码片段参考 往期优质资源 经过一年多的创作&#xff0c;目前…

Aigtek超声功率放大器产品介绍

超声功率放大器是一种特殊类型的功率放大器&#xff0c;专门用于增强和放大超声信号的功率。它在医疗、工业和科学领域中得到广泛应用。 一、超声功率放大器的基本概述 超声功率放大器是一种能够将低功率超声信号放大到更高功率水平的设备。它是超声系统的关键组成部分&#xf…

力扣1. 两数之和

思路&#xff1a;用一个map存放 已遍历过的元素和下标&#xff1b; 若当前元素是nums[i], 且该元素的另一半 target-nums[i] 在已遍历过的map里面&#xff0c;则返回两个元素的下标&#xff1b; class Solution {public int[] twoSum(int[] nums, int target) {int[] ans new…

腾讯云服务器多少钱1个月?2024一个月收费阿济格IE吧

2024腾讯云服务器多少钱一个月&#xff1f;5元1个月起&#xff0c;腾讯云轻量服务器4核16G12M带宽32元1个月、96元3个月&#xff0c;8核32G22M配置115元一个月、345元3个月&#xff0c;腾讯云轻量应用服务器61元一年折合5元一个月、4核8G12M配置646元15个月、2核4G5M服务器165元…

数据结构:详解【顺序表】的实现

1. 顺序表的定义 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构&#xff0c;一般情况下采用数组存储。动态顺序表与数组的本质区别是——根据需要动态的开辟空间大小。 2. 顺序表的功能 动态顺序表的功能一般有如下几个&#xff1a; 初始化顺序表打印顺序…

PlantUML Integration 编写短信服务类图

PlantUML Integration 写一个类图&#xff0c;主要功能为 1、编写一个serviceSms短信服务类&#xff1b; 2、需要用到短信的地方统一调用基建层的服务即可&#xff1b; 3、可以随意切换、增加短信厂商&#xff0c;不需要更改场景代码&#xff0c;只需要更改application.yml 里面…

Redis数据结构对象中的对象共享、对象的空转时长

对象共享 概述 除了用于实现引用计数内存回收机制之外&#xff0c;对象的引用计数属性还带有对象共享的作用。 在Redis中&#xff0c;让多个键共享同一个值对象需要执行以下两个步骤: 1.将数据库键的值指针指向一个现有的值对象2.将被共享的值对象的引用计数增一 目前来说…

【Godot4.2】2D导航01 - AStar2D及其使用方法

概述 对于2D平台跳跃或飞机大战&#xff0c;以及一些直接用键盘方向键操控玩家的游戏&#xff0c;是根本用不到寻路的&#xff0c;因为只需要检测碰撞就可以了。 但是对于像RTS或战棋这样需要操控玩家到地图指定位置的移动方式&#xff0c;就绝对绕不开寻路了。 导航、碰撞与…

微信小程序接口请求出错:request:fail url not in domain list:xxxxx

一、微信小程序后台和开发者工具配的不一样导致了这个错误 先说结论&#xff1a; 开发者工具配置了https://www.xxx.cn/prod-api/ 微信后台配置了 https://www.xxx.cn 一、最开始 开发者工具配置了https://www.xxx.cn:7500 微信后台配置了 https://www.xxx.cn 报错:reques…

代码随想录算法训练营第53天 | 1143.最长公共子序列 ,1035.不相交的线 ,53. 最大子序和

动态规划章节理论基础&#xff1a; https://programmercarl.com/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92%E7%90%86%E8%AE%BA%E5%9F%BA%E7%A1%80.html 1143.最长公共子序列 题目链接&#xff1a;https://leetcode.cn/problems/longest-common-subsequence/description/ 思路&…

ASP .Net Core ILogger日志服务

&#x1f433;简介 ILogger日志服务是.NET平台中的一个内置服务&#xff0c;主要用于应用程序的日志记录。它提供了灵活的日志记录机制&#xff0c;允许开发者在应用程序中轻松地添加日志功能。以下是其主要特点和组件&#xff1a; ILogger接口&#xff1a;这是ILogger日志服…

电脑数据安全新利器:自动备份文件的重要性与实用方案

一、数据安全的守护神&#xff1a;自动备份文件的重要性 在数字化时代&#xff0c;电脑中的文件承载着我们的工作成果、个人回忆以及众多重要信息。然而&#xff0c;数据丢失的风险无处不在&#xff0c;无论是硬件故障、软件崩溃&#xff0c;还是恶意软件的攻击&#xff0c;都…

JupytetNotebook常用的快捷键

Jupyter Notebook 中常用的快捷键&#xff1a; 切换到命令模式&#xff1a;按 Esc 键。切换到编辑模式&#xff1a;按 Enter 键。运行当前单元格并选择下面的单元格&#xff1a;按 Shift Enter。运行当前单元格并插入新的单元格在下面&#xff1a;按 Alt Enter。删除当前单元…

【Vue3】Vue3中的编程式路由导航 重点!!!

&#x1f497;&#x1f497;&#x1f497;欢迎来到我的博客&#xff0c;你将找到有关如何使用技术解决问题的文章&#xff0c;也会找到某个技术的学习路线。无论你是何种职业&#xff0c;我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章&#xff0c;也欢…

test测试类-变量学习

test测试类 作用&#xff1a;标记到类上成为测试类&#xff0c;标记到方法上成为测试方法 变量&#xff1a;测试类的变量&#xff0c;在测试类括号中应用 1、invocationCount变量 意思是这个方法应该被调用的次数。 在测试框架中&#xff0c;特别是当使用参数化测试或数据驱动…

HarmonyOS(鸿蒙)快速入门

一:下载开发工具 鸿蒙的开发工具叫DevEco 下载点击 其他部分都一直next 就行,这个页面出现的install 建议都点击install 然后单独选择安装目录 可能存在的问题 就是之前安装nodejs&#xff08;比如自己开发web或者RN等情况&#xff09;版本低 等情况 所以建议你单独安装一次 …
最新文章