【算法与数据结构】496、503、LeetCode下一个更大元素I II

文章目录

  • 一、496、下一个更大元素 I
  • 二、503、下一个更大元素II
  • 三、完整代码

所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。

一、496、下一个更大元素 I

在这里插入图片描述

  思路分析:本题思路和【算法与数据结构】739、LeetCode每日温度类似。如果用暴力破解法时间复杂度需要 O ( m ∗ n ) O(m*n) O(mn),其中 m m m n n n分别是两个数组的长度。单调栈只需要 O ( n + m ) O(n+m) O(n+m)的时间复杂度。相较于739题,本题需要找到nums1元素在nums2数组中的位置,那么我们可以利用unordered_map,查找和增删效率是最高的【算法与数据结构】算法与数据结构知识点:

	unordered_map<int, int> umap; // key:下标元素,value:下标
	for (int i = 0; i < nums1.size(); i++) {
		umap[nums1[i]] = i;
	}

  然后利用739题的单调栈思路,遍历nums2数组。每当当前遍历元素大于栈顶元素,并且nums2数组的元素在nums1中存在(umap.count(nums2[st.top()]) > 0就是统计数量,大于零说明nums2[st.top()]元素存在),我们找到栈顶元素在nums1中的下标,在结果数组中根据下标修改其值:

	for (int i = 0; i < nums2.size(); i++) {			
		while (!st.empty() && nums2[i] > nums2[st.top()]) {
			if (umap.count(nums2[st.top()]) > 0) { // 看map里是否存在这个元素,count函数计算数量
				int index = umap[nums2[st.top()]]; // 根据map找到nums2[st.top()] 在 nums1中的下标
				result[index] = nums2[i];
			}
			st.pop();
		}
		st.push(i); // 插入数组的下标
	}

  程序如下

// 496、下一个更大元素 I
class Solution {
public:
	vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
		vector<int> result(nums1.size(), -1);
		stack<int> st;
		unordered_map<int, int> umap; // key:下标元素,value:下标
		for (int i = 0; i < nums1.size(); i++) {
			umap[nums1[i]] = i;
		}
		for (int i = 0; i < nums2.size(); i++) {			
			while (!st.empty() && nums2[i] > nums2[st.top()]) {
				if (umap.count(nums2[st.top()]) > 0) { // 看map里是否存在这个元素,count函数计算数量
					int index = umap[nums2[st.top()]]; // 根据map找到nums2[st.top()] 在 nums1中的下标
					result[index] = nums2[i];
				}
				st.pop();
			}
			st.push(i); // 插入数组的下标
		}
		return result;
	}
};

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

二、503、下一个更大元素II

在这里插入图片描述

  思路分析:本题和496题不同之处在于从两个数组变成一个数组,然后数组是环形数组。针对环形数组,我们要比较大小,可以将环形数组复制一份,两个相同的数组扩充成一个新数组。然后在新数组上去做单调栈的操作。
  程序如下

// 503、下一个更大元素II-版本一
class Solution2 {
public:
	vector<int> nextGreaterElements(vector<int>& nums) {
		vector<int> nums1(nums.begin(), nums.end()); // 拼接一个新的nums
		nums.insert(nums.end(), nums1.begin(), nums1.end());		
		vector<int> result(nums.size(), -1);	// 用新的nums大小来初始化result

		// 开始单调栈
		stack<int> st;
		st.push(0);
		for (int i = 1; i < nums.size(); i++) {
			while (!st.empty() && nums[i] > nums[st.top()]) {
				result[st.top()] = nums[i];
				st.pop();
			}
			st.push(i);
		}
		result.resize(nums.size() / 2);		// 最后再把结果集即result数组resize到原数组大小
		return result;
	}
};

  虽然这种写法比较直观,但是做了很多无用操作。resize函数是O(1)的操作,但扩充nums数组相当于多了一个O(n)的操作。其实也可以不扩充nums,而是在遍历的过程中模拟走了两边nums。例如我们改变索引的上界,然后令其做取nums.size()模的操作。

// 503、下一个更大元素II-版本二
class Solution3 {
public:
	vector<int> nextGreaterElements(vector<int>& nums) {
		vector<int> result(nums.size(), -1);
		stack<int> st;
		for (int i = 0; i < nums.size() * 2; i++) {
			// 模拟遍历两边nums,注意一下都是用i % nums.size()来操作
			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;
	}
};

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n)
  • 空间复杂度: O ( n ) O(n) O(n)

三、完整代码

# include <iostream>
# include <vector>
# include <unordered_map>.
# include <stack>
using namespace std;

// 496、下一个更大元素 I
class Solution {
public:
	vector<int> nextGreaterElement(vector<int>& nums1, vector<int>& nums2) {
		vector<int> result(nums1.size(), -1);
		stack<int> st;
		unordered_map<int, int> umap; // key:下标元素,value:下标
		for (int i = 0; i < nums1.size(); i++) {
			umap[nums1[i]] = i;
		}
		for (int i = 0; i < nums2.size(); i++) {			
			while (!st.empty() && nums2[i] > nums2[st.top()]) {
				if (umap.count(nums2[st.top()]) > 0) { // 看map里是否存在这个元素,count函数计算数量
					int index = umap[nums2[st.top()]]; // 根据map找到nums2[st.top()] 在 nums1中的下标
					result[index] = nums2[i];
				}
				st.pop();
			}
			st.push(i); // 插入数组的下标
		}
		return result;
	}
};

