代码随想录 刷题记录-23 单调栈

news2024/9/21 22:26:12

题目对“下一个更高”或者“下一个更低”有要求,可以考虑单调栈

(也可以考虑双指针,双指针往往能够把时间复杂度的指数减一)

1.739. 每日温度

思路

首先想到的当然是暴力解法,两层for循环,把至少需要等待的天数就搜出来了。时间复杂度是O(n^2)

那么接下来在来看看使用单调栈的解法。

什么时候用单调栈呢?

通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。时间复杂度为O(n)。

例如本题其实就是找找到一个元素右边第一个比自己大的元素,此时就应该想到用单调栈了。

单调栈的原理是什么呢?为什么时间复杂度是O(n)就可以找到每一个元素的右边第一个比它大的元素位置呢?

单调栈的本质是空间换时间,因为在遍历的过程中需要用一个栈来记录右边第一个比当前元素高的元素,优点是整个数组只需要遍历一次。

更直白来说,就是用一个栈来记录我们遍历过的元素,因为我们遍历数组的时候,我们不知道之前都遍历了哪些元素,以至于遍历一个元素找不到是不是之前遍历过一个更小的,所以我们需要用一个容器(这里用单调栈)来记录我们遍历过的元素。

在使用单调栈的时候首先要明确如下几点:

1.单调栈里存放的元素是什么?

单调栈里只需要存放元素的下标i就可以了,如果需要使用对应的元素,直接T[i]就可以获取。

2.单调栈里元素是递增呢? 还是递减呢?

本题中,我们要求的是“下一个更大”,当新元素大于栈内元素时,我们知道新元素就是站内比它小的元素的“下一个更大”,所以只有新元素小于栈顶元素时才可以入栈,维护的是栈顶到栈底非严格递增的栈。

使用单调栈主要有三个判断条件。

  • 当前遍历的元素T[i]小于栈顶元素T[st.top()]的情况
  • 当前遍历的元素T[i]等于栈顶元素T[st.top()]的情况
  • 当前遍历的元素T[i]大于栈顶元素T[st.top()]的情况

把这三种情况分析清楚了,也就理解透彻了

本题图解参考:739每日温度单调栈图解

单调栈递增(从栈口到栈底顺序),就是求右边第一个比自己大的,单调栈递减的话,就是求右边第一个比自己小的。

代码如下:

class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        int[] result = new int[temperatures.length];
        Deque<Integer> stack = new ArrayDeque<>();
        stack.push(0);
        for(int i = 1 ; i < temperatures.length ;i++){
            if(temperatures[stack.peek()] >= temperatures[i]){
                stack.push(i);
            }else{
                while(!stack.isEmpty() && temperatures[stack.peek()]< temperatures[i]){
                    result[stack.peek()] = i - stack.pop();
                }
                stack.push(i);
            }
        }

        while(!stack.isEmpty()){
            result[stack.pop()] = 0;
        }
        return result;
    }
}

2.496.下一个更大元素 I

暴力搜索:

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int[] res = new int[nums1.length];
        for(int i = 0 ; i < nums1.length ; i++){
            res[i] = -1;
        }
        for(int i = 0 ; i < nums1.length ; i++){
            for(int j = 0 ; j < nums2.length ; j++){
                if(nums1[i] == nums2[j]){
                    for(int k = j+1 ; k < nums2.length ; k++){
                        if(nums1[i] < nums2[k]){
                            res[i] = nums2[k];
                            break;
                        }
                    }
                    break;
                }
            }
        }
        return res;
    }
}

由于题目要求求的是“下一个更大”,考虑使用单调栈降低时间复杂度

从题目示例中我们可以看出最后是要求nums1的每个元素在nums2中下一个比当前元素大的元素,那么就要定义一个和nums1一样大小的数组result来存放结果。

这个result数组初始化应该为多少呢?

