【单调栈】单调栈基础及经典案例

【单调栈】单调栈基础及经典案例

  • 单调栈理论基础
  • 每日温度
  • 下一个更大元素Ⅰ
  • 下一个更大元素Ⅱ
  • 经典例题—接雨水
    • 思路一 暴力求解
    • 思路二 双指针优化
    • 思路三 单调栈解法
  • 经典例题—柱状图中最大的矩形
    • 思路一 暴力求解
    • 思路二 单调栈

单调栈理论基础

单调栈的应用场景:要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时就要用到单调栈,时间复杂度为O(n)。

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

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

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

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

  2. 单调栈里元素是递增呢? 还是递减呢?
    顺序的描述为 从栈头到栈底的顺序,若求一个元素右边第一个更大元素,单调栈就是递增的,反之则是递减的。

使用单调栈主要有三个判断条件,以递增栈为例

  • 当前遍历的元素nums[i]小于栈顶元素nums[st.top()],即 nums[i] < nums[st.top()]
    直接将遍历数据加入栈即可,实现递增,即 st.push(i);

  • 当前遍历的元素nums[i]等于栈顶元素nums[st.top()],即 nums[i] == nums[st.top()]
    直接将遍历数据加入栈即可,因为求的是第一个比自己大的数,即 st.push(i);

  • 当前遍历的元素nums[i]大于栈顶元素nums[st.top()],即 nums[i] > nums[st.top()]
    (1)收集结果,结果处理
    (2)将栈顶元素弹出,进行下次比较,因为需要用while()
    (3)最后将当前遍历的元素下标加入栈

单调栈程序模板
求每个数值的右边第一个比自己大的元素下标

vector<int> func(vector<int>& nums) 
{vector<int> result(nums.size(), -1);stack<int> st;			// 单调递增存放遍历过的数据的下标st.push(0);				// 把第一个元素下标先加入//数组遍历完毕for(int i = 1; i < nums.size(); i++){if(nums[i] <= nums[st.top()])st.push(i);else{// 如果遍历数据比栈顶数据大while(!st.empty() && nums[i] > nums[st.top()])	{result[st.top()] = i;	// 保存下标值st.pop();				// 移除元素}st.push(i);}}return result;
}

说明:

  • 栈的数据存放过程详情参考:代码随想录-每日温度

  • 单调栈的顺序:若求第一个比自己大(递增),反之则相反

  • 栈存放的元素:已经遍历过的数据的下标

  • 当前遍历元素nums[i];

  • 右边第一个比当前元素大的数据下标st.top();

  • 左边第一个比当前元素大的数据下标:栈顶第二个元素

    // 先把右边第一个比当前数据大的数据下标记录,并弹出
    int right = st.top();
    st.pop();
    // 获取左边第一个比当前数据大的数据下标
    int left = st.top();
    

每日温度

力扣原题

给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替

例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。

核心思想

  • 本题是一个单调栈的裸题,题意即要求右边第一个比自己大的元素和自己直接的下标差值,因此用单调递增栈。
  • 结果数组是求两数的下表差值,因此收集结果代码为
    result[st.top()] = i - st.top();	// 计算下标差
    

代码实现

