数据结构——栈与队列相关题目
数据结构——栈与队列相关题目
- 232. 用栈实现队列
- 思路
- 225. 用队列实现栈
- 1.两个队列实现栈
- 2.一个队列实现栈
- 20. 有效的括号
- 思路
- 1047. 删除字符串中的所有相邻重复项
- 思路
- 155. 最小栈
- 150. 逆波兰表达式求值
- 思路
- 239. 滑动窗口最大值
- 单调队列
- 347. 前 K 个高频元素
- 思路
232. 用栈实现队列
232. 用栈实现队列
使用栈实现队列的下列操作:
- push(x) – 将一个元素放入队列的尾部。
- pop() – 从队列首部移除元素。
- peek() – 返回队列首部的元素。
- empty() – 返回队列是否为空。
说明:
你只能使用标准的栈操作 – 也就是只有 push to top, peek/pop from top, size, 和 is empty 操作是合法的。
你所使用的语言也许不支持栈。你可以使用 list 或者 deque(双端队列)来模拟一个栈,只要是标准的栈操作即可。
假设所有操作都是有效的 (例如,一个空的队列不会调用 pop 或者 peek 操作)。
思路
需要两个栈一个输入栈,一个输出栈,这里要注意输入栈和输出栈的关系。
在push数据的时候,只要数据放进输入栈就好,但在pop的时候,操作就复杂一些,输出栈如果为空,就把进栈数据全部导入进来(注意是全部导入),再从出栈弹出数据,如果输出栈不为空,则直接从出栈弹出数据就可以了。
最后如何判断队列为空呢?如果进栈和出栈都为空的话,说明模拟的队列为空了。
class MyQueue {Stack<Integer> stackIn;Stack<Integer> stackOut;public MyQueue() {stackIn = new Stack<>();stackOut = new Stack<>();}public void push(int x) {stackIn.push(x);}public int pop() {dumpstackIn();return stackOut.pop();}public int peek() {dumpstackIn();return stackOut.peek();}public boolean empty() {return stackIn.isEmpty() && stackOut.isEmpty();}// 如果stackOut为空,那么将stackIn中的元素全部放到stackOut中private void dumpstackIn(){if (!stackOut.isEmpty()) return; while (!stackIn.isEmpty()){stackOut.push(stackIn.pop());}}
}
225. 用队列实现栈
225. 用队列实现栈
使用队列实现栈的下列操作:
- push(x) – 元素 x 入栈
- pop() – 移除栈顶元素
- top() – 获取栈顶元素
- empty() – 返回栈是否为空
注意:
你只能使用队列的基本操作-- 也就是 push to back, peek/pop from front, size, 和 is empty 这些操作是合法的。
你所使用的语言也许不支持队列。 你可以使用 list 或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。
你可以假设所有操作都是有效的(例如, 对一个空的栈不会调用 pop 或者 top 操作)。
1.两个队列实现栈
队列是先进先出的规则,把一个队列中的数据导入另一个队列中,数据的顺序并没有变,并没有变成先进后出的顺序。
用两个队列que1和que2实现队列的功能,que2其实完全就是一个备份的作用,把que1最后面的元素以外的元素都备份到que2,然后弹出最后面的元素,再把其他元素从que2导回que1。
使用两个 Queue 实现:
class MyStack {Queue<Integer> queue1; // 和栈中保持一样元素的队列Queue<Integer> queue2; // 辅助队列public MyStack() {queue1 = new LinkedList<>();queue2 = new LinkedList<>();}public void push(int x) {queue2.offer(x); // 先放在辅助队列中while (!queue1.isEmpty()){queue2.offer(queue1.poll());}Queue<Integer> queueTemp;queueTemp = queue1;queue1 = queue2;queue2 = queueTemp; // 最后交换queue1和queue2,将元素都放到queue1中}public int pop() {// 因为queue1中的元素和栈中的保持一致,所以这个和下面两个的操作只看queue1return queue1.poll(); }public int top() {return queue1.peek();}public boolean empty() {return queue1.isEmpty();}
}
使用两个 Deque 实现:
class MyStack {// Deque 接口继承了 Queue 接口// 所以 Queue 中的 add、poll、peek等效于 Deque 中的 addLast、pollFirst、peekFirstDeque<Integer> que1;Deque<Integer> que2;public MyStack() {que1 = new ArrayDeque<>();//双端队列que2 = new ArrayDeque<>();}public void push(int x) {que1.addLast(x);}public int pop() {int size = que1.size();size--;// 将que1导入que2 ,留下最后一个值while (size-- > 0) {que2.addLast(que1.peekFirst());que1.pollFirst();}//删除que1中最后的元素并作为返回结果int res = que1.pollFirst();// 将que2对象的引用赋给que1,此时que1,que2指向同一个队列que1 = que2;// 如果直接操作que2,que1也会受到影响,所以为que2分配一个新的空间que2 = new ArrayDeque<>();return res; }public int top() {return que1.peekLast();}public boolean empty() {return que1.isEmpty();}
}
2.一个队列实现栈
队列模拟栈,其实一个队列就够了
一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时在去弹出元素就是栈的顺序了。
class MyStack {// Deque 接口继承了 Queue 接口Deque<Integer> que1;public MyStack() {que1 = new ArrayDeque<>();//双端队列}public void push(int x) {que1.addLast(x);}public int pop() {int size = que1.size();size--;while (size-- > 0) {//队列头部的元素(除了最后一个元素外) 重新添加到队列尾部que1.addLast(que1.peekFirst());que1.pollFirst();}int res = que1.pollFirst();return res;}public int top() {return que1.peekLast();}public boolean empty() {return que1.isEmpty();}
}
ArrayDeque双端队列可直接使用提供的API实现:(没啥意义了)
class MyStack {// Deque 提供了实现堆栈的push,pop,peekDeque<Integer> que1;public MyStack() {que1 = new ArrayDeque<>();//双端队列}public void push(int x) {que1.push(x);}public int pop() {return que1.pop(); }public int top() {return que1.peek();}public boolean empty() {return que1.isEmpty();}
}
20. 有效的括号
20. 有效的括号
给定一个只包括 ‘(’,‘)’,‘{’,‘}’,‘[’,‘]’ 的字符串,判断字符串是否有效。
有效字符串需满足:
- 左括号必须用相同类型的右括号闭合。
- 左括号必须以正确的顺序闭合。
- 注意空字符串可被认为是有效字符串。
示例 1:
输入: “()”
输出: true
示例 2:
输入: “()[]{}”
输出: true
示例 3:
输入: “(]”
输出: false
思路
括号匹配是使用栈解决的经典问题。
编译原理中,编译器在词法分析的过程中处理括号、花括号等这个符号的逻辑,也是使用了栈这种数据结构。
由于栈结构的特殊性,非常适合做对称匹配类的题目。
首先要弄清楚,字符串里的括号不匹配有几种情况。
-
第一种情况,字符串里左方向的括号多余了 ,所以不匹配。
-
第二种情况,括号没有多余,但是 括号的类型没有匹配上。
-
第三种情况,字符串里右方向的括号多余了,所以不匹配。
代码随想录动画:
字符串遍历完之后,栈是空的,就说明全都匹配了。
第一种情况:已经遍历完了字符串,但是栈不为空,说明有相应的左括号没有右括号来匹配,所以return false
第二种情况:遍历字符串匹配的过程中,发现栈里没有要匹配的字符。所以return false
第三种情况:遍历字符串匹配的过程中,栈已经为空了,没有匹配的字符了,说明右括号没有找到对应的左括号return false
技巧:在匹配左括号的时候,右括号先入栈,就只需要比较当前元素和栈顶相不相等就可以了,比左括号先入栈代码实现要简单的多了
时间复杂度:O(n)O(n)O(n),其中 nn 是字符串 ss 的长度。
空间复杂度:O(n+∣Σ∣)O(n+∣Σ∣)O(n+∣Σ∣),其中Σ 表示字符集,本题中字符串只包含 6 种括号,∣Σ∣=6。
class Solution {public boolean isValid(String s) {Deque<Character> deque = new LinkedList<>();char ch;for (int i=0;i<s.length();i++) {ch = s.charAt(i);//碰到左括号,就把相应的右括号入栈if (ch=='(') {deque.push(')');} else if (ch=='{') {deque.push('}'); } else if (ch=='[') {deque.push(']');} else if (deque.isEmpty()||deque.peek()!=ch) {//栈已经为空或匹配不对return false;} else {//如果是右括号判断是否和栈顶元素匹配//匹配则从栈中删除deque.pop();}}//最后判断栈中是否还有元素return deque.isEmpty();}
}
1047. 删除字符串中的所有相邻重复项
1047. 删除字符串中的所有相邻重复项
给出由小写字母组成的字符串 S,重复项删除操作会选择两个相邻且相同的字母,并删除它们。
在 S 上反复执行重复项删除操作,直到无法继续删除。
在完成所有重复项删除操作后返回最终的字符串。答案保证唯一。
示例:
输入:“abbaca”
输出:“ca”
解释:例如,在 “abbaca” 中,我们可以删除 “bb” 由于两字母相邻且相同,这是此时唯一可以执行删除操作的重复项。之后我们得到字符串 “aaca”,其中又只有 “aa” 可以执行重复项删除操作,所以最后的字符串为 “ca”。
提示:
1 <= S.length <= 20000
S 仅由小写英文字母组成。
思路
本题要删除相邻相同元素,其实也是匹配问题,相同左元素相当于左括号,相同右元素就是相当于右括号,匹配上了就删除。
可以把字符串顺序放到一个栈中,然后如果相同的话 栈就弹出,这样最后栈里剩下的元素都是相邻不相同的元素了。
从栈中弹出剩余元素,因为从栈里弹出的元素是倒序的,所以在对字符串进行反转一下,就得到了最终的结果。
用Deque作为堆栈:
class Solution {public String removeDuplicates(String s) {//ArrayDeque会比LinkedList在除了删除元素这一点外会快一点//参考:https://stackoverflow.com/questions/6163166/why-is-arraydeque-better-than-linkedlistArrayDeque<Character> deque = new ArrayDeque<>();char ch;for (int i=0;i<s.length();i++) {ch = s.charAt(i);if (deque.isEmpty()||deque.peek()!=ch) {deque.push(ch);} else {deque.pop();}}String str = "";while (!deque.isEmpty()) {//直接把删除的元素放在前面拼接//否则还需要反转字符串str = deque.pop() + str;}return str;}
}
拿字符串直接作为栈,省去了栈还要转为字符串的操作:
class Solution {public String removeDuplicates(String s) {// 将 res 当做栈StringBuffer res = new StringBuffer();// top为 res 的长度int top = -1;for (int i = 0; i < s.length(); i++) {char c = s.charAt(i);// 当 top > 0,即栈中有字符时,当前字符如果和栈中字符相等,弹出栈顶字符,同时 top--if (top >= 0 && res.charAt(top) == c) {res.deleteCharAt(top);top--;// 否则,将该字符入栈,同时top++} else {res.append(c);top++;}}return res.toString();}
}
拓展:双指针
class Solution {public String removeDuplicates(String s) {char[] ch = s.toCharArray();int fast = 0;int slow = 0;while (fast< s.length()) {// 直接用fast指针覆盖slow指针的值ch[slow] = ch[fast];// 遇到前后相同值的,就跳过,即slow指针后退一步,下次循环就可以直接被覆盖掉了if(slow > 0 && ch[slow] == ch[slow - 1]){slow--;}else{slow++;}fast++;}return new String(ch,0,slow);}
}
155. 最小栈
155. 最小栈
150. 逆波兰表达式求值
150. 逆波兰表达式求值
根据 逆波兰表示法,求表达式的值。
有效的运算符包括 + , - , * , / 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。
说明:
整数除法只保留整数部分。 给定逆波兰表达式总是有效的。换句话说,表达式总会得出有效数值且不存在除数为 0 的情况。
示例 1:
输入: [“2”, “1”, “+”, “3”, " * "]
输出: 9
解释: 该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
示例 2:
输入: [“4”, “13”, “5”, “/”, “+”]
输出: 6
解释: 该算式转化为常见的中缀算术表达式为:(4 + (13 / 5)) = 6
示例 3:
输入: [“10”, “6”, “9”, “3”, “+”, “-11”, " * ", “/”, " * ", “17”, “+”, “5”, “+”]
输出: 22
解释:该算式转化为常见的中缀算术表达式为:
((10 * (6 / ((9 + 3) * -11))) + 17) + 5
= ((10 * (6 / (12 * -11))) + 17) + 5
= ((10 * (6 / -132)) + 17) + 5
= ((10 * 0) + 17) + 5
= (0 + 17) + 5
= 17 + 5
= 22
逆波兰表达式:是一种后缀表达式,所谓后缀就是指算符写在后面。
平常使用的算式则是一种中缀表达式,如 ( 1 + 2 ) * ( 3 + 4 ) 。
该算式的逆波兰表达式写法为 ( ( 1 2 + ) ( 3 4 + ) * ) 。
逆波兰表达式主要有以下两个优点:
-
去掉括号后表达式无歧义,上式即便写成 1 2 + 3 4 + * 也可以依据次序计算出正确结果。
-
适合用栈操作运算:遇到数字则入栈;遇到算符则取出栈顶两个数字进行计算,并将结果压入栈中。
思路
本题中每一个子表达式要得出一个结果,然后拿这个结果再进行运算,那么这就是一个相邻元素做运算的过程,出现运算符就要对之前的元素计算
class Solution {public int evalRPN(String[] tokens) {Deque<Integer> stack = new LinkedList<>();for (int i=0;i<tokens.length;i++) {if ("+".equals(tokens[i])) {stack.push(stack.pop()+stack.pop());} else if ("-".equals(tokens[i])) {stack.push(-stack.pop()+stack.pop());} else if ("*".equals(tokens[i])) {stack.push(stack.pop()*stack.pop());} else if ("/".equals(tokens[i])) {int temp1 = stack.pop();int temp2 = stack.pop();stack.push(temp2/temp1);} else {stack.push(Integer.valueOf(tokens[i]));}}return stack.pop();}
}
239. 滑动窗口最大值
239. 滑动窗口最大值
给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回滑动窗口中的最大值。
进阶:
你能在线性时间复杂度内解决此题吗?
提示:
1 <= nums.length <= 10^5
-10^4 <= nums[i] <= 10^4
1 <= k <= nums.length
单调队列
我们需要一个队列,这个队列呢,放进去窗口里的元素,然后随着窗口的移动,队列也一进一出,每次移动之后,队列告诉我们里面的最大值是什么。队列里的元素一定是要排序的,而且要最大值放在出队口。
但如果把窗口里的元素都放进队列里,窗口移动的时候,队列需要弹出元素。
实际上没有必要维护窗口里的所有元素,只需要维护有可能成为窗口里最大值的元素就可以了,同时保证队里里的元素数值是由大到小的。那么这个维护元素单调递减的队列就叫做单调队列,即单调递减或单调递增的队列。
不要以为实现的单调队列就是 对窗口里面的数进行排序,如果排序的话,那和优先级队列又有什么区别了呢。
代码随想录动画:
对于窗口里的元素{2, 3, 5, 1 ,4},单调队列里只维护{5, 4} 就够了,保持单调队列里单调递减,此时队列出口元素就是窗口里最大元素。
设计单调队列的时候,pop,和push操作要保持如下规则:
- pop(value):如果窗口移除的元素value等于单调队列的出口元素,那么队列弹出元素,否则不用任何操作
- push(value):如果push的元素value大于入口元素的数值,那么就将队列入口的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止
保持如上规则,每次窗口移动的时候,只要问que.front()就可以返回当前窗口的最大值。
时间复杂度: O(n)O(n)O(n)
空间复杂度: O(k)O(k)O(k)
自定义单调队列:
class Solution {public int[] maxSlidingWindow(int[] nums, int k) {if (nums.length == 1) {return nums;}//结果数组的长度int len = nums.length - k + 1;int[] res = new int[len];int num = 0;MyQueue myQueue = new MyQueue();for (int i=0;i<k;i++) {myQueue.add(nums[i]);}res[num++] = myQueue.peek();for (int i = k; i < nums.length; i++) {//滑动窗口移除最前面的元素,移除时判断该元素是否放入队列myQueue.poll(nums[i - k]);//滑动窗口加入最后面的元素myQueue.add(nums[i]);//记录对应的最大值res[num++] = myQueue.peek();}return res;}
}
class MyQueue {Deque<Integer> deque = new LinkedList<>();//弹出元素时,比较当前要弹出的数值是否等于队列出口的数值,如果相等则弹出//同时判断队列当前是否为空void poll(int val) {if (!deque.isEmpty() && val == deque.peek()) {deque.poll();}}//添加元素时,如果要添加的元素大于入口处的元素,就将入口元素弹出//保证队列元素单调递减//比如此时队列元素3,1,2将要入队,比1大,所以1弹出,此时队列:3,2void add(int val) {while (!deque.isEmpty() && val > deque.getLast()) {deque.removeLast();}deque.add(val);}//队列队顶元素始终为最大值int peek() {return deque.peek();}
}
利用双端队列手动实现单调队列:
/*** 用一个单调队列来存储对应的下标,每当窗口滑动的时候,直接取队列的头部指针对应的值放入结果集即可* 单调队列类似 (tail -->) 3 --> 2 --> 1 --> 0 (--> head) (右边为头结点,元素存的是下标)*/
class Solution {public int[] maxSlidingWindow(int[] nums, int k) {ArrayDeque<Integer> deque = new ArrayDeque<>();int res[] = new int[nums.length-k+1];int idx = 0;for (int i=0;i<nums.length;i++) {// 根据题意,i为nums下标,是要在[i - k + 1, i] 中选到最大值,只需要保证两点// 1.队列头结点需要在[i - k + 1, i]范围内,不符合则要弹出while(!deque.isEmpty() && deque.peek() < i - k + 1){deque.poll();}// 2.单调就要保证每次放进去的数字要比末尾的都大,否则也弹出while(!deque.isEmpty() && nums[deque.peekLast()] < nums[i]) {deque.pollLast();}deque.offer(i);// 因为单调,当i增长到符合第一个k范围的时候,每滑动一步都将队列头节点放入结果就行了if(i >= k - 1){res[idx++] = nums[deque.peek()];}}return res;}
}
PS:题解中单调队列里的pop和push接口,仅适用于本题。单调队列不是一成不变的,而是不同场景不同写法,总之要保证队列里单调递减或递增的原则,所以叫做单调队列。
347. 前 K 个高频元素
347. 前 K 个高频元素
给定一个非空的整数数组,返回其中出现频率前 k 高的元素。
示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]
示例 2:
输入: nums = [1], k = 1
输出: [1]
提示:
- 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
- 你的算法的时间复杂度必须优于 O(nlogn)O(n \log n)O(nlogn) , n 是数组的大小。
- 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
- 你可以按任意顺序返回答案。
思路
这道题目主要涉及到如下三块内容:
- 要统计元素出现频率
- 对频率排序
- 找出前K个高频元素
首先统计元素出现的频率,这一类的问题可以使用map来进行统计。
然后是对频率进行排序,这里我们可以使用一种容器适配器就是优先级队列。
为什么不用快排呢, 使用快排要将map转换为数组的结构,然后对整个数组进行排序,效率较低。而这种场景下,我们其实只需要维护k个有序的序列就可以了,所以使用优先级队列是最优的。
如果定义一个大小为k的大顶堆,在每次移动更新大顶堆的时候,每次弹出都把最大的元素弹出去了,那么怎么保留下来前K个高频元素呢。而且使用大顶堆就要把所有元素都进行排序,那能不能只排序k个元素呢?
所以我们要用小顶堆,因为要统计最大前k个元素,只有小顶堆每次将最小的元素弹出,最后小顶堆里积累的才是前k个最大元素。
寻找前k个最大元素流程如代码随想录图所示:(图中的频率只有三个,所以正好构成一个大小为3的小顶堆,如果频率更多一些,则用这个小顶堆进行扫描)
class Solution {public int[] topKFrequent(int[] nums, int k) {int[] result = new int[k];HashMap<Integer, Integer> map = new HashMap<>();for (int num : nums) {map.put(num, map.getOrDefault(num, 0) + 1);}Set<Map.Entry<Integer, Integer>> entries = map.entrySet();// 根据map的value值正序排,相当于一个小顶堆// 使用lambda表达式PriorityQueue<Map.Entry<Integer, Integer>> queue = new PriorityQueue<>((o1, o2) -> o1.getValue() - o2.getValue()); for (Map.Entry<Integer, Integer> entry : entries) {queue.offer(entry);if (queue.size() > k) {queue.poll();}}for (int i = k - 1; i >= 0; i--) {result[i] = queue.poll().getKey();}return result;}
}
相关文章:

数据结构——栈与队列相关题目
数据结构——栈与队列相关题目232. 用栈实现队列思路225. 用队列实现栈1.两个队列实现栈2.一个队列实现栈20. 有效的括号思路1047. 删除字符串中的所有相邻重复项思路155. 最小栈150. 逆波兰表达式求值思路239. 滑动窗口最大值单调队列347. 前 K 个高频元素思路232. 用栈实现队…...

Redhat6.7离线安装rabbitmq
一、下载资源文件(.rpm文件) 链接: https://pan.baidu.com/s/1j2Ze_Jjm0oMrP-r95PPCtA?pwdv3is 提取码: v3is 复制这段内容后打开百度网盘手机App,操作更方便哦 创建rabbit文件夹Mkdir rabbit 三、通过ftp上传文件 四、安装erlang环境 …...

EasyCVR平台基于GB28181协议的语音对讲配置操作教程
EasyCVR基于云边端协同,具有强大的数据接入、处理及分发能力,平台可支持海量视频的轻量化接入与汇聚管理,可提供视频监控直播、视频轮播、视频录像、云存储、回放与检索、智能告警、服务器集群、语音对讲、云台控制、电子地图、平台级联等功能…...

谷歌发布Self-Debug方法,让大模型学会自己修bug,一次性生成正确代码
文 | 智商掉了一地你有没有想过,让一台计算机诊断和修复自己生成的错误代码?一篇最新的研究论文介绍了一种名为 Self-Debugging 的技术,通过在生成的代码中添加自解释的信息,让计算机像一个可以自己修复代码的程序员一样调试自己的…...
行为型模式-模板方法
行为型模式-模板方法 模板方法(Template Method)解决算法框架问题描述适用环境优点:缺点:违反原则:代码实现模板方法(Template Method) 解决算法框架问题 描述 定义了一个算法的骨架,并将某些步骤延迟到子类中进行实现,从而使得算法的具体实现能够在子类中自由变化…...
正则表达式识别日期
正则表达式识别日期 正则表达式识别各种格式的日期 import redef extract_dates(text):# 正则表达式,用于识别常见的日期格式date_pattern r"""(?P<date>(?P<year_only>\d{4}(?![\d年]))| # …...
如何设计一个秒杀架构设计?
文章目录 1. 秒杀业务的特点2. 总体思路2.1 削峰限流安全保护页面优化,动静分离异步处理热点分离2.2 Nginx的设计细节2.3 页面优化细节降低交互的压力安全控制2.4 Redis集群的应用分布式悲观锁(参考redis悲观锁的代码)异步处理订单2.5 消息队列限流2.6 数据库设计2.7 答题验…...

Elasticsearch:配置选项
Elasticsearch 带有大量的设置和配置,甚至可能让专家工程师感到困惑。 尽管它使用约定优于配置范例并且大部分时间使用默认值,但在将应用程序投入生产之前自定义配置是必不可少的。 在这里,我们将介绍属于不同类别的一些属性,并讨…...

消息中间件Kafka分布式数据处理平台+ZooKeeper
目录 一.消息队列基本介绍 1.为什么需要消息队列(MQ) 2.使用消息队列的好处 2.1 解耦 2.2 可恢复性 2.3 缓冲 2.4 灵活性 & 峰值处理能力 2.5 异步通信 3.消息队列的两种模式 3.1 点对点模式 3.2 发布/订阅模式 二.Kafka基本介绍 1.Kaf…...

Linux 用户文件磁盘网络进程指令
用户相关指令 useradd 用户名添加用户useradd -g 组名 用户名 向组添加用户passwd 用户名 设置密码id 用户名 查看用户名的具体信息cat /etc/passwd 查看创建了哪些用户su 用户名 切换用户名(不能获得环境变量)su - 用户名获得环境变量以及执行权…...
如何使用Socks5代理IP提高网络安全性
随着网络的快速发展,网络安全问题变得越来越重要。为了保障网络安全,人们普遍使用代理IP,其中Socks5代理IP是一种常用的选择。本文将介绍什么是Socks5代理IP,以及如何使用它提高网络安全性。 一、什么是Socks5代理IP Socks5代…...

《Java8实战》第3章 Lambda 表达式
利用行为参数化来传递代码有助于应对不断变化的需求。它允许你定义一段代码块来表示一个行为,然后传递它。采用匿名类来表示多种行为并不令人满意:代码十分啰唆,这会影响程序员在实践中使用行为参数化的积极性。 3.1 Lambda 管中窥豹 可以…...

开放式耳机的颠覆之作!南卡OE Pro新皇降临!佩戴和音质双重突破
千呼万唤的南卡OE Pro终于要在最近正式官宣上线,此消息一经放出,蓝牙耳机市场就已经沸腾。NANK南卡品牌作为国内的音频大牌,发展和潜力一直备受业内关注,这次要上线的南卡OE Pro更是南卡十余年来积累的声学技术结晶之一。 据透露…...

生成器设计模式(Builder Design Pattern)[论点:概念、图示、示例、框架中的应用、场景]
文章目录概念相关图示代码示例框架中的应用场景多个生成器(Concrete Builder):单个生成器概念 生成器设计模式(Builder Design Pattern)是一种创建型设计模式,用于处理具有多个属性和复杂构造过程的对象。生…...

JUC并发工具
JUC并发工具 一、CountDownLatch应用&源码分析 1.1 CountDownLatch介绍 CountDownLatch就是JUC包下的一个工具,整个工具最核心的功能就是计数器。 如果有三个业务需要并行处理,并且需要知道三个业务全部都处理完毕了。 需要一个并发安全的计数器来操作。 CountDown…...
java面试题-基础问题-如何理解Java中的多态?
如何理解Java中的多态?如何理解Java中的多态?典型回答扩展知识方法的重载与重写重载和重写的区别如何理解Java中的多态? 典型回答 多态的概念比较简单,就是同一操作作用于不同的对象,可以有不同的解释,产…...

03.vue3的计算属性
文章目录1.计算属性1.get()和set()2.computed的简写3.computed和methods对比2.相关demo1.全选和反选2.todos列表1.计算属性 模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的。在模板中放入太多的逻辑会让模板过重且难以维护。所以,对于任何…...
Ceph性能调优
1. 最佳实践 1.1 基本 监控节点对于集群的正确运行非常重要,应当为其分配独立的硬件资源。如果跨数据中心部署,监控节点应该分散在不同数据中心或者可用性区域日志可能会让集群的吞吐量减半。理想情况下,应该在不同磁盘上运行操作系统、OSD…...
机器学习-问答题准备(英文)-更新中
第一章 入门 How would you define Machine Learning? Machine Learning is about building systems that can learn from data. Learning means getting better at some task, given some performance measure. Can you name four types of problems where it shines? To r…...

展示演示软件设计制作(C语言)
展示演示软件设计制作 所谓展示演示软件就像是PPT那样的东西。PPT是幻灯片式的展示,而我设计的软件是多媒体的,多样展示方法的,多种功能的。可以扩展为产品展示,项目介绍,景点导游,多媒体授课,…...

SpringCloud——Docker
1.命令解读 docker run -d 解释:创建并运行一个容器,-d则是让容器以后台进程运行 --name mysql 解释: 给容器起个名字叫mysql -p 3306:3306 解释:-p 宿主机端口:容器内端口,设置端口映射 注意: 1、…...

【C语言】讲解 程序分配的区域(新手)
目录 代码区 数据区 堆区 栈区 常量区 重点比较一下堆区与 栈区 总结: 前言: C语言程序的内存分配区域是理解其运行机制的重要部分。根据提供的多条证据,我们可以总结出C语言程序在运行时主要涉及以下五个关键内存区域: 代…...
24核32G,千兆共享:裸金属服务器的技术原理与优势
在云计算和数据中心领域,裸金属服务器正逐渐成为企业追求高性能计算的热门选择。本文将深入探讨裸金属服务器的技术原理,以及以“24核32G,千兆共享”配置为代表的裸金属服务器所具备的独特优势。 一、裸金属服务器的技术原理 (一…...

使用Mathematica绘制随机多项式的根
使用ListPlot和NSolve直接绘制: (*返回系数为r和s之间整数的n次随机多项式*) eq[n_, r_, s_] : RandomInteger[{r, s}, {n}] . Array[Power[x, # - 1] &, n] (*返回给定随机多项式的根所对应的笛卡尔坐标*) sol[n_, r_, s_] : {Re[#], Im[#]} & / (x /.…...

嵌入式编译工具链熟悉与游戏移植
在自己的虚拟机Ubuntu系统下,逐步编译 mininim源码(波斯王子重制开源版) 指令流程 sudo apt-get remove liballegro5-dev liballegro-image5-dev \liballegro-audio5-dev liballegro-acodec5-dev liballegro-dialog5-dev sudo apt-get install automak…...

系统思考:化繁为简的艺术
系统思考,其实是一门化繁为简的艺术。当我们能够把复杂的问题拆解成清晰的核心以及更加简单,从而提升团队的思考品质和行动品质,发挥最大的合力。 每个公司都想在某方面成为最优秀的,但是实际上具有穿透性的洞察力和摆脱虚荣心的清…...
Java 数据处理 - 数值转不同进制的字符串(数值转十进制字符串、数值转二进制字符串、数值转八进制字符串、数值转十六进制字符串)
一、数值转十进制字符串 调用 String.valueOf() int num 123;String decStr String.valueOf(num);System.out.println(decStr);# 输出结果123调用 Integer.toString(),指定进制 int num 123;String decStr Integer.toString(num);System.out.println(decStr)…...

XJTU-SY轴承振动数据集的json自封装
1.最终形式的形式 不用再去翻文档找对应的故障类型,采样率等信息了,所有的信息自包含在.json文件里,15个测试例,一个测试例对应一整个.json文件。 {"dataset": {"name": "XJTU-SY_Bearing_Datasets&quo…...

数据结构与算法学习笔记(Acwing 提高课)----动态规划·区间DP
数据结构与算法学习笔记----动态规划区间DP author: 明月清了个风 first publish time: 2025.5.26 ps⭐️区间DP的特征在于子结构一般是一个子区间上的问题,涉及到的问题也非常多,如环形区间,记录方案数,高精度,二维…...

零基础开始的网工之路第十四天------Linux程序管理
目录 一、Linux程序与进程 1、程序,进程,线程的概念 2、程序和进程的区别 3、进程和线程的区别 二、Linux进程基础(生命周期) 1、进程生命周期 2、父子进程的关系 三、程序管理 1、常见的软件包类型 四、Linux操作系统启动流程详解 1、概述 2、启动流程核心阶段 1…...