算法题016 -- [Implement Queue using Stacks] by java

本文探讨了如何仅使用标准堆栈操作实现队列的基本功能,包括push、pop、peek和empty。通过两个堆栈的巧妙运用,确保了队列的先进先出特性,即使在语言不直接支持原生堆栈的情况下,也能有效模拟队列行为。

题目

  • 使用堆栈实现队列的以下操作:
  • push(x) - 将元素x推送到队列的后面。
  • pop() - 从队列前面删除元素。
  • peek() - 获取前面的元素。
  • empty() - 返回队列是否为空。
  • 要求:
  • 必须仅使用堆栈的标准操作 - 这意味着只能从顶部添加元素、查看/弹出;队列大小,判空空操作是有效的。
  • 由于语言不同,可能不支持原生堆栈。 您可以使用列表或双端队列(双端队列)来模拟堆栈,只要您只使用堆栈的标准操作即可。
  • 您可以假设所有操作都是有效的(例如,不会在空队列上调用pop或Peek操作)。

分析

对于java而言,也就是使用 Stack 来实现 Queue…
后记:事实上这条题目比我预估的要难一点,用三个 stack 我能解决,用两个 stack ,参考了别的代码,做了点优化…这比用 queue 实现 stack 要难。

思路

在使用两个 stack 的做法中,其中一个stack是用来记录需要pop的元素

代码

package algorithm016;

import java.util.Stack;

public class Algorithm016 {

	public static void main(String[] args) {
		IQueue<Integer> queue = new StackQueue<Integer>();
		System.out.println(queue.pop());
		System.out.println(queue.peek());
		queue.push(4);
		System.out.println(queue.peek());
		System.out.println(queue.pop());
		queue.push(1);
		queue.push(0);
		System.out.println(queue.pop());
		System.out.println(queue.peek());
		queue.push(12);
		queue.push(2);
		queue.push(9);
		queue.push(5);
		System.out.println(queue.pop());
		System.out.println(queue.pop());
	}
	
}

interface IQueue<E>{
	E push(E item);
	E pop();
	E peek();
	boolean empty();
}

class StackQueue<E> implements IQueue<E> {
	
	Stack<E> stackTemp = new Stack<E>();
	Stack<E> stack = new Stack<E>();

	@Override
	public E push(E item) {
		if(item != null) 
			stackTemp.push(item);
		return item;
	}

	@Override
	public E pop() {
		if(stack.empty() && stackTemp.empty())
			return null;
		if(stack.empty() && !stackTemp.empty())
			peek();
		return stack.pop();
	}

	@Override
	public E peek() {
		if(stack.empty())
			while(stackTemp.size() != 0) {
				stack.push(stackTemp.pop());
			}
		if(stack.empty() && stackTemp.empty())
			return null;
		return stack.peek();
	}

	@Override
	public boolean empty() {
		return stack.empty() && stackTemp.empty();
	}	
}