题目说如果不存在对应位置就输出 -1 ,所以result数组如果某位置没有被赋值,那么就应该是是-1,所以就初始化为-1。

在遍历nums2的过程中,我们要判断nums2[i]是否在nums1中出现过,因为最后是要根据nums1元素的下标来更新result数组。

注意题目中说是两个没有重复元素 的数组 nums1 和 nums2

没有重复元素,我们就可以用map来做映射了。根据数值快速找到下标,还可以判断nums2[i]是否在nums1中出现过。

使用单调栈的思路和纯使用单调栈寻找“下一个更大”一样,只是这一次在填写答案的时候,先检查要填写的数字是否在nums1里,如果有,就填写,如果没有就不用填写。

代码如下:

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        Map<Integer,Integer> map = new HashMap<>();
        Deque<Integer> stack = new ArrayDeque<>();
        int[] res = new int[nums1.length];
        for(int i = 0 ; i < nums1.length ;i++){
            res[i] = -1;
        }
        for(int i = 0; i < nums1.length ; i++){
            map.put(nums1[i],i);
        }
        stack.push(0);
        for(int i = 1 ; i < nums2.length ; i++){
            //仍然像正常遍历求nextBigger一样维护单调栈
            //但是在出栈(填写答案)的时候判断是不是nums1里的元素即可
            while(!stack.isEmpty() && nums2[stack.peek()] < nums2[i]){
                if(map.containsKey(nums2[stack.peek()])){
                    res[map.get(nums2[stack.peek()])] = nums2[i];
                }
                stack.pop();
            }
            stack.push(i);
        }
        return res;
    }
}

3.503.下一个更大元素II

思路:既然是循环,那么把原来的操作进行一遍后,再来一遍,就可以得到循环的结果。

代码如下:

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int[] res = new int[nums.length];
        Deque<Integer> stack = new ArrayDeque<>();
        for(int i = 0 ; i < nums.length ;i++){
            res[i] = -1;
        }
        stack.push(0);
        for(int i = 0; i < nums.length ;i++){
            if(nums[stack.peek()] < nums[i]){
                while(!stack.isEmpty() && nums[stack.peek()] < nums[i]){
                    res[stack.peek()] = nums[i];
                    stack.pop();
                }
            }
            stack.push(i);
        }

        for(int i = 0; i < nums.length ;i++){
            if(nums[stack.peek()] < nums[i]){
                while(!stack.isEmpty() && nums[stack.peek()] < nums[i]){
                    res[stack.peek()] = nums[i];
                    stack.pop();
                }
            }
            stack.push(i);
        }
        return res;
    }
}

精简版本:

class Solution {
    public int[] nextGreaterElements(int[] nums) {
        int[] res = new int[nums.length];
        Deque<Integer> stack = new ArrayDeque<>();
        for(int i = 0 ; i < nums.length ;i++){
            res[i] = -1;
        }
        stack.push(0);
        for(int i = 0; i < nums.length*2 ;i++){
            if(nums[stack.peek()] < nums[i%nums.length]){
                while(!stack.isEmpty() && nums[stack.peek()] < nums[i%nums.length]){
                    res[stack.peek()] = nums[i%nums.length];
                    stack.pop();
                }
            }
            stack.push(i%nums.length);
        }
        return res;
    }
}

4.42. 接雨水

思路1:前后缀

根据本题要求的物理特性,把每一个格子看成一个独立的水桶,它能盛多少水取决于水桶左右的最小高度。因此我们要计算出它的右边的最大和左边的最大,在这两个最大中取最小,再减去地基的高度,这就是这个水桶能盛水的数量。

