IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 栈和队列(queue & stack) -> 正文阅读

[数据结构与算法]栈和队列(queue & stack)

栈和队列(queue & stack)

1 栈和队列

栈的特点是后入先出,根据这个特点可以临时保存一些数据,之后用到依次再弹出来,常用于 DFS 深度搜索。
队列的特点是先入先出,一般常用于 BFS 广度搜索,类似一层一层的搜索。

2 栈常见题目

2.1 (lee-155) 最小栈

设计一个支持 push ,pop ,top 操作,并能在常数时间内检索到最小元素的栈。

  • push(x) —— 将元素 x 推入栈中。
  • pop() —— 删除栈顶的元素。
  • top() —— 获取栈顶元素。
  • getMin() —— 检索栈中的最小元素。

输入
[“MinStack”,“push”,“push”,“push”,“getMin”,“pop”,“top”,“getMin”]
[[ ],[-2],[0],[-3],[ ],[ ],[ ],[ ]]
输出
[null,null,null,null,-3,null,0,-2]
解释
MinStack minStack = new MinStack();
minStack.push(-2);
minStack.push(0);
minStack.push(-3);
minStack.getMin(); --> 返回 -3.
minStack.pop();
minStack.top(); --> 返回 0.
minStack.getMin(); --> 返回 -2.

思路:用两个栈实现,一个最小栈始终保证最小值在顶部

public class MinStack {
	private Deque<Integer> stack; 
	private Deque<Integer> minStack;
	private int min;
	
	public MinStack() { //创建最小栈
		stack = new LinkedList<Integer>();
		minStack = new LinkedList<Integer>();
		min = Integer.MAX_VALUE;
	}
	
	public void push(int x) { //入栈
		stack.offerFirst(x);
		min = Math.min(min, x);
		minStack.offerFirst(min);
	}
	
	public void pop() {   //出栈
		stack.pollFirst();
		minStack.pollFirst();
		min = minStack.isEmpty() ? Integer.MAX_VALUE : minStack.peekFirst();
	}
	
	public int top() {   //返回栈顶
		return stack.peekFirst();
	}
	
	public int getMin() { //返回最小元素
		return minStack.peekFirst();	
	}
	
	public static void main(String[] args) {
		MinStack e = new MinStack();
		e.push(1);
		e.push(2);
		e.push(3);
		e.push(4);
		e.pop();
		int p = e.top();
		System.out.println(p);
		int q = e.getMin();
		System.out.println(q);	
	}
}

2.2 (lee-150) 逆波兰表达式求值

根据 逆波兰表示法,求表达式的值。有效的算符包括 +、-、*、/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:
整数除法只保留整数部分。
给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。

