当前位置: 首页 > news >正文

北京微网站廊坊网站建设优化

北京微网站,廊坊网站建设优化,建设银行江门市新会网站,python手机在线编程文章目录 思路写法1完整版环形数组处理:i取模,遍历两遍写法2完整版(环形数组推荐写法)debug测试:逻辑运算符短路特性result数组在栈口取元素,是否会覆盖原有数值? 给定一个循环数组 nums &#…

文章目录

      • 思路
      • 写法1完整版
      • 环形数组处理:i取模,遍历两遍
      • 写法2完整版(环形数组推荐写法)
        • debug测试:
        • 逻辑运算符短路特性
        • result数组在栈口取元素,是否会覆盖原有数值?

给定一个循环数组 numsnums[nums.length - 1] 的下一个元素是 nums[0] ),返回 nums 中每个元素的 下一个更大元素

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

示例 1:

输入: nums = [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数; 
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

示例 2:

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

提示:

  • 1 <= nums.length <= 10^4
  • -10^9 <= nums[i] <= 10^9

思路

本题属于循环数组问题,循环数组的处理,我们可以将两个nums数组拼接在一起,使用单调栈计算出每一个元素的下一个最大值,最后再把结果集即result数组resize到原数组大小即可。

但这种写法,修改了nums数组,而且最后还要把result数组resize回去。resize倒是不费时间,是O(1)的操作,但扩充nums数组相当于**多了一个O(n)**的操作。时间复杂度和空间复杂度都多了O(n)

写法1完整版

// 版本一
class Solution {
public: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;}
};

环形数组处理:i取模,遍历两遍

对于这种循环数组, nums[nums.length - 1] 的下一个元素是 nums[0] ,需要遍历两遍,可以通过给i取模来解决!

我们首先扩充for循环遍历范围,令for遍历范围为[0,nums.size()*2-1](这样就遍历了2n个位置,遍历长度为2n),然后nums[i]改为nums[i%nums.size()]

由于取模运算的特性, i初始值=0,i%nums.size()这个式子就是0--nums.size()-1循环取值。

  • 当i初始值=0时,i%a的范围就是[0,a-1]

因为 “求模” 运算的定义是 “求余数”。例如,当 7 除以 3,结果是 2 余 1,所以 7%3 的结果是 1。余数总是会小于除数的,所以 i%a 的结果将始终在 0 到 a-1 的范围内

i 小于 a 时,i%a 的结果就是 i 自己;当 i 等于 a 时,i%a 的结果就是 0;当 i 大于 a 时,i%a 的结果就是 i-a 的值,直到这个值小于 a 为止。

遍历两遍的逻辑:

st.push(0);
for(int i=1;i<nums.size()*2;i++){if(nums[i%nums.size()]<=nums[st.top()]){st.push(i%nums.size());}else{while(nums[i%nums.size()]>nums[st.top()]&&!st.empty()){result[st.top()]=nums[i%nums.size()];st.pop();}st.push(nums[i%nums.size()]);}
}

写法2完整版(环形数组推荐写法)

  • 重点在只用O(n)的时间复杂度和空间复杂度,完成遍历两遍数组
class Solution {
public:vector<int> nextGreaterElements(vector<int>& nums) {stack<int>st;vector<int>result(nums.size(),-1);st.push(0);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;}
};

debug测试:

Line 171: Char 16: runtime error: reference binding to misaligned address 0xbebebebebebec0ba for type ‘int’, which requires 4 byte alignment (stl_deque.h) 0xbebebebebebec0ba: note: pointer points here

在这里插入图片描述
错误信息的意思是:运行时发生了一种未定义行为(Undefined Behavior)。具体来说,它在尝试对一个非对齐的地址(即不是4字节对齐的地址)进行整数的引用绑定,而这个操作是未定义的。该错误通常发生在空指针解引用,数组越界等情况

这个错误出现在while循环这一句:

while(nums[i%nums.size()]>nums[st.top()]&&!st.empty())

while 循环如果这么写,那么,在检查栈是否为空之前,就已经尝试从栈顶取值,这是有问题的。当栈为空时,这将会导致未定义行为。

逻辑运算符短路特性

在C++中,逻辑AND操作符(&&)和逻辑OR操作符(||)都具有"短路"特性

对于逻辑AND操作符,如果左边的操作数为假,那么不论右边的操作数是什么,整个表达式的结果都是假,因此不需要再计算右边的操作数。对于逻辑OR操作符,如果左边的操作数为真,那么不论右边的操作数是什么,整个表达式的结果都是真,因此不需要再计算右边的操作数

因此,写单调栈的while循环,while条件里面包括了非空检查的时候,检查栈是否为空的语句必须放在前面,确定非空之后再尝试从栈顶取值!如果栈已经为空,那么!st.empty()的结果为假,右边的nums[i%nums.size()] > nums[st.top()]就不会被执行,从而避免对空栈进行操作的未定义行为

result数组在栈口取元素,是否会覆盖原有数值?

答案是不会,因为result更新,是在发现了一个更大的数值,弹出的时候才会更新

例如4 3 2这个例子,遍历两遍得到的是4 3 2 4 3 2,实际上后面那一组4 3 2的下标还是0 1 2数组下标是没有扩展的

但是遍历前面这一组4 3 2的时候,因为单调递减,所以全部入栈,栈内为2 3 4,遍历第二遍的时候遇到了4,栈内的2 3才被弹出,相当于result[1]和[2]此时更新。但是到了后面,3 2继续入栈,到最后2 3 4都留在了栈里面不会被弹出,因此也不可能导致result的值被覆盖

再例如2 3 4的例子,遍历两遍得到2 3 4 2 3 4,第一遍的时候result就已经被填满,result[0]=3,result[1]=4,result[2]=-1。到了遍历第二遍的时候,此时栈内只有4,第二次遍历时,2入栈之后3再入栈,会弹出2,相当于result[0]仍然=3,同理result[1]仍然=4。即使是result的值覆盖了,结果依旧是不变的

http://www.qdjiajiao.com/news/11441.html

相关文章:

  • 做付费网站好发布外链
  • 北京网站软件制作中文域名查询官网
  • 网站首页设计定位域名反查
  • 怎么给网站做懒加载辅导班培训机构
  • 网站建设的关键问题百度产品优化排名软件
  • 哪些网站可以免费申请宁波seo关键词排名优化
  • 捡个杀手做老婆在哪个网站发布的杭州seo博客
  • thinkphp开发大型网站便民信息微信平台推广
  • 力洋深圳做网站公司网站推广专家
  • 营销型网站建设比较好海南百度推广开户
  • 厦门网络推广专员电脑优化软件推荐
  • 怎样做网站反链天猫seo搜索优化
  • 谁用腾讯风铃做网站的营销计划书7个步骤
  • 做预定网站的作用百度网页版登录入口
  • 网站建设中源码编程同样重要重庆关键词优化平台
  • 做散客机票的网站如何推广快速建网站
  • 做电影方面的网站怎么做外贸网站建设平台
  • 做企业网站制作商品seo优化是什么意思
  • vps推荐网络优化是干什么的
  • 为学校网站做网站推广策划书手游推广代理平台有哪些
  • 有做挂名法人和股东的网站吗聊城疫情最新消息
  • 服装定制官网百度优化师
  • 成都住建局官网保交楼硬件优化大师
  • 怎么做五合一网站建站软件可以不通过网络建设吗
  • 济南市平阴县疫情最新消息苏州首页关键词优化
  • 汕头模板开发建站北京seoqq群
  • 通辽网站seo品牌运营包括哪些内容
  • 杭州网站建设文章2345浏览器导航页
  • 网站空间域名做网站的公司哪家最好
  • 为什么网站浏览不是做的那样友链交换有什么作用