<think>好的,我现在需要处理用户关于Java算法综合性问题的问题。用户希望得到综合性的Java算法面试题或练习题的前十名,并且要求结合站内引用内容。首先,我需要回顾用户提供的引用内容,看看是否有相关信息可以利用。 引用[1]提到面试流程包括算法题,通常为LeetCode高频题或剑指offer高频题。引用[2]列出了高频问题场景,如数组/链表操作、动态规划、哈希表、双指针、二叉树遍历,还提到时间复杂度优化和边界条件处理的重要性。引用[3]则涉及空间复杂度分析和哈希表的使用。 接下来,我需要结合这些信息,确定Java算法中的Top 10题目。通常来说,高频题目包括两数之和、反转链表、二叉树遍历、动态规划问题如爬楼梯、最长子序列、合并有序数组、括号生成、链表环检测、数组中的重复元素以及堆栈实现队列等。这些题目覆盖了引用中提到的主要场景和考察重点。 需要确保每个问题都符合用户的要求,并且引用相关的知识点。例如,两数之和可以使用哈希表优化,二叉树遍历涉及递归和迭代,动态规划问题需要时间复杂度优化等。同时,每个问题的解析应包含核心思路、时间复杂度和空间复杂度,以及可能的优化方法,如引用[3]提到的哈希表方法。 还要注意回答结构清晰,分点列出每个问题,确保语言简洁,符合中文回答的要求。最后,生成的相关问题需要围绕这些题目类型和考察点展开,帮助用户进一步深入学习。</think>### Java算法综合性问题Top 10(面试/练习) --- #### 1. **两数之和(Two Sum)** **问题**:给定整数数组和目标和,返回两数下标使它们的和等于目标值。 **核心**:哈希表(HashMap)实现$O(n)$时间复杂度[^3]。 **代码关键**: ```java public int[] twoSum(int[] nums, int target) { Map<Integer, Integer> map = new HashMap<>(); for (int i = 0; i < nums.length; i++) { int complement = target - nums[i]; if (map.containsKey(complement)) { return new int[] { map.get(complement), i }; } map.put(nums[i], i); } return new int[0]; } ``` --- #### 2. **反转链表(Reverse Linked List)** **问题**:单链表反转(迭代或递归)。 **考察点**:指针操作与边界条件处理[^2]。 **迭代法**: ```java public ListNode reverseList(ListNode head) { ListNode prev = null, curr = head; while (curr != null) { ListNode next = curr.next; curr.next = prev; prev = curr; curr = next; } return prev; } ``` --- #### 3. **二叉树的中序遍历(Inorder Traversal)** **问题**:输出二叉树中序遍历结果(递归与非递归)。 **考察点**:栈的应用与递归转迭代的能力[^2]。 **非递归实现**: ```java public List<Integer> inorderTraversal(TreeNode root) { List<Integer> res = new ArrayList<>(); Stack<TreeNode> stack = new Stack<>(); TreeNode curr = root; while (curr != null || !stack.isEmpty()) { while (curr != null) { stack.push(curr); curr = curr.left; } curr = stack.pop(); res.add(curr.val); curr = curr.right; } return res; } ``` --- #### 4. **爬楼梯(Climbing Stairs)** **问题**:每次爬1或2阶,求到达第$n$阶的方法数。 **动态规划**:状态转移方程$f(n) = f(n-1) + f(n-2)$,空间复杂度优化为$O(1)$。 ```java public int climbStairs(int n) { if (n <= 2) return n; int a = 1, b = 2; for (int i = 3; i <= n; i++) { int c = a + b; a = b; b = c; } return b; } ``` --- #### 5. **最长递增子序列(Longest Increasing Subsequence)** **问题**:求数组中最长递增子序列的长度。 **优化方法**:贪心+二分法,时间复杂度$O(n \log n)$。 **代码片段**: ```java public int lengthOfLIS(int[] nums) { int[] tails = new int[nums.length]; int len = 0; for (int num : nums) { int i = Arrays.binarySearch(tails, 0, len, num); if (i < 0) i = -(i + 1); tails[i] = num; if (i == len) len++; } return len; } ``` --- #### 6. **合并两个有序数组(Merge Sorted Array)** **问题**:将两个有序数组合并到第一个数组中。 **双指针技巧**:从后向前遍历避免覆盖原数据。 ```java public void merge(int[] nums1, int m, int[] nums2, int n) { int i = m - 1, j = n - 1, k = m + n - 1; while (j >= 0) { nums1[k--] = (i >= 0 && nums1[i] > nums2[j]) ? nums1[i--] : nums2[j--]; } } ``` --- #### 7. **括号生成(Generate Parentheses)** **问题**:生成所有有效的$n$对括号组合。 **回溯法**:剪枝条件控制左右括号数量平衡[^2]。 ```java public List<String> generateParenthesis(int n) { List<String> res = new ArrayList<>(); backtrack(res, "", 0, 0, n); return res; } private void backtrack(List<String> res, String s, int left, int right, int n) { if (s.length() == 2 * n) { res.add(s); return; } if (left < n) backtrack(res, s + "(", left + 1, right, n); if (right < left) backtrack(res, s + ")", left, right + 1, n); } ``` --- #### 8. **环形链表检测(Linked List Cycle)** **问题**:判断链表中是否存在环。 **快慢指针法**:Floyd判圈算法,时间复杂度$O(n)$。 ```java public boolean hasCycle(ListNode head) { ListNode slow = head, fast = head; while (fast != null && fast.next != null) { slow = slow.next; fast = fast.next.next; if (slow == fast) return true; } return false; } ``` --- #### 9. **数组中重复的数字(Find Duplicate Number)** **问题**:数组包含$n+1$个$[1, n]$的数,找到重复数。 **原地哈希法**:利用数值与下标映射关系。 ```java public int findDuplicate(int[] nums) { while (true) { int num = nums[0]; if (nums[num] == num) return num; nums[0] = nums[num]; nums[num] = num; } } ``` --- #### 10. **用栈实现队列(Implement Queue using Stacks)** **问题**:用两个栈模拟队列的先进先出特性。 **双栈反转法**:输入栈与输出栈配合,均摊时间复杂度$O(1)$[^2]。 ```java class MyQueue { Stack<Integer> in = new Stack<>(); Stack<Integer> out = new Stack<>(); public void push(int x) { in.push(x); } public int pop() { if (out.isEmpty()) { while (!in.isEmpty()) out.push(in.pop()); } return out.pop(); } } ``` --- ###
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值