vector<int> dailyTemperatures(vector<int>& temperatures) 
{vector<int> result(temperatures.size(), 0);stack<int> st;			// 单调递增存放遍历过的数据的下标st.push(0);				// 把第一个元素下标先加入//数组遍历完毕for(int i = 1; i < temperatures.size(); i++){if(temperatures[i] <= temperatures[st.top()])st.push(i);else{while(!st.empty() && temperatures[i] > temperatures[st.top()])	// 如果遍历数据比栈顶数据大{result[st.top()] = i - st.top();			// 计算下标差st.pop();									// 移除元素下标}st.push(i);}}return result;}

下一个更大元素Ⅰ

力扣链接

给你两个 没有重复元素 的数组 nums1nums2 ,其中nums1nums2 的子集。

请你找出 nums1 中每个元素在 nums2 中的下一个比其大的值。

nums1 中数字 x 的下一个更大元素是指 x 在 nums2 中对应位置的右边的第一个比 x 大的元素。如果不存在,对应位置输出 -1 。

输入:nums1 = [4,1,2], nums2 = [1,3,4,2].
输出:[-1,3,-1]

核心思想

  • 本题也是一个单调栈的裸题,只是通过了nums1数组进行包装,需要明确结果数组大小为 nums1.size(),遍历的数组为 nums2
  • 解题核心:明确nums2中的数据在nums1中的下标(若存在)
  • 通过map映射nums1中的数据的下标,使其在遍历num2时,可以通过数值获取该数据在nums1中的下标

部分核心代码
(1)将nums1数据通过数值找下标的map映射:

// 将数组1的值与下标做映射,通过数值找到在nums1中的下标
unordered_map<int,int> umap;
for(int i = 0; i < nums1.size(); i++)umap[nums1[i]]= i;	

(2)查找nums2中的数据在nums1中的下标

// 看nums1中是否存在该元素
if(umap.count(nums2[st.top()]) > 0)			int idx = umap[nums2[st.top()]];	// 获取数据在nums1中的下标		

代码实现

vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) 
{vector<int> result(nums1.size(),-1);stack<int> st;if(nums1.size() == 0)return result;// 将数组1的值与下标做映射,通过数值找到在nums1中的下标unordered_map<int,int> umap;for(int i = 0; i < nums1.size(); i++)umap[nums1[i]]= i;	st.push(0);	for(int i = 1; i < nums2.size(); i++){if(nums2[i] <= nums2[st.top()])st.push(i);else{while(!st.empty() && nums2[i] > nums2[st.top()]){if(umap.count(nums2[st.top()]) > 0)			// 看nums1中是否存在该元素{int idx = umap[nums2[st.top()]];		// 获取数据在nums1中的下标result[idx] = nums2[i];}st.pop();}st.push(i);}}return result;
}

下一个更大元素Ⅱ

力扣链接

给定一个循环数组(最后一个元素的下一个元素是数组的第一个元素),输出每个元素的下一个更大元素。

数字 x 的下一个更大的元素是按数组遍历顺序,这个数字之后的第一个比它更大的数,这意味着你应该循环地搜索它的下一个更大的数。如果不存在,则输出 -1。

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

本题也为一道明显的单调栈问题

思路一 暴力拼接

  • 由于循环数组,不妨直接把两个数组拼接在一起,然后使用单调栈求下一个最大值就暴力解决了!

  • 将两个nums数组拼接在一起,使用单调栈计算出每一个元素的下一个最大值,最后再把结果集即result数组resize到原数组大小就可以了

  • 这种写法确实比较直观,但做了很多无用操作,例如修改了nums数组,扩充nums数组相当于多了一个 O ( n ) O(n) O(n)的操作

程序实现:

vector<int> nextGreaterElements(vector<int>& nums) 
{// 拼接一个新的numsvector<int> nums1(nums.begin(), nums.end());nums.insert(nums.end(), nums1.begin(), nums1.end());// 用新的nums大小来初始化resultvector<int> result(nums.size(), -1);if (nums.size() == 0) return result;// 开始单调栈stack<int> st;st.push(0);for (int i = 1; i < nums.size(); i++) { if (nums[i] < nums[st.top()]) st.push(i); else if (nums[i] == nums[st.top()]) st.push(i);else { while (!st.empty() && nums[i] > nums[st.top()]) {result[st.top()] = nums[i];st.pop();}st.push(i);}}// 最后再把结果集即result数组resize到原数组大小result.resize(nums.size() / 2);return result;
}

思路二

  • 其实也可以不扩充nums,而是在遍历的过程中模拟走两遍nums,即:
    for(int i = 1; i < nums.size() * 2; i++)
    
  • 对循环中用到的每个 i 取模长操作,保证 nums[i] 不会溢出

程序实现:

vector<int> nextGreaterElements(vector<int>& nums) 
{vector<int> result(nums.size(),-1);stack<int> st;if(nums.size() == 0)return result;st.push(0);	// 模拟遍历两边nums,注意一下都是用 i % nums.size()来操作for(int i = 1; i < nums.size() * 2; i++){if(nums[i % nums.size()] <= nums[st.top()])st.push(i % nums.size());else{while(!st.empty() && nums[i % nums.size() ] > nums[st.top()]){result[st.top()] = nums[i % nums.size()];st.pop();}st.push(i % nums.size());}}	return result;		
}