暴力模拟(会时间超限,时间复杂度O(n^2):

class Solution {
    public int trap(int[] height) {
        int res = 0;
        for(int i = 0; i < height.length ;i++){
            if(i == 0 || i == height.length-1) continue;
            int left = height[i] , right = height[i];
            for(int j = i-1 ; j >= 0 ; j--){
                left = Math.max(left,height[j]);
            }
            for(int j = i+1 ; j < height.length ;j++){
                right = Math.max(right,height[j]);
            }
            res += (Math.min(left,right)-height[i]);
        }
        return res;
    }
}

思路2:考虑使用双指针求前后缀降低时间复杂度:

class Solution {
    public int trap(int[] height) {
        int[] maxLeft = new int[height.length];
        maxLeft[0] = height[0];
        int[] maxRight = new int[height.length];
        maxRight[height.length-1] = height[height.length-1];
        for(int i = 1; i < height.length ; i++){
            maxLeft[i] = Math.max(height[i],maxLeft[i-1]);
        }
        for(int i = height.length-2 ; i >= 0 ; i--){
            maxRight[i] = Math.max(maxRight[i+1],height[i]);
        }
        int result = 0;
        for(int i = 0 ; i < height.length ; i++){
            result += (Math.min(maxLeft[i],maxRight[i]) - height[i]);
        }
        return result;

    }
}

这里的思想是考虑到maxLeft 和 maxRight 的计算存在重复,因此使用了 maxLeft 和 maxRight两个数组来记录已经计算过的结果。同时也用到了动态规划的思想,使用记录过的已经计算过的结果来得到新的要计算的结果,需要考虑遍历顺序和初始化的问题。

思路3:单调栈

通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,就可以考虑用单调栈了。

1.单调栈的解题思路以行的方式考虑雨水累加,这样一层层计算,层的宽度与 当前下标 和 下一个更高的下标 有关,层高与 Math.min(左高,右高) - 底高 有关。

2.使用单调栈内元素的顺序:

从栈头(元素从栈头弹出)到栈底的顺序应该是从小到大的顺序。

因为一旦发现添加的柱子高度大于栈头元素了,此时就出现凹槽了,栈头元素就是凹槽底部的柱子,栈头第二个元素就是凹槽左边的柱子,而添加的元素就是凹槽右边的柱子。

如图:

42.接雨水4

3.遇到相同的元素

遇到相同的元素,更新栈内下标,就是将栈里元素(旧下标)弹出,将新元素(新下标)加入栈中。

例如 5 5 1 3 这种情况。如果添加第二个5的时候就应该将第一个5的下标弹出,把第二个5添加到栈中。

因为我们要求宽度的时候 如果遇到相同高度的柱子,需要使用最右边的柱子来计算宽度

如图所示:

42.接雨水5

4.栈里存放什么元素

使用单调栈,也是通过 长 * 宽 来计算雨水面积的。

长就是通过柱子的高度来计算,宽是通过柱子之间的下标来计算,

栈里就存放下标就行,想要知道对应的高度,通过height[stack.top()] 就知道弹出的下标对应的高度了。

单调栈处理逻辑

以下操作过程其实和 739. 每日温度 (opens new window)也是一样的,建议先做 739. 每日温度 (opens new window)。

以下逻辑主要就是三种情况

  • 情况一:当前遍历的元素(柱子)高度小于栈顶元素的高度 height[i] < height[st.top()]
  • 情况二:当前遍历的元素(柱子)高度等于栈顶元素的高度 height[i] == height[st.top()]
  • 情况三:当前遍历的元素(柱子)高度大于栈顶元素的高度 height[i] > height[st.top()]

先将下标0的柱子加入到栈中,st.push(0);。 栈中存放我们遍历过的元素,所以先将下标0加进来。

然后开始从下标1开始遍历所有的柱子,for (int i = 1; i < height.size(); i++)

如果当前遍历的元素(柱子)高度小于栈顶元素的高度,就把这个元素加入栈中,因为栈里本来就要保持从小到大的顺序(从栈头到栈底)。

代码如下:

if (height[i] < height[st.top()])  st.push(i);

如果当前遍历的元素(柱子)高度等于栈顶元素的高度,要跟更新栈顶元素,因为遇到相相同高度的柱子,需要使用最右边的柱子来计算宽度。

代码如下:

if (height[i] == height[st.top()]) { // 例如 5 5 1 7 这种情况
  st.pop();
  st.push(i);
}

如果当前遍历的元素(柱子)高度大于栈顶元素的高度,此时就出现凹槽了,如图所示:

42.接雨水4

取栈顶元素,将栈顶元素弹出,这个就是凹槽的底部,也就是中间位置,下标记为mid,对应的高度为height[mid](就是图中的高度1)。

此时的栈顶元素st.top(),就是凹槽的左边位置,下标为st.top(),对应的高度为height[st.top()](就是图中的高度2)。

当前遍历的元素i,就是凹槽右边的位置,下标为i,对应的高度为height[i](就是图中的高度3)。

此时大家应该可以发现其实就是栈顶和栈顶的下一个元素以及要入栈的元素,三个元素来接水!

那么雨水高度是 min(凹槽左边高度, 凹槽右边高度) - 凹槽底部高度,代码为:int h = min(height[st.top()], height[i]) - height[mid];

雨水的宽度是 凹槽右边的下标 - 凹槽左边的下标 - 1(因为只求中间宽度),代码为:int w = i - st.top() - 1 ;

当前凹槽雨水的体积就是:h * w

求当前凹槽雨水的体积代码如下:

while (!st.empty() && height[i] > height[st.top()]) { // 注意这里是while,持续跟新栈顶元素
    int mid = st.top();
    st.pop();
    if (!st.empty()) {
        int h = min(height[st.top()], height[i]) - height[mid];
        int w = i - st.top() - 1; // 注意减一,只求中间宽度
        sum += h * w;
    }
}

逻辑详细的完整代码如下:

class Solution {
    public int trap(int[] height) {
    //横向切分,思路是单调栈,注意下一个元素与当前栈顶元素 因 大小不同 造成的不同逻辑
        int sum = 0;
        Deque<Integer> stack = new ArrayDeque<>();//存放下标,如果要取高度,则用height取
        stack.push(0);
        for(int i = 1; i < height.length ; i++){
            if(height[stack.peek()] > height[i]){
                stack.push(i);
            }else if(height[stack.peek()] == height[i]){
                stack.pop();
                stack.push(i);
            }else{
                while(!stack.isEmpty() && height[stack.peek()] < height[i]){
                    int mid = stack.pop();
                    int right = i;
                    if(!stack.isEmpty()){
                        int left = stack.peek();
                        int w = right - left - 1;
                        int h = Math.min(height[right],height[left]) - height[mid];
                        sum += h*w;
                    }
                }
                stack.push(i);
            }

        }
        return sum;
    }
}

对重复的地方进行优化;

class Solution {
    public int trap(int[] height) {
    //横向切分,思路是单调栈,注意下一个元素与当前栈顶元素 因 大小不同 造成的不同逻辑
        int sum = 0;
        Deque<Integer> stack = new ArrayDeque<>();//存放下标,如果要取高度,则用height取
        stack.push(0);
        for(int i = 1; i < height.length ; i++){
            if(height[stack.peek()] == height[i]){
                stack.pop();
            }else if(height[stack.peek()] < height[i]){
                while(!stack.isEmpty() && height[stack.peek()] < height[i]){
                    int mid = stack.pop();
                    int right = i;
                    if(!stack.isEmpty()){
                        int left = stack.peek();
                        int w = right - left - 1;
                        int h = Math.min(height[right],height[left]) - height[mid];
                        sum += h*w;
                    }
                }
            }
            stack.push(i);
        }
        return sum;
    }
}

5.84.柱状图中最大的矩形

暴力解法

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int sum = 0;
        for (int i = 0; i < heights.size(); i++) {
            int left = i;
            int right = i;
            for (; left >= 0; left--) {
                if (heights[left] < heights[i]) break;
            }
            for (; right < heights.size(); right++) {
                if (heights[right] < heights[i]) break;
            }
            int w = right - left - 1;
            int h = heights[i];
            sum = max(sum, w * h);
        }
        return sum;
    }
};