输入:tokens = [“2”,“1”,"+",“3”,"*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9

	/**
	 * 使用栈实现后缀表达式
	 * @param tokens
	 * @return
	 */
	public int evalRPN(String[] tokens) {
		Deque<Integer> stack = new LinkedList<Integer>();
		int n = tokens.length;
		for(int i = 0;i <n;i++) {
			String token = tokens[i];
			if(isNumber(token)) {
				stack.push(Integer.parseInt(token));
			}else {
				int num2 = stack.pop();
				int num1 = stack.pop();
				switch(token) {
					case "+":
						stack.push(num1+num2);
						break;
					case "-":
						stack.push(num1-num2);
						break;
					case "*":
						stack.push(num1*num2);
						break;
					case "/":
						stack.push(num1/num2);
						break;
					default:
				}
			}
		}
		return stack.pop();
	}
	
	private boolean isNumber(String token) {
		return !("+".equals(token) || "-".equals(token) || "*".equals(token) || "/".equals(token));
	}

	/**
	 * 创建数组模拟栈
	 * @param tokens
	 * @return
	 */
	public int evalRPN(String[] tokens) {
		int[] nums = new int[tokens.length/2+1]; //一个有效的逆波兰表达式,其长度n一定是奇数,且操作数的个数一定比运算符的个数多1个
		int index = 0; //数组下标 0 的位置对应栈底
		for (String s : tokens) {
			switch (s) {
			case "+":    //如果遇到运算符,则将两个操作数出栈,然后将一个新操作数入栈,因此栈内元素先减少 2 个再增加 1 个,结果是栈内元素减少 1 个
				nums[index - 2] += nums[--index];
				break;
			case "-":
				nums[index - 2] -= nums[--index];
				break;
			case "*":
				nums[index - 2] *= nums[--index];
				break;
			case "/":
				nums[index - 2] /= nums[--index];
				break;
			default:
				nums[index++]  = Integer.parseInt(s); //如果遇到操作数,则将操作数入栈,因此栈内元素增加 1 个
				break;
			}
		}
		return nums[0];
	}

2.3 (lee-394) 字符串解码

给定一个经过编码的字符串,返回它解码后的字符串。编码规则为: k[encoded_string],表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。

输入:s = “3[a]2[bc]”
输出:“aaabcbc”
输入:s = “3[a2[c]]”
输出:“accaccacc”

	/**
	 * 思路:数字一个栈,字母一个栈,取出来计算就可以了。
	 * @param s
	 * @return
	 */
	public String decodeString(String s) {
		StringBuilder res = new StringBuilder();
		LinkedList<Integer> numStack = new LinkedList<Integer>();
		LinkedList<StringBuilder> resStack = new LinkedList<StringBuilder>();
		int num =0;
		char[] c = s.toCharArray();
		for(int i = 0;i <c.length;i++) {
			if(c[i] >= '0' && c[i] <='9') {
				num = 10* num + Integer.parseInt(c[i] +"");
			}else if(c[i] == '[') {
				numStack.addLast(num);
				resStack.addLast(res);
				num  = 0;
				res = new StringBuilder();
			}else if(c[i] == ']') {
				StringBuilder temp = resStack.removeLast();
				int curNum = numStack.removeLast();
				for(int j = 0;j <curNum;j++) {
					temp.append(res);
				}
				res = temp;
			}else {
				res.append(c[i]);
			}
		}
		return res.toString();
	}

2.4 (lee-94) 二叉树的中序遍历

给定一个二叉树的根节点 root ,返回它的 中序 遍历。

输入:root = [1,null,2,3]
输出:[1,3,2]

	class TreeNode{
		int val;
		TreeNode left;
		TreeNode right;
		TreeNode(int x){
			val = x;
		}
	}
	/**
	 * 给定一个二叉树,返回它的中序遍历。
	 * 思路:通过stack 保存已经访问的元素,用于原路返回
	 * @param root
	 * @return
	 */
	public List<Integer> inorderTraversal(TreeNode root){
		if(root==null) {
			return new LinkedList<>();
		}
		List<Integer> res = new LinkedList<>();
		Deque<TreeNode> stack = new LinkedList<>();
		TreeNode node = root;
		while(node!= null || !stack.isEmpty()) {
			while(node!= null) {
				stack.addLast(node);
				node = node.left;
			}
			node = stack.removeLast();
			res.add(node.val);
			node = node.right;
		}
		return res;
	}

2.5 (lee-133) 克隆图

给你无向 连通 图中一个节点的引用,请你返回该图的 深拷贝(克隆)。

	class Node {
	    public int val;
	    public List<Node> neighbors;
	    public Node() {
	        val = 0;
	        neighbors = new ArrayList<Node>();
	    }
	    public Node(int _val) {
	        val = _val;
	        neighbors = new ArrayList<Node>();
	    }
	    public Node(int _val, ArrayList<Node> _neighbors) {
	        val = _val;
	        neighbors = _neighbors;
	    }
	}
	
	/**
	 * 给你无向连通图中一个节点的引用,请你返回该图的深拷贝(克隆)
	 * 递归:深度优先遍历
	 */
	
	public Node cloneGraph(Node node) {
		if(node==null) {
			return node;
		}
		HashMap<Node,Node> visited = new HashMap<>();
		if(visited.containsKey(node)) { // 如果visited存在node的克隆结点则返回克隆结点
			return visited.get(node);
		}
		Node cloneNode = new Node(node.val,new ArrayList<>());
		visited.put(node, cloneNode);
		
		for (Node neighbor : node.neighbors) {  // 设置好cloneNode结点的克隆结点
			cloneNode.neighbors.add(cloneGraph(neighbor)); // 递归node邻居结点的克隆结点
		}
		return cloneNode;
	}
	
	/**
	 * 广度优先遍历
	 */
	public Node cloneGraph2(Node node) {
		if(node==null) {
			return node;
		}
		HashMap<Node,Node> visited = new HashMap<>();
		LinkedList<Node> queue = new LinkedList<>(); //将原节点添加到队列
		visited.put(node, new Node(node.val, new ArrayList<>())); //克隆第一个节点并存储到哈希表中
		// 广度优先搜索
		while(!queue.isEmpty()) {
			Node n = queue.remove();  // 取出队列的头节点
			for(Node neighbor: n	.neighbors) { // 遍历该节点的邻居
				if(!visited.containsKey(neighbor)) { // 如果没有被访问过,就克隆并存储在哈希表中
					visited.put(neighbor, new Node(neighbor.val, new ArrayList<>()));
					queue.add(neighbor); // 将邻居节点加入队列中
				}
				visited.get(n).neighbors.add(visited.get(neighbor)); // 更新当前节点的邻居列表
			}
		}
		return visited.get(node);
		
	}

2.6 (lee-200) 岛屿数量

给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。此外,你可以假设该网格的四条边均被水包围。
思路:通过深度搜索遍历可能性

输入:grid = [
[“1”,“1”,“1”,“1”,“0”],
[“1”,“1”,“0”,“1”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“0”,“0”,“0”]
]
输出:1

2.6.2 暴力

	public int numIslands(char[][] grid) {
		if(grid.length==0) {
			return 0;
		}
		int total = 0;
		int row = grid.length;
		int col = grid[0].length;
		for(int i = 0;i < row;i++) {
			for(int j = 0;j < col;j++) {
				if(grid[i][j]=='1') {
					dfs(grid,i,j);
					total++;				
				}
			}
		}
		return total;
    }

2.6.2 深度搜索

	/**
	 * 深度搜索DFS
	 * @param grid 二维网格-岛屿
	 * @param x 
	 * @param y
	 * @return
	 */
	private void dfs(char[][] grid, int x, int y) {
		if(x < 0 || x >= grid.length || y < 0 || y >= grid[0].length || grid[x][y] != '1' ) {
			return;
		}
		grid[x][y] = '0';
		dfs(grid,x-1,y);
		dfs(grid,x+1,y);
		dfs(grid,x,y-1);
		dfs(grid,x,y+1);
	}

2.7 (lee-84) 柱状图中最大的矩形

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

输入: [2,1,5,6,2,3]
输出: 10

2.7.1 枚举宽 O(n*2)

	public int largestRectangleArea(int[] heights) {
		int n = heights.length;
		int ans = 0;
		// 枚举左边界
		for(int l = 0;l < n;l++) {
			int minHeight = Integer.MAX_VALUE;
			// 枚举右边界
			for(int r = l;r < n;r++) {
				minHeight = Math.min(minHeight, heights[r]);// 确定高度
				ans = Math.max(ans, (r-l+1)*minHeight); // 计算面积
			}
		}
		return ans;
	}

2.7.2 枚举高 O(n*2)

	public int largestRectangleArea2(int[] heights) {
		int n = heights.length;
		int ans = 0;
		for(int mid = 0;mid < n;mid++) {
			int height = heights[mid];// 枚举高
			int left = mid;
			int right = mid;
			while(left-1 >= 0 && heights[left-1] >= height) { // 确定左边界
				left--;
			}
			while(right+1  < n && heights[right+1] >= height) { // 确定右边界
				right++;
			}
			ans = Math.max(ans, (right-left+1)*height);// 计算面积
		}
		return ans;
	}

2.7.3 使用单调栈 O(N)

	public int largestRectangleArea3(int[] heights) {
		int n = heights.length;
        int[] left = new int[n];
        int[] right = new int[n];
        
        Stack<Integer> mono_stack = new Stack<Integer>();
        for (int i = 0; i < n; ++i) {
            while (!mono_stack.isEmpty() && heights[mono_stack.peek()] >= heights[i]) {
                mono_stack.pop();
            }
            left[i] = (mono_stack.isEmpty() ? -1 : mono_stack.peek());
            mono_stack.push(i);
        }

        mono_stack.clear();
        for (int i = n - 1; i >= 0; --i) {
            while (!mono_stack.isEmpty() && heights[mono_stack.peek()] >= heights[i]) {
                mono_stack.pop();
            }
            right[i] = (mono_stack.isEmpty() ? n : mono_stack.peek());
            mono_stack.push(i);
        }
        
        int ans = 0;
        for (int i = 0; i < n; ++i) {
            ans = Math.max(ans, (right[i] - left[i] - 1) * heights[i]);
        }
        return ans;
	}

2.7.4 使用deque 用时更少

	public int largestRectangleArea4(int[] heights) {
        int len = heights.length;
        if (len == 0) {
            return 0;
        }
        if (len == 1) {
            return heights[0];
        }
        int[] newHeights = new int[len + 2]; //左右边界包含
        for (int i = 0; i < len; ++i) {
            newHeights[i + 1] = heights[i];
        }
        int maxArea = 0;
        len += 2;
        heights = newHeights;
        Deque<Integer> stack = new LinkedList<>();
        stack.addFirst(0);
        for (int i = 1; i < len; ++i) {
            while (heights[stack.peekFirst()] > heights[i]) {
                int height = heights[stack.removeFirst()];
                int width = i - stack.peekFirst() - 1;
                maxArea = Math.max(maxArea, height * width);
            }
            stack.addFirst(i);
        }
        return maxArea;
    }

2.8 (lee-42) 接雨水

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

输入:height = [0,1,0,2,1,0,1,3,2,1,2,1]
输出:6
解释:上面是由数组 [0,1,0,2,1,0,1,3,2,1,2,1] 表示的高度图,在这种情况下,可以接 6 个单位的雨水(蓝色部分表示雨水)。

2.8.1 动态规划

	/**
	 * 1.动态规划
	 * 时间复杂度O(n)
	 * 空间复杂度O(n)
	 * 需要维护两个数组 leftMax 和 rightMax
	 * @param height
	 * @return
	 */
	public int trap(int[] height) {
		int n = height.length;
		if(n==0) {
			return 0;
		}
		
		int[] leftMax = new int[n];
		leftMax[0] = height[0];
		for(int i = 1;i < n;++i) {
			leftMax[i] = Math.max(leftMax[i-1], height[i]);
		}
		
		int[] rightMax = new int[n];
		rightMax[n-1] = height[n-1];
		for(int i = n-2;i >=0;--i) {
			rightMax[i] = Math.max(rightMax[i+1], height[i]);
		}
		
		int res = 0;
		for(int i= 0;i<n;i++) {
			res += Math.min(leftMax[i], rightMax[i]) - height[i];
		}
		return res;
	}

2.8.2 单调栈

	/**
	 * 2.单调栈
	 * 时间复杂度O(n)
	 * 空间复杂度O(n)
	 * @param height
	 * @return
	 */
	public int trap2(int[] height) {
		int res = 0;
		Deque<Integer> stack = new LinkedList<Integer>();
		int n = height.length;
		for(int i = 0;i < n;i++) {
			while(!stack.isEmpty() && height[i] > height[stack.peek()]) {
				int top = stack.pop();
				if(stack.isEmpty()) {
					break;
				}
				int left = stack.peek();
				int curWidth = i-left-1;
				int curHeight = Math.min(height[left], height[i]) - height[top];
				res += curWidth * curHeight;
						
			}
			stack.push(i);
		}
		return res;
	}

2.8.3 双指针

	/**
	 * 3.使用双指针
	 * 时间复杂度O(n)
	 * 空间复杂度O(1)
	 * 维护两个指针 left 和 right,以及两个变量 leftMax 和 rightMax
	 * @param height
	 * @return
	 */
	public int trap3(int[] height) {
		int res = 0;
		int left = 0;
		int right = height.length-1;
		int leftMax = 0;
		int rightMax = 0;
		while(left < right) {
			leftMax = Math.max(leftMax, height[left]);
			rightMax = Math.max(rightMax, height[right]);
			if(height[left] < height[right]) {
				res += leftMax - height[left];
				++left;
			}else {
				res += rightMax - height[right];
				--right;
			}
		}
		return res;
	}

2.9 (lee-227)基本计算器2

给你一个字符串表达式 s ,请你实现一个基本计算器来计算并返回它的值。整数除法仅保留整数部分(无括号)。
思路:我们可以用一个栈,保存这些(进行乘除运算后的)整数的值,对于加减号后的数字,将其直接压入栈中;对于乘除号后的数字,可以直接与栈顶元素计算,并替换栈顶元素为计算后的结果。
时间复杂度O(n)
空间复杂度O(n)

输入:s = “3+2*2”
输出:7

	public int calculate(String s) {
        Deque<Integer> stack = new LinkedList<Integer>();//数字栈	
        char preSign = '+';  //符号栈用一个变量preSigh代替,只存储上一个符号
        int num = 0;
        int n = s.length();
        for (int i = 0; i < n; ++i) {
        	char cur = s.charAt(i);
            if (cur >= '0') {
                num = num * 10 - '0'+ cur;// 记录当前数字。先减,防溢出
            }
            if ((cur < '0' && cur != ' ' )|| i == n - 1) {
                switch (preSign) {
                    case '+':
                        stack.push(num);
                        break;
                    case '-':
                        stack.push(-num);
                        break;
                    case '*':
                        stack.push(stack.pop() * num);
                        break;
                    default:
                        stack.push(stack.pop() / num);
                }
                preSign = s.charAt(i); //保存当前符号
                num = 0; //数字清0
            }
        }
        int ans = 0;
        while (!stack.isEmpty()) {
            ans += stack.pop();
        }
        return ans;
    }

3 队列常见题目

3.1 (lee-232) 用栈实现队列

请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作(push、pop、peek、empty)
实现 MyQueue 类:

  • void push(int x) 将元素 x 推到队列的末尾
  • int pop() 从队列的开头移除并返回元素
  • int peek() 返回队列开头的元素
  • boolean empty() 如果队列为空,返回 true ;否则,返回 false

输入
[“MyQueue”, “push”, “push”, “peek”, “pop”, “empty”]
[[], [1], [2], [], [], []]
输出
[null, null, null, 1, 1, false]
解释
MyQueue myQueue = new MyQueue();
myQueue.push(1); // queue is: [1]
myQueue.push(2); // queue is: [1, 2] (leftmost is front of the queue)
myQueue.peek(); // return 1
myQueue.pop(); // return 1, queue is [2]
myQueue.empty(); // return false

public class QueueUseStack {
	public QueueUseStack(){}
	
	private Deque<Integer> stackA = new LinkedList<>();//栈A作为队列的入口,负责插入新元素
	private Deque<Integer> stackB = new LinkedList<>();//栈B作为队列的出口,负责移除老元素
	
	//入队操作
	public void enQueue(int x) {
		stackA.addFirst(x);
	}
	
	//出队操作
	public Integer deQueue() {
		if(stackB.isEmpty()) {
			if(stackA.isEmpty()) {
				return null;
			}
			transfer();
		}
		return stackB.removeFirst();
	}
	
	//栈A元素转移到栈B
	private void transfer() {
		while(!stackA.isEmpty()) {
			stackB.addFirst(stackA.removeFirst());
		}
	}

	public static void main(String[] args) {
		QueueUseStack qus = new QueueUseStack();
		qus.enQueue(1);
		qus.enQueue(2);
		qus.enQueue(3);
		System.out.println(qus.deQueue());
		System.out.println(qus.deQueue());
		qus.enQueue(4);
		System.out.println(qus.deQueue());	
	}
}

3.2 (lee-102) 二叉树的层序遍历

给你一个二叉树,请你返回其按 层序遍历 得到的节点值。 (即逐层地,从左到右访问所有节点)

二叉树:[3,9,20,null,null,15,7],
[ [3],
[9,20],
[15,7] ]

	class TreeNode{
		int val;
		TreeNode left;
		TreeNode right;
		TreeNode(int x){
			val = x;
		}
	}
	/**
	 * 二叉树层次遍历
	 * @param root
	 * @return
	 */
	public List<List<Integer>> levelOrder(TreeNode root){
		if(root==null) {
			return null;
		}
		List<List<Integer>> res = new LinkedList<>();
		Queue<TreeNode> queue  = new LinkedList<>();
		queue.offer(root);
		while(!queue.isEmpty()) {   //注意
			int size = queue.size();
			List<Integer> list = new ArrayList<>();
			for(int i = 0;i <size;i++) {
				TreeNode node = queue.remove();
				list.add(node.val);
				if(node.left != null) {
					queue.offer(node.left);
				}
				if(node.right != null) {
					queue.offer(node.right);
				}
			}
			res.add(list);
		}
		return res;
	}

3.3 (lee-542) 01矩阵

给定一个由 0 和 1 组成的矩阵,找出每个元素到最近的 0 的距离。两个相邻元素间的距离为 1。

输入
[[0,0,0],
[0,1,0],
[0,0,0]]
输出
[[0,0,0],
[0,1,0],
[0,0,0]]

动态规划

	public int[][] updateMatrix(int[][] matrix){
		int row = matrix.length;
		int col = matrix[0].length;
		int[][] dist = new int[row][col];
		int MAX_TEMP  = Integer.MAX_VALUE/2;
		 // 如果 (i, j) 的元素为 0,那么距离为 0,否则设置成一个很大的数
		for(int i = 0;i < row;i++) {
			for(int j = 0;j < col;j++) {
				if(matrix[i][j]==0) {
					dist[i][j] = 0;
				}else {
					dist[i][j] = MAX_TEMP;
				}
			}
		}
		// 水平向左移动 和 竖直向上移动
		for(int i =0;i < row;i++) {
			for(int j = 0;j < col;j++) {
				if(i-1 >= 0) {
					dist[i][j] = Math.min(dist[i][j], dist[i-1][j]+1);
				}	
				if(j-1 >= 0) {
					dist[i][j] = Math.max(dist[i][j], dist[i][j-1]+1);
				}
			}
		}
		 // 水平向右移动 和 竖直向下移动
		for(int i = row-1;i >= 0;i--) {
			for(int j = col-1;j >= 0;j--) {
				if(i+1 < row) {
					 dist[i][j] = Math.min(dist[i][j], dist[i + 1][j] + 1);
				}
				if(j+1 < col) {
					 dist[i][j] = Math.min(dist[i][j], dist[i][j+1] + 1);
				}
			}
		}
		return dist;
	}

4 总结

  • 熟悉栈的使用场景
    • 后出先出,保存临时值
    • 利用栈 DFS 深度搜索
  • 熟悉队列的使用场景
    • 利用队列 BFS 广度搜索

5 练习链接

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-14 23:11:55  更:2021-07-14 23:13:22 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/8 10:55:57-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码