经典例题—接雨水

力扣链接

给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。

示例 :
输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6

思路一 暴力求解

本题暴力解法也是也是使用双指针

首先要明确,要按照行来计算,还是按照列来计算。

按照行与列计算如下图所示:

  • 这里按照列来计算,比较容易理解,并且宽度是1,只需计算每一列雨水的高度即可。
  • 可以看出每一列雨水的高度,取决于,该列左侧最高的柱子和右侧最高的柱子中最矮的那个柱子的高度。
  • 对于其中一根长度为 height 的柱子,左侧最高的柱子为 leftHeight,右侧最高的柱子为 rightHeight,那么这根柱子可接的雨水为:
    min(leftHeight, rightHeight) - height
    
  • 从头遍历一遍所有的列,然后求出每一列雨水的体积,相加之后就是总雨水的体积了
  • 注意第一个柱子和最后一个柱子不接雨水

代码实现:

int trap(vector<int>& height) 
{int sum = 0;for (int i = 0; i < height.size(); i++) {// 第一个柱子和最后一个柱子不接雨水if (i == 0 || i == height.size() - 1) continue;int rHeight = height[i]; // 记录右边柱子的最高高度int lHeight = height[i]; // 记录左边柱子的最高高度for (int r = i + 1; r < height.size(); r++) {if (height[r] > rHeight) rHeight = height[r];}for (int l = i - 1; l >= 0; l--) {if (height[l] > lHeight) lHeight = height[l];}int h = min(lHeight, rHeight) - height[i];if (h > 0) sum += h;}return sum;
}

思路二 双指针优化

  • 在上述解法中,我们可以看到只要记录左边柱子的最高高度 和 右边柱子的最高高度,就可以计算当前位置的雨水面积,min(左边柱子的最高高度,记录右边柱子的最高高度) - 当前柱子高度。

  • 为了得到两边的最高高度,使用了双指针来遍历,每到一个柱子都向两边遍历一遍,这其实是有大量重复计算的。我们把每一个位置的左边最高高度记录在一个数组上(maxLeft),右边最高高度记录在一个数组上(maxRight),这样就避免了重复计算。

  • 当前位置,左边的最高高度是前一个位置的左边最高高度和本高度的最大值。

    从左向右遍历:

    maxLeft[i] = max(height[i], maxLeft[i - 1]);
    

    从右向左遍历:

    maxRight[i] = max(height[i], maxRight[i + 1]);
    

程序实现:

int trap(vector<int>& height) 
{if (height.size() <= 2) return 0;vector<int> maxLeft(height.size(), 0);vector<int> maxRight(height.size(), 0);int size = maxRight.size();// 记录每个柱子左边柱子最大高度maxLeft[0] = height[0];for (int i = 1; i < size; i++) maxLeft[i] = max(height[i], maxLeft[i - 1]);// 记录每个柱子右边柱子最大高度maxRight[size - 1] = height[size - 1];for (int i = size - 2; i >= 0; i--) maxRight[i] = max(height[i], maxRight[i + 1]);// 求和int sum = 0;for (int i = 0; i < size; i++) {int count = min(maxLeft[i], maxRight[i]) - height[i];if (count > 0) sum += count;}return sum;
}

思路三 单调栈解法

  而接雨水这道题目,我们正需要寻找一个元素,右边最大元素以及左边最大元素,来计算雨水面积。

那么本题使用单调栈有如下几个问题:

  1. 首先单调栈是按照行方向来计算雨水

  2. 使用单调栈内元素的顺序:由于是查找一个元素左右两侧第一个比自身大的元素,因此顺序为单调递增栈

  3. 遇到相同高度的柱子怎么办:遇到相同的元素,更新栈内下标,就是将栈里元素(旧下标)弹出,将新元素(新下标)加入栈中。

    例如 5 5 1 3 这种情况。如果添加第二个5的时候就应该将第一个5的下标弹出,把第二个5添加到栈中。因为我们要求宽度的时候 如果遇到相同高度的柱子,需要使用最右边的柱子来计算宽度。

单调栈处理逻辑
(1)当前遍历的元素高度小于栈顶元素的高度:把这个元素加入栈中,因为栈里本来就要保持从小到大的顺序

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

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

else if(height[i] == height[st.top()])
{st.pop();st.push(i);
}

(3)当前遍历的元素高度大于栈顶元素的高度:出现凹槽,计算雨水面积。

  1. 取栈顶元素,将栈顶元素弹出,这个就是凹槽的底部,下标记为mid,对应的高度为height[mid](就是图中的高度1)
  2. 此时的栈顶元素st.top(),就是凹槽的左边位置,下标为st.top(),对应的高度为height[st.top()](就是图中的高度2)
  3. 当前遍历的元素i,就是凹槽右边的位置,下标为i,对应的高度为height[i](就是图中的高度3)

栈顶和栈顶的下一个元素以及要入栈的元素,三个元素来接水!

那么雨水高度 h = min(凹槽左边高度, 凹槽右边高度) - 凹槽底部高度,代码为:

int h = min(height[st.top()], height[i]) - height[mid];

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

int w = i - st.top() - 1 ;

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

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;}
}