如上代码并不能通过leetcode,超时了,因为时间复杂度是$O(n^2)$。

双指针法

(但是时间复杂度仍然是O(n^2))量级:

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        vector<int> minLeftIndex(heights.size());
        vector<int> minRightIndex(heights.size());
        int size = heights.size();

        // 记录每个柱子 左边第一个小于该柱子的下标
        minLeftIndex[0] = -1; // 注意这里初始化,防止下面while死循环
        for (int i = 1; i < size; i++) {
            int t = i - 1;
            // 这里不是用if,而是不断向左寻找的过程
            while (t >= 0 && heights[t] >= heights[i]) t = minLeftIndex[t];
            minLeftIndex[i] = t;
        }
        // 记录每个柱子 右边第一个小于该柱子的下标
        minRightIndex[size - 1] = size; // 注意这里初始化,防止下面while死循环
        for (int i = size - 2; i >= 0; i--) {
            int t = i + 1;
            // 这里不是用if,而是不断向右寻找的过程
            while (t < size && heights[t] >= heights[i]) t = minRightIndex[t];
            minRightIndex[i] = t;
        }
        // 求和
        int result = 0;
        for (int i = 0; i < size; i++) {
            int sum = heights[i] * (minRightIndex[i] - minLeftIndex[i] - 1);
            result = max(sum, result);
        }
        return result;
    }
};