// 503、下一个更大元素II-版本一
class Solution2 {
public:
	vector<int> nextGreaterElements(vector<int>& nums) {
		vector<int> nums1(nums.begin(), nums.end()); // 拼接一个新的nums
		nums.insert(nums.end(), nums1.begin(), nums1.end());		
		vector<int> result(nums.size(), -1);	// 用新的nums大小来初始化result

		// 开始单调栈
		stack<int> st;
		st.push(0);
		for (int i = 1; i < nums.size(); i++) {
			while (!st.empty() && nums[i] > nums[st.top()]) {
				result[st.top()] = nums[i];
				st.pop();
			}
			st.push(i);
		}
		result.resize(nums.size() / 2);		// 最后再把结果集即result数组resize到原数组大小
		return result;
	}
};

// 503、下一个更大元素II-版本二
class Solution3 {
public:
	vector<int> nextGreaterElements(vector<int>& nums) {
		vector<int> result(nums.size(), -1);
		if (nums.size() == 0) return result;
		stack<int> st;
		for (int i = 0; i < nums.size() * 2; i++) {
			// 模拟遍历两边nums,注意一下都是用i % nums.size()来操作
			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;
	}
};

int main() {
	//vector<int> nums1 = { 4,1,2 };
	//vector<int> nums2 = { 1,3,4,2 };
	//Solution s1;
	//vector<int> result = s1.nextGreaterElement(nums1, nums2);

	vector<int> nums = { 1,2,3,4,3 };
	Solution2 s1;
	vector<int> result = s1.nextGreaterElements(nums);

	for (vector<int>::iterator i = result.begin(); i != result.end(); i++) {
		cout << *i << " ";
	}
	cout << endl;

	system("pause");
	return 0;
}

end

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

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

相关文章

大脑是宇宙中最复杂的物体——科学家们试图破译它,读懂人们的思想

2023年&#xff0c;德克萨斯大学HuthLab进行的一项研究在神经科学和技术领域引发了震动。通过人工智能(AI)和脑成像技术的结合&#xff0c;无法与外界交流的人的思想首次被翻译成连续的自然语言。 这是迄今为止最接近读心术的科学方法。在过去的二十年里&#xff0c;神经成像技…

Zookeeper集群搭建(3台)

准备工作 1、提前安装好hadoop102、hadoop103、hadoop104三台机器&#xff0c;参照&#xff1a;CentOS7集群环境搭建&#xff08;3台&#xff09;-CSDN博客 2、提前下载好Zookeeper安装包并上传到/opt/software上、安装包&#xff0c;链接&#xff1a;https://pan.baidu.com/…

如何解决利用cron定时任务自动更新SSL证书后Nginx重启问题

利用cron定时任务自动更新SSL证书后&#xff0c;用浏览器访问网站&#xff0c;获取到的证书仍然是之前的。原因在于没有对Nginx进行重启。 据说certbot更新完成证书后会自动重启Nginx,但显然经我检测不是这回事儿。 所以我们需要创建一bash脚本&#xff0c;然后定时调用这个脚…

Java多线程:定时器

&#x1f451;专栏内容&#xff1a;Java⛪个人主页&#xff1a;子夜的星的主页&#x1f495;座右铭&#xff1a;前路未远&#xff0c;步履不停 目录 一、Timer类二、手动实现定时器1、实现逻辑2、问题描述2.1、问题一&#xff1a;线程安全问题2.2、问题二&#xff1a;使用 slee…

[C# WPF] DataGrid选中行或选中单元格的背景和字体颜色修改

问题描述 WPF中DataGrid的选中行或选中者单元格&#xff0c;在焦点失去后&#xff0c;颜色会很淡&#xff0c;很不明显&#xff0c;不容易区分。 解决方法 在失去焦点的情况下&#xff0c;如何设置行或单元格与选中的时候颜色一样&#xff1f; <DataGrid.Resources>&…

滑块识别验证

滑块识别 1. 获取图片 测试网站&#xff1a;https://www.geetest.com/adaptive-captcha-demo 2. 点击滑块拼图并开始验证 # 1.打开首页 driver.get(https://www.geetest.com/adaptive-captcha-demo)# 2.点击【滑动拼图验证】 tag WebDriverWait(driver, 30, 0.5).until(la…

利用YOLOv8 pose estimation 进行 人的 头部等马赛克

文章大纲 马赛克几种OpenCV 实现马赛克的方法高斯模糊pose estimation 定位并模糊:三角形的外接圆与膨胀系数实现实现代码实现效果参考文献与学习路径之前写过一个文章记录,怎么对人进行目标检测后打码,但是人脸识别有个问题是,很多人的背影,或者侧面无法识别出来人脸,那…

Golang GC 介绍

文章目录 0.前言1.发展史2.并发三色标记清除和混合写屏障2.1 三色标记2.2 并发标记问题2.3 屏障机制Dijkstra 插入写屏障Yuasa 删除写屏障混合写屏障 3.GC 过程4.GC 触发时机5.哪里记录了对象的三色状态&#xff1f;6.如何观察 GC&#xff1f;方式1&#xff1a;GODEBUGgctrace1…

算法学习——LeetCode力扣二叉树篇1

算法学习——LeetCode力扣二叉树篇1 144. 二叉树的前序遍历 144. 二叉树的前序遍历 - 力扣&#xff08;LeetCode&#xff09; 描述 给你二叉树的根节点 root &#xff0c;返回它节点值的 前序 遍历。 示例 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&a…

大水仙花数求解

输入位数&#xff0c;求解水仙花数。暴力求解&#xff0c;位数如果太多&#xff0c;会超时。 思路&#xff1a; &#xff08;1&#xff09;11333355和33331155看上去是不一样的两个数&#xff0c;但是它们又一样&#xff0c;因为相同数字出现的次数一样。 &#xff08;2&…

深度学习图像分类相关概念简析+个人举例3(CNN相关补充,附详细举例代码1)

【1】激活函数&#xff08;Activation Function&#xff09;&#xff1a;在深度学习&#xff08;CNN&#xff09;中&#xff0c;激活函数用于引入非线性性质&#xff0c;帮助模型学习复杂的关系。常见的激活函数有ReLU、Sigmoid和Tanh等。 &#xff08;1&#xff09;ReLU激活函…

2万字曝光:华尔街疯狂抢购比特币背后

作者/来源&#xff1a;Mark Goodwin and whitney Webb BitcoinMagazine 编译&#xff1a;秦晋 全文&#xff1a;19000余字 在最近比特币ETF获得批准之后&#xff0c;贝莱德的拉里-芬克透露&#xff0c;很快所有东西都将被「ETF化」与代币化&#xff0c;不仅威胁到现有的资产和商…

详细介绍Python网络编程模块

根据前面对网络分层棋型的介绍&#xff0c;我们知道实际的网络模型大致分为四层&#xff0c;这四层各有对应的网络协议提供支持&#xff0c; 网络层协议主要是 IP&#xff0c;它是所有互联网协议的基础&#xff0c;其中 ICMP&#xff08;Internet Control Message Protocol&…

JAVA设计模式之策略模式详解

策略模式 1 策略模式概述 策略模式(strategy pattern)的原始定义是&#xff1a;定义一系列算法&#xff0c;将每一个算法封装起来&#xff0c;并使它们可以相互替换。策略模式让算法可以独立于使用它的客户端而变化。 其实我们在现实生活中常常遇到实现某种目标存在多种策略…

Netty应用(一) 之 NIO概念 基本编程

目录 第一章 概念引入 1.分布式概念引入 第二章 Netty基础 - NIO 1.引言 1.1 什么是Netty&#xff1f; 1.2 为什么要学习Netty&#xff1f; 2.NIO编程 2.1 传统网络通信中开发方式及问题&#xff08;BIO&#xff09; 2.1.1 多线程版网络编程 2.1.2 线程池版的网络编程…

6.JavaScript中赋值运算符,自增运算符,比较运算符,逻辑运算符

赋值运算符 就是简单的加减乘除&#xff0c;没啥可说的这里直接上代码比较好 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><…

一文彻底搞懂Kafka如何保证消息不丢失

文章目录 1. kafka 架构2. producer端是如何保证数据不丢失的2.1 同步发送2.2 异步发送2.3 批量发送 3. consumer端是如何保证数据不丢失的3.1 手动提交3.2 幂等性消费 4. broker端是如何保证数据不丢失的4.1 副本机制4.2 ISR机制4.3 刷盘机制 1. kafka 架构 Producer&#xff…

redis的主从配置模拟(一主双从)

目录 先来给大家扩展机道面试官经常会问到关于redis的题 一、redis有哪些好处 二、redis相比memcached有哪些优势 三、redis常见性能问题和解决方案 四、redis集群的工作原理 五、redis主从的原理 redis的主从配置模拟&#xff08;一主双从&#xff09; 一、准备环境 …

二级建造师试题答案?学生党都在用的6款搜题工具来了 #学习方法#学习方法#微信

作为大学生&#xff0c;我们应该善于利用各种学习工具&#xff0c;提高学习效率和质量。 1.灵兔搜题 这是一个公众号 包含大学网课、课后教材、选修课、mooc慕课及各类职业资格证、学历提升考试、公务员考试等常见题库。 下方附上一些测试的试题及答案 1、Uri主要由三部分组…

spark sql上线前的调试工作实现

背景 每个公司应该都有大数据的平台的吧&#xff0c;平台的作用就是可以在上面执行各种spark sql以及定时任务&#xff0c;不过一般来说&#xff0c;由于这些spark sql的上线不经过测试&#xff0c;所以可能会影响到生产的数据&#xff0c;这种情况下大数据平台提供一个上线前…