完整代码实现

int trap(vector<int>& height) 
{int result = 0;stack<int> st;		if(height.size() == 0)return result;st.push(0);	// 记录每个格子左右两边比他的的第一个元素和自身的差值for(int i = 1; i < height.size(); i++){if(height[i] <= height[st.top()])st.push(i);else if(height[i] == height[st.top()]){st.pop();st.push(i);}else{while(!st.empty() && height[i] > height[st.top()]){int mid = st.top();			// 中间元素的下标st.pop();if(!st.empty()){// 左边第一个比他大的元素为栈里面第二个元素int h = min(height[i], height[st.top()]) - height[mid];	int w = i - st.top() - 1;result += (h * w);}}st.push(i);}}return result;	
}

经典例题—柱状图中最大的矩形

力扣链接

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1,求在该柱状图中,能够勾勒出来的矩形的最大面积。

输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10


本题和接雨水是遥相呼应的两道题目,原理上有很多相同的地方,细节上又有差
异。

核心思路

  • 分别求每一根柱子左右比自身低的柱子下标,并求其间距为 w
  • 以自身高度为 h,形成的 h * w 的矩形即为每一个柱子可以构造的最大矩形
  • 其中以 1 为高度构造的矩形如下图所示:

思路一 暴力求解

  通过暴力求解每一根柱子左右两侧第一根比自身矮的柱子,以此求出每根柱子可形成的最大矩形面积

程序实现:

// 暴力求解
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;
}

注:该方法的时间复杂度为 O ( n 2 ) O(n^2) O(n2),在力扣上超时,但核心思想为下述优化做了很好的铺垫。

双指针优化

同接雨水一样,引入数组,记录每个柱子 左右两边第一个小于该柱子的下标

// 暴力求解 - 双指针优化
int largestRectangleArea2(vector<int>& heights) 
{int result = 0;int size = heights.size();vector<int> minLeftIndex(heights.size(),  -1);vector<int> minRightIndex(heights.size(), -1);// 记录每个柱子 左边第一个小于该柱子的下标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[i] = t;}// 记录每个柱子 右边第一个小于该柱子的下标minRightIndex[size - 1] = size; 	// 注意这里初始化,防止下面while死循环for(int i = 0; i < size - 1; i++){int t = i + 1;while(t < size && heights[t] >= heights[i]	)t++;minRightIndex[i] = t;}for(int i = 0; i < size; i++){int w = minRightIndex[i] - minLeftIndex[i] - 1;int h = heights[i];result = max(w * h, result);}return result;
}

思路二 单调栈

考虑到本题题意为求每根柱子左右两边第一根比自身矮的柱子的下标,显然是一道单调栈题目。

  • 由于是求左右第一个比自身小的元素下标,那么单调栈为递减栈
  • 栈顶和栈顶的下一个元素以及要入栈的三个元素组成了我们要求最大面积的高度和宽度

主要就是理清当前遍历元素和栈顶元素大小比较的三种情况,具体代码如下:

int largestRectangleArea(vector<int>& heights) 
{int result = 0;stack<int> st;		// 头尾加0heights.insert(heights.begin(), 0);heights.push_back(0);st.push(0);	// 记录每一个数值左右两边比自身小的数值 即矩形面积for(int i = 1; i < heights.size(); i++){if(heights[i] >= heights[st.top()])st.push(i);else if(heights[i] == heights[st.top()]){st.pop();		// 可加可不加 思路不一样而已st.push(i);}else{while(!st.empty() && heights[i] < heights[st.top()]){int mid = st.top();			// 中间元素的下标 为基准st.pop();// 左边第一个比他小的元素为栈里面第二个元素if(!st.empty()){int left = st.top();int right = i;				// 右边比中间小的 下标int h = heights[mid];int w = right - left - 1;result = max(h * w, result);}}st.push(i);}}return result;	
}

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

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

相关文章

109.游戏安全项目:信息显示二-利用游戏通知辅助计算基址

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 内容参考于&#xff1a;易道云信息技术研究院 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要盲目相信…

Visual Studio使用与“Hello Word“的编写

1.打开Visual Studio点击"创建新项目" 2.点击"空项目"&#xff0c;并点击"下一步" 3.设置"项目名称"并"设置地址" 4.打开项目后&#xff0c;右击"源文件"并选择"添加"的"新建项" 5.点击"…

Java每日面试题(JVM)(day15)

目录 Java对象内存布局markWord 数据结构JDK1.8 JVM 内存结构JDK1.8堆内存结构GC垃圾回收如何发现垃圾如何回收垃圾 JVM调优参数 Java对象内存布局 markWord 数据结构 JDK1.8 JVM 内存结构 程序计数器: 线程私有&#xff0c;记录代码执行的位置. Java虚拟机栈: 线程私有&#…

【移植】标准系统方案之扬帆移植案例

往期知识点记录&#xff1a; 鸿蒙&#xff08;HarmonyOS&#xff09;应用层开发&#xff08;北向&#xff09;知识点汇总 鸿蒙&#xff08;OpenHarmony&#xff09;南向开发保姆级知识点汇总~ 持续更新中…… 本文章是基于瑞芯微RK3399芯片的yangfan开发板&#xff0c;进行标准…

【论文速看】DL最新进展20240927-目标检测、Transformer

目录 【目标检测】【Transformer】 【目标检测】 [2024小目标检测] A DeNoising FPN With Transformer R-CNN for Tiny Object Detection 论文链接&#xff1a;https://arxiv.org/abs/2406.05755 代码链接&#xff1a;https://github.com/hoiliu-0801/DNTR 尽管计算机视觉领域…

笔记整理—linux进程部分(1)进程终止函数注册、进程环境、进程虚拟地址

对于mian()函数而言&#xff0c;执行前也需要先执行一段引导代码才会去执行main()函数&#xff0c;该部分的代码包含构建c语言的运行环境等配置&#xff0c;如清理bss段等。 在使用gcc去编译程序的时候&#xff0c;使用gcc -v xxx.c可见链接过程。在编译完成后可见xxx.out文件。…

数据结构——计数、桶、基数排序

目录 引言 计数排序 1.算法思想 2.算法步骤 3.代码实现 4.复杂度分析 桶排序 1.算法思想 2.算法步骤 3.代码实现 4.复杂度分析 基数排序 1.算法思想 2.算法步骤 3.代码实现 4.复杂度分析 排序算法的稳定性 1.稳定性的概念 2.各个排序算法的稳定性 结束语 引…

NVLM多模态 LLM 在图像和语言任务中的表现优于 GPT-4o

论文地址&#xff1a;https://arxiv.org/pdf/2409.11402 背景 传统的多模态 LLM 有两种主要方法&#xff1a;纯解码器架构&#xff08;如 LLaVA&#xff09;和基于交叉注意力的架构&#xff08;如 Flamingo&#xff09;。混合架构&#xff0c;既提高了训练效率&#xff0c;又增…

[CKA]CKA的购买和注册考试券

CKA的购买和注册考试券 一、购买CKA 1、注册 LF开源软件学园 账号 LF开源软件学园&#xff1a;https://training.linuxfoundation.cn/register 2、个人中心进行实名认证 3、按需求进行购买 4、在考试中心–我的订单 中查看购买的订单 我是在"黑色星期五"打折买的…

LLM大模型书籍:专补大模型短板的RAG入门与实战书来了!