单调栈

寻找leftNextLow 和 rightNextLow;

分别存放i对应的左边第一个更小元素位置 和 右边第一个更小元素位置;

注意遍历顺序和初始化:

leftNextLow初始化成 -1 (可以认为是没有更小的情况下,-1的位置没有元素,高度是0,是左边第一个更小元素的位置),从右往左遍历。

同理, rightNextLow初始化成 height.length ,从左往右遍历。

遍历,取最大的 height[i] * (rightNextLow[i] - leftRightLow[i] - 1);

class Solution {
    public static int largestRectangleArea(int[] heights) {
        int res = 0;
        int[] leftNextLow = new int[heights.length];
        for(int i = 0; i < heights.length ; i++){
            leftNextLow[i] = -1;
        }
        int[] rightNextLow = new int[heights.length];
        for(int i = 0 ; i < heights.length ; i++){
            rightNextLow[i] = heights.length;
        }
        Deque<Integer> stack = new ArrayDeque<>();
        stack.push(0);
        for(int i = 1 ; i < heights.length ; i++){
            while(!stack.isEmpty() && heights[stack.peek()] > heights[i]){
                rightNextLow[stack.peek()] = i;
                stack.pop();
            }
            stack.push(i);
        }

        while(!stack.isEmpty()) stack.pop();
        stack.push(heights.length-1);
        for(int i = heights.length - 2 ; i >= 0 ; i--){
            while(!stack.isEmpty() && heights[stack.peek()] > heights[i]){
                leftNextLow[stack.peek()] = i;
                stack.pop();
            }
            stack.push(i);
        }

        for(int i = 0; i < heights.length ; i++){
            int w = rightNextLow[i] - leftNextLow[i] - 1;
            int h = heights[i];
            res = Math.max(res,w*h);
        }
        return res;
    }
}

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

豆包MarsCode编程助手:让编程更简单

在编程的浩瀚宇宙中&#xff0c;每一个开发者都在寻找那把能够开启高效与创意之门的钥匙。随着AI技术的飞速发展&#xff0c;智能编程助手应运而生&#xff0c;为开发者们带来了前所未有的便捷与灵感。今天&#xff0c;我们将以五子棋小游戏开发为例&#xff0c;深入解读豆包Ma…

从文本坐标数据转换为矢量(点线面)

