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

算法通关村第五关—队栈和Hash的经典问题(白银)

 emsp;emsp;emsp队栈和Hash的经典问题

用栈实现队列

栈是先进后出,队列是先进先出,所以可以使用两个栈来实现队列的功能。
LeetCode232:
请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、
empty):
截屏2023-11-30 21.18.57.png
思路:
(1)一个栈作为输入栈,支持push操作,一个栈作为输出栈,支持pop和peek操作
(2)每次pop或peek时,如果输出栈为空,则把输入栈的元素弹出并压入输出栈,此时输出栈从栈顶到栈尾的顺序就是队列从队首道队尾的顺序

class MyQueue{
	Deque<Integer>inStack;
	Deque<Integer>outstack;
	public MyQueue(){
		inStack = new LinkedList<Integer>();
		outStack = new LinkedList<Integer>();
	}
	public void push(int x){
		inStack.push(x);
	}
	public int pop(){
		if (outStack.isEmpty()) in2out();
		return outstack.pop();
	}
	public int peek(){
		if (outstack.isEmpty()) in2out();
		return outstack.peek();
	}
	public boolean empty(){
		return instack.isEmpty() && outstack.isEmpty();
	}
	private void in2out(){
		while (!instack.isEmpty()) outstack.push(instack.pop());
	}
}

用队列实现栈

leetcode225:
请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop和empty)。
实现MyStack类:
截屏2023-11-30 21.36.40.png
思路:同样,可以使用两个队列来实现栈。为了满足栈道特性,要满足最后入栈道元素位于队列的队首。
那么可以使用queue1用于存储栈内的元素,queue2作为入栈操作的辅助队列。
入栈时,将将元素入队到queue2,然后将queue1的全部元素依次出队后入队到queue2。此时,queue2的前面的元素就是新入栈的元素,再将queue1与queue2互换,则queue1元素即为栈内元素,队头为栈顶
出栈或取栈顶时,取queue1的队头即可
判空时,判断queue1即可

class Mystack{
	Queue<Integer>queuel;
	Queue<Integer>queue2;
	public MyStack(){
		queue1 = new LinkedList<Integer>();
		queue2 = new LinkedList<Integer>();
	}
	public void push(int x){
		queue2.offer(x);
		while (!queue1.isEmpty()) queue2.offer(queue1.poll());
		Queue<Integer>temp queue1;
		queue1 queue2;
		queue2 temp;
	}
	public int pop(){
		return queue1.poll();
	}
	public int top(){
		return queue1.peek();
	}
	public boolean empty(){
		return queue1.isEmpty();
	}
}

n数之和专题

我的LeetCode的第一题就是求两数之和的问题,当时还只会暴力,不会Hash之类的方法,看到题解差点劝退了。
事实上除此之外,还有几个类似的问题,例如LeetCode15三数之和,LeetCode18.四数相加和LeetCode454.四数相加ll等等。我们就集中看一下。

3.1 两数之和

LeetCode1.给定一个整数数组nums和一个整数目标值target,请你在该
数组中找出和为目标值target的那两个整数,并返回它们的数组下标。你
可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里
不能重复出现。你可以按任意顺序返回答案。
截屏2023-12-01 10.46.34.png
这种题用两层for循环时间复杂度太高,不采用
可以利用哈希表,把遍历过的值保存起来,这样只需寻找target-nums[i]在哈希表中是否存在即可

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer, Integer> map = new HashMap<>(); //创建一个哈希表map
        for (int i = 0; i < nums.length; i++) { //从数组第一个数遍历到最后一个数
            if (map.containsKey(target - nums[i])) return new int[]{map.get(target - nums[i]), i}; //判断 目标值减去当前值 得到的值在哈希表是否存在(一石二鸟,通过一个数找到另一个数),若存在,证明已达到题目的要求,直接返回这两个数的索引位
            else map.put(nums[i], i);// 上面的if不成立,把当前值存入map哈希表中,注意,key保存当前整数值,value保存对应的索引值
        }
        return new int[]{}; //虽然题目保证能找到,但按照语法要求,还是要返回一个int型数组,比如会报错
    }
}

3.2 三数之和

如果将两个数换成三个会怎样呢?
LeetCode15.给你一个包含n个整数的数组nums,判断nums中是否存在三个元素a,b,c,使得a+b+c=0?请你找出所有和为0且不重复的三元组。注意:答案中不可以包含重复的三元组。
截屏2023-12-01 11.07.00.png
本题看似就是两数增加了一个数,但是难度增加了很多,我们可以使用三
层循环直接找,时间复杂度为O(3),太高了,放弃。
也可以使用双层循环+Hash来实现,首先按照第一题两数之和的思路,我们可以固定一个数target,再利用两数之和的思想去map中存取或查找(-1)*target-num[j],但是这样的问题是无法消除重复结果,例如如果输入[-1,0,1,2,-1,-4],返回的结果是[-1,1,0],[-1,-1,2],[0,1,-1],[0,-1,1],[1,-1,0],[2,-1,-],如果我们再增加一个去重方法,将直接导致执行超时。

那这时候,我们就要想其他方法了,这个公认最好的方式是”排序+双指针我们可以先将数组排序来处理重复结果,然后还是固定一位元素,由于数组是排好序的,所以我们用双指针来不断寻找即可求解,代码如下:

class Solution{
	public List<List<Integer>>threeSum(int[]nums){
		int n = nums.length;
		Arrays.sort(nums);
		List<List<Integer>>ans = new ArrayList();
		//枚举a
		for (int first = 0;first < n; first++){
			//需要和上一次枚举的数不相同
			if (first > 0 && nums[first] = nums[first - 1]) continue;
			//C对应的指针初始指向数组的最右端
			int third = n - 1;
			int target = -nums[first];
			//枚举b
			for (int second  = first + 1; second < n; second++){
				//需要和上一次枚举的数不相同
				if (second > first + 1 && nums[second] == nums[second - 1]) continue;
				//需要保证b的指针在c的指针的左侧
				while (second < third && nums[second] + nums[third] > target) --third;

				//如果指针重合,随着b后续的增加
				//就不会有满足a+b+c=0并且b<c的c了,可以退出循环
				if (second == third) break;

				if (nums[second] + nums[third] == target){
					List<Integer>list new ArrayList<Integer>();
					list.add(nums [first]);
					list.add(nums [second]);
					list.add(nums [third]);
					ans.add(list);
				}
			}
		}
		return ans;
	}
}

http://www.kler.cn/a/152449.html

相关文章:

  • 人才缺口达150万!云计算凭什么这么火?
  • 计算机网络(二)
  • Spring Security 6.x 系列(7)—— 源码分析之Builder设计模式
  • 【办公软件】电脑开机密码忘记了如何重置?
  • 通过lua脚本在redis中处理json数据
  • web:ics-05(本地文件包含漏洞、preg_replace函数/e漏洞、php伪协议读取文件)
  • 服务器内存使用率高的原因及解决方法_Maizyun
  • Docker配置Halo搭建个人博客-快速入门
  • 压力测试+接口测试
  • 形态学操作—底帽运算
  • 易石无代码开发:电商平台连接CRM与客服系统,实现营销自动化
  • java 偏向锁 10个课题
  • leetcode704. 二分查找
  • 前端页面构成有哪些,分别是什么?
  • 容器技术发展史,编排与容器的技术演进之路——2
  • 探索容灾架构演进之路,从单点到异地多活
  • FLASK博客系列6——数据库之谜
  • 微调Fine tune
  • 2023年中国金融科技研究报告
  • 深度学习手势识别 - yolo python opencv cnn 机器视觉 计算机竞赛