文末赠书 RAG自2020年由Facebook AI Research推出后&#xff0c;一下子就窜红了。 毕竟&#xff0c;它是真的帮了大忙&#xff0c;在解决大语言模型的“幻觉”问题上起到了关键作用。 如今&#xff0c;Google、AWS、IBM、微软、NVIDIA等科技巨头都在支持RAG应用的开发。微软…

中国新媒体联盟与中运律师事务所 建立战略合作伙伴关系

2024年9月27日&#xff0c;中国新媒体联盟与中运律师事务所举行战略合作协议签字仪式。中国新媒体联盟主任兼中国社会新闻网主编、中法新闻法制网运营中心主任左新发&#xff0c;中运律师事务所高级顾问刘学伟代表双方单位签字。 中国新媒体联盟是由央视微电影中文频道联合多家…

你的下一台手机会是眼镜吗?RTE 大会与你一同寻找下一代计算平台丨「空间计算和新硬件」论坛报名

周四 Meta 刚公布新一代 AR 眼镜 Orion 后&#xff0c;Perplexity 的 CEO 发了一条状态&#xff1a;「如果你还在做软件&#xff0c;请转型硬件。」 一家估值 30 亿美元的 AI 软件公司 CEO 说出这样的言论&#xff0c;既有有见到「最强 AR 眼镜」Orion 后的激动情绪&#xff0c…

如何组织一场考试并筛选未参加答题的考生?

&#x1f64b;频繁有小伙伴咨询&#xff1a;我组织了一场答题活动&#xff0c;导出考试成绩时只有参加了答题的人&#xff0c;但我想要找到哪些人没答题 此前我们会建议小伙伴逐人排查&#xff0c;但这建议被反复吐槽&#x1f926; 确实&#xff0c;如果只有十几个人逐人排查还…

鸿蒙开发(NEXT/API 12)【硬件(Pen Kit)】手写笔服务

Pen Kit&#xff08;手写笔服务&#xff09;是华为提供的一套手写套件&#xff0c;提供笔刷效果、笔迹编辑、报点预测、一笔成形和全局取色的功能。手写笔服务可以为产品带来优质手写体验&#xff0c;为您创造更多的手写应用场景。 目前Pen Kit提供了四种能力&#xff1a;手写…

银行大模型,走到哪了?

频道说 透过近期披露的上市银行中报&#xff0c;窥探银行业大模型最新进展。 大模型浪潮依然汹涌澎湃。 9月12日&#xff0c;OpenAI全新发布o1模型&#xff0c;在复杂推理任务取得重大进步&#xff0c;代表了人工智能能力的新水平&#xff0c;被视为AI时代的又一个里程碑。 …

Bigemap Pro首发(一款真正全面替代Arcgis的国产基础软件)

Bigemap Pro是一款功能强大的计算机数据要素辅助设计(Computer-Aided Data Elements Design CADED)软件&#xff0c;由成都比格图数据处理有限公司研发设计&#xff0c;主要应用在数据要素设计领域&#xff0c;为各行业提供安全可靠高效易用的数据要素设计类国产化基础软件。Bi…

公交换乘C++

题目&#xff1a; 样例解释&#xff1a; 样例#1&#xff1a; 第一条记录&#xff0c;在第 3 分钟花费 10 元乘坐地铁。 第二条记录&#xff0c;在第 46 分钟乘坐公交车&#xff0c;可以使用第一条记录中乘坐地铁获得的优惠票&#xff0c;因此没有花费。 第三条记录&#xff0c;…

OpenCV与AI深度学习 | 实战 | 使用OpenCV和Streamlit搭建虚拟化妆应用程序(附源码)

本文来源公众号“OpenCV与AI深度学习”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;实战 | 使用OpenCV和Streamlit搭建虚拟化妆应用程序&#xff08;附源码&#xff09; 现看看demo演示。 本文将介绍如何使用Streamlit和OpenCV…

【GUI设计】基于Matlab的图像去噪GUI系统(8),matlab实现

博主简介&#xff1a; 如需获取设计的完整源代码或者有matlab图像代码项目需求/合作&#xff0c;可联系主页个人简介提供的联系方式或者文末的二维码。 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 本次案例是基于Matlab的图像去噪GUI系统&am…