从坐标数据转换为空间几何(点线面) 介绍 只要文件中包含空间数据(如经纬度信息),转换为点、线或面要素。我们将使用内置的 excel Reader 参数、VertexCreator 转换器将坐标转换为点要素。我们还将使用 VertexCreator 转换器和 LineBuilder 转换器和AreaBuilder转换为线和…

第七讲 开发环境的搭建

1 首先是mdk5 的安装破解 然后就是 安装 f103 的 库。 然后是破解 &#xff1a; 2 然后是 进行编译测试。 随便打开一个工程 开始编译 3 然后是 ch340 的驱动的安装 目前就是安装完毕

校招简历生成器智能体:重塑求职新体验

校招简历生成器智能体&#xff1a;重塑求职新体验 在数字化时代&#xff0c;人工智能正以前所未有的速度改变着我们的生活与工作方式。百度文心智能体平台&#xff0c;作为AI技术应用的典范&#xff0c;正引领着智能服务的新潮流。今天&#xff0c;我们将聚焦于该平台上的一个…

黑马-Cloud21版-面试篇13:Sentinel源码分析

Sentinel源码分析 1.Sentinel的基本概念 Sentinel实现限流、隔离、降级、熔断等功能&#xff0c;本质要做的就是两件事情&#xff1a; 统计数据&#xff1a;统计某个资源的访问数据&#xff08;QPS、RT等信息&#xff09;规则判断&#xff1a;判断限流规则、隔离规则、降级规…

SprinBoot+Vue社团管理系统的设计与实现

目录 1 项目介绍2 项目截图3 核心代码3.1 Controller3.2 Service3.3 Dao3.4 application.yml3.5 SpringbootApplication3.5 Vue 4 数据库表设计5 文档参考6 计算机毕设选题推荐7 源码获取 1 项目介绍 博主个人介绍&#xff1a;CSDN认证博客专家&#xff0c;CSDN平台Java领域优质…

「C++系列」重载运算符/重载函数

文章目录 一、重载运算符1. 运算符重载的规则2. 示例&#xff1a;重载加法运算符3. 注意事项 二、可重载运算符/不可重载运算符1. 可重载的运算符2. 不可重载的运算符3. 注意事项 三、重载函数1. 函数重载的基本规则2. 示例3. 注意事项 四、相关链接 一、重载运算符 在C中&…

[创业之路-145] :做项目做产品,50米/100米短跑与马拉松长跑,跑法不同,几人的小分队作战与兵团战役,打法不同

目录 一、做项目做产品类同于跑步&#xff0c;50米/100米短跑与马拉松长跑&#xff0c;跑法不同 1. 50米/100米短跑与项目/产品短周期开发的类比 2. 马拉松长跑与长期项目/产品开发的类比 3. 跑法不同的核心差异 二、做项目做产品类同于打仗&#xff0c;几人的小分队作战与…

MySQL-基础篇-事务(事务简介、事务操作、事务的四大特性、并发事务引发的问题、事务的隔离级别)

文章目录 1. 事务简介2. 事务操作2.1 未控制事务2.2 控制事务2.2.1 查看事务的提交方式2.2.2 设置事务的提交方式2.2.3 提交事务2.2.4 回滚事务2.2.5 开启事务2.2.6 完善转账案例 3. 事务的四大特性&#xff08;ACID&#xff09;4. 并发事务引发的问题5. 事务隔离级别5.1 演示5…

Golang | Leetcode Golang题解之第387题字符串中的第一个唯一字符

题目&#xff1a; 题解&#xff1a; type pair struct {ch bytepos int }func firstUniqChar(s string) int {n : len(s)pos : [26]int{}for i : range pos[:] {pos[i] n}q : []pair{}for i : range s {ch : s[i] - aif pos[ch] n {pos[ch] iq append(q, pair{ch, i})} e…

TensorRT模型量化实践

文章目录 量化基本概念量化的方法方式1&#xff1a;trtexec&#xff08;PTQ的一种&#xff09;方式2&#xff1a;PTQ2.1 python onnx转trt2.2 polygraphy工具:应该是对2.1量化过程的封装 方式3&#xff1a;QAT(追求精度时推荐) 使用TensorRT量化实践&#xff08;C版&#xff09…

算法训练营——day2数组部分例题

1 移除元素-力扣27&#xff08;简单&#xff09; 1.1 题目&#xff1a; 移除元素1 1.2 思路及解法 只能覆盖&#xff0c;不能删除 暴力遍历解法 class Solution {public int removeElement(int[] nums, int val) {int sizenums.length;for(int i0;i<size;i){if(nums[i]va…

鸿蒙状态管理

我们开发中构建的页面多为静态页面。如果希望构建一个动态的,有交互的界面,就需要引入‘状态’的概念 用户构建了一个UI模型,其中应用的运行时的状态是参数,当参数改变时,UI作为返回结果,也将进行对应的改变。状态变化带来UI的重新渲染。 自定义组件拥有变量所谓属性,…

数据类型和程序运算

1. 数据类型 1.1 static修饰的变量 本文所有内容在企业考核的笔试题出现频率很高&#xff0c;而且是易错题大家注意下&#xff01; 南友们在玩Java时有没发现&#xff0c;下面这样一个对象&#xff0c;我们即使没有给变量赋值&#xff0c;在创建它后这个变量依旧会有默认值。…

【个人笔记】Git

Tiltle: Github 使用 &#x1f4d6; 快速使用 音标&#xff1a;[ɡɪthʌb] 0 介绍 Github是一个面向开源与私有软件项目的 托管平台&#xff0c;Git源自其内部的版本库格式.2008年上线&#xff0c;18年被微软收购&#xff1b;有很多知名的开源项目&#xff1a;jQuery、pytho…

Android Framework(三)Activity启动流程

文章目录 大纲总体流程 第一阶段&#xff1a;点击图标启动应用流程概览SourceActivity端处理system_service处理启动请求参数的构建activityInfo的解析创建ActivityRecord 窗口层级树的处理获取Task--getOrCreateRootTaskActivityRecord挂载到Task--setNewTask移动Task到容器顶…

最新!yolov10+deepsort的目标跟踪实现

目录 yolov10介绍——实时端到端物体检测 概述 主要功能 型号 性能 方法 一致的双重任务分配&#xff0c;实现无 NMS 培训 效率-精度驱动的整体模型设计 提高效率 精度提升 实验和结果 比较 deepsort介绍&#xff1a; yolov10结合deepsort实现目标跟踪 效果展示…

Elasticsearch的部署和使用

首先对java来说,我们可用的有原生elasticsearch和经过spring二次封装的spring data elasticsearch. 后者自带了一些方法,类似于mybatisplus,可以直接使用,十分方便. 如果是spring项目都建议使用第二种,除非你要深度使用. 首先是服务器的部署.部署之前要知道版本,我在部署时遇到…

GoLang:Go语言开发环境的配置

Go语言 Go语言开发环境的配置 - 文章信息 - Author: 李俊才 (jcLee95) Visit me at CSDN: https://jclee95.blog.csdn.netMy WebSite&#xff1a;http://thispage.tech/Email: 291148484163.com. Shenzhen ChinaAddress of this article:https://blog.csdn.net/qq_28550263/a…

一款管理苹果设备的软件iMazing3中文破解安装激活教程

iMazing3官方版是一款管理苹果设备的软件&#xff0c;是一款帮助用户管理 IOS 手机的PC端应用程序&#xff0c;能力远超 iTunes 提供的终极 iOS 设备管理器。在iMazing官方版上与苹果设备连接后&#xff0c;可以轻松传输文件&#xff0c;浏览保存信息等&#xff0c;功能比Itune…