diff --git a/README.md b/README.md index 8aa93194..3b0e8d65 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,7 @@ 我在题目讲解中统一使用C++,但你会发现下面几乎每篇题解都配有其他语言版本,Java、Python、Go、JavaScript等等,正是这些[热心小伙们](https://github.com/youngyangyang04/leetcode-master/graphs/contributors)的贡献的代码,当然我也会严格把控代码质量。 -**所以也欢迎大家参与进来,完善题解的各个语言版本,拥抱开源,让更多小伙伴们收益**。 +**所以也欢迎大家参与进来,完善题解的各个语言版本,拥抱开源,让更多小伙伴们受益**。 准备好了么,刷题攻略开始咯,go go go! diff --git a/problems/0001.两数之和.md b/problems/0001.两数之和.md index acf2a995..7bada9af 100644 --- a/problems/0001.两数之和.md +++ b/problems/0001.两数之和.md @@ -152,25 +152,11 @@ class Solution: def twoSum(self, nums: List[int], target: int) -> List[int]: records = dict() - # 用枚举更方便,就不需要通过索引再去取当前位置的值 - for idx, val in enumerate(nums): - if target - val not in records: - records[val] = idx - else: - return [records[target - val], idx] # 如果存在就返回字典记录索引和当前索引 -``` - -Python (v2): - -```python -class Solution: - def twoSum(self, nums: List[int], target: int) -> List[int]: - rec = {} - for i in range(len(nums)): - rest = target - nums[i] - # Use get to get the index of the data, making use of one of the dictionary properties. - if rec.get(rest, None) is not None: return [rec[rest], i] - rec[nums[i]] = i + for index, value in enumerate(nums): + if target - value in records: + return [records[target- value], index] + records[value] = index + return [] ``` Go: diff --git a/problems/0015.三数之和.md b/problems/0015.三数之和.md index fb289d54..5ee57127 100644 --- a/problems/0015.三数之和.md +++ b/problems/0015.三数之和.md @@ -655,7 +655,7 @@ impl Solution { ```Rust // 双指针法 -use std::collections::HashSet; +use std::cmp::Ordering; impl Solution { pub fn three_sum(nums: Vec) -> Vec> { let mut result: Vec> = Vec::new(); @@ -667,22 +667,21 @@ impl Solution { if i > 0 && nums[i] == nums[i - 1] { continue; } let (mut left, mut right) = (i + 1, len - 1); while left < right { - if nums[i] + nums[left] + nums[right] > 0 { - right -= 1; - // 去重 - while left < right && nums[right] == nums[right + 1] { right -= 1; } - } else if nums[i] + nums[left] + nums[right] < 0 { - left += 1; - // 去重 - while left < right && nums[left] == nums[left - 1] { left += 1; } - } else { - result.push(vec![nums[i], nums[left], nums[right]]); - // 去重 - right -= 1; - left += 1; - while left < right && nums[right] == nums[right + 1] { right -= 1; } - while left < right && nums[left] == nums[left - 1] { left += 1; } - } + match (nums[i] + nums[left] + nums[right]).cmp(&0){ + Ordering::Equal =>{ + result.push(vec![nums[i], nums[left], nums[right]]); + left +=1; + right -=1; + while left < right && nums[left] == nums[left - 1]{ + left += 1; + } + while left < right && nums[right] == nums[right+1]{ + right -= 1; + } + } + Ordering::Greater => right -= 1, + Ordering::Less => left += 1, + } } } result diff --git a/problems/0018.四数之和.md b/problems/0018.四数之和.md index 463eaf8f..ca33eb57 100644 --- a/problems/0018.四数之和.md +++ b/problems/0018.四数之和.md @@ -527,6 +527,7 @@ public class Solution Rust: ```Rust +use std::cmp::Ordering; impl Solution { pub fn four_sum(nums: Vec, target: i32) -> Vec> { let mut result: Vec> = Vec::new(); @@ -545,22 +546,25 @@ impl Solution { if i > k + 1 && nums[i] == nums[i - 1] { continue; } let (mut left, mut right) = (i + 1, len - 1); while left < right { - if nums[k] + nums[i] > target - (nums[left] + nums[right]) { - right -= 1; - // 去重 - while left < right && nums[right] == nums[right + 1] { right -= 1; } - } else if nums[k] + nums[i] < target - (nums[left] + nums[right]) { - left += 1; - // 去重 - while left < right && nums[left] == nums[left - 1] { left += 1; } - } else { - result.push(vec![nums[k], nums[i], nums[left], nums[right]]); - // 去重 - while left < right && nums[right] == nums[right - 1] { right -= 1; } - while left < right && nums[left] == nums[left + 1] { left += 1; } - left += 1; - right -= 1; - } + match (nums[k] + nums[i] + nums[left] + nums[right]).cmp(&target){ + Ordering::Equal => { + result.push(vec![nums[k], nums[i], nums[left], nums[right]]); + left += 1; + right -= 1; + while left < right && nums[left] == nums[left - 1]{ + left += 1; + } + while left < right && nums[right] == nums[right + 1]{ + right -= 1; + } + } + Ordering::Less => { + left +=1; + }, + Ordering::Greater => { + right -= 1; + } + } } } } diff --git a/problems/0019.删除链表的倒数第N个节点.md b/problems/0019.删除链表的倒数第N个节点.md index 314c396e..b0641b5f 100644 --- a/problems/0019.删除链表的倒数第N个节点.md +++ b/problems/0019.删除链表的倒数第N个节点.md @@ -364,6 +364,40 @@ impl Solution { dummy_head.next } } +``` +C语言 +```c +/**c语言单链表的定义 + * Definition for singly-linked list. + * struct ListNode { + * int val; + * struct ListNode *next; + * }; + */ +struct ListNode* removeNthFromEnd(struct ListNode* head, int n) { + //定义虚拟头节点dummy 并初始化使其指向head + struct ListNode* dummy = malloc(sizeof(struct ListNode)); + dummy->val = 0; + dummy->next = head; + //定义 fast slow 双指针 + struct ListNode* fast = head; + struct ListNode* slow = dummy; + + for (int i = 0; i < n; ++i) { + fast = fast->next; + } + while (fast) { + fast = fast->next; + slow = slow->next; + } + slow->next = slow->next->next;//删除倒数第n个节点 + head = dummy->next; + free(dummy);//删除虚拟节点dummy + return head; +} + + + ```

diff --git a/problems/0028.实现strStr.md b/problems/0028.实现strStr.md index 7078738e..19d16e9f 100644 --- a/problems/0028.实现strStr.md +++ b/problems/0028.实现strStr.md @@ -1299,6 +1299,53 @@ impl Solution { } ``` +> 前缀表统一减一 + +```rust +impl Solution { + pub fn get_next(next_len: usize, s: &Vec) -> Vec { + let mut next = vec![-1; next_len]; + let mut j = -1; + for i in 1..s.len() { + while j >= 0 && s[(j + 1) as usize] != s[i] { + j = next[j as usize]; + } + if s[i] == s[(j + 1) as usize] { + j += 1; + } + next[i] = j; + } + next + } + pub fn str_str(haystack: String, needle: String) -> i32 { + if needle.is_empty() { + return 0; + } + if haystack.len() < needle.len() { + return -1; + } + let (haystack_chars, needle_chars) = ( + haystack.chars().collect::>(), + needle.chars().collect::>(), + ); + let mut j = -1; + let next = Self::get_next(needle.len(), &needle_chars); + for (i, v) in haystack_chars.into_iter().enumerate() { + while j >= 0 && v != needle_chars[(j + 1) as usize] { + j = next[j as usize]; + } + if v == needle_chars[(j + 1) as usize] { + j += 1; + } + if j == needle_chars.len() as i32 - 1 { + return (i - needle_chars.len() + 1) as i32; + } + } + -1 + } +} +``` +

diff --git a/problems/0052.N皇后II.md b/problems/0052.N皇后II.md index f1edd281..e4faac0c 100644 --- a/problems/0052.N皇后II.md +++ b/problems/0052.N皇后II.md @@ -256,7 +256,54 @@ int totalNQueens(int n){ return answer; } ``` - +Java +```java +class Solution { + int count = 0; + public int totalNQueens(int n) { + char[][] board = new char[n][n]; + for (char[] chars : board) { + Arrays.fill(chars, '.'); + } + backTrack(n, 0, board); + return count; + } + private void backTrack(int n, int row, char[][] board) { + if (row == n) { + count++; + return; + } + for (int col = 0; col < n; col++) { + if (isValid(row, col, n, board)) { + board[row][col] = 'Q'; + backTrack(n, row + 1, board); + board[row][col] = '.'; + } + } + } + private boolean isValid(int row, int col, int n, char[][] board) { + // 检查列 + for (int i = 0; i < row; ++i) { + if (board[i][col] == 'Q') { + return false; + } + } + // 检查45度对角线 + for (int i = row - 1, j = col - 1; i >= 0 && j >= 0; i--, j--) { + if (board[i][j] == 'Q') { + return false; + } + } + // 检查135度对角线 + for (int i = row - 1, j = col + 1; i >= 0 && j <= n - 1; i--, j++) { + if (board[i][j] == 'Q') { + return false; + } + } + return true; + } +} +```

diff --git a/problems/0084.柱状图中最大的矩形.md b/problems/0084.柱状图中最大的矩形.md index 5fad9c5a..220b096e 100644 --- a/problems/0084.柱状图中最大的矩形.md +++ b/problems/0084.柱状图中最大的矩形.md @@ -409,7 +409,44 @@ class Solution: ``` -***** + +Go: + +> 单调栈 + +```go +func largestRectangleArea(heights []int) int { + // 声明max并初始化为0 + max := 0 + // 使用切片实现栈 + stack := make([]int, 0) + // 数组头部加入0 + heights = append([]int{0}, heights...) + // 数组尾部加入0 + heights = append(heights, 0) + // 初始化栈,序号从0开始 + stack = append(stack, 0) + for i := 1; i < len(heights); i++ { + // 结束循环条件为:当即将入栈元素>top元素,也就是形成非单调递增的趋势 + for heights[stack[len(stack)-1]] > heights[i] { + // mid 是top + mid := stack[len(stack)-1] + // 出栈 + stack = stack[0 : len(stack)-1] + // left是top的下一位元素,i是将要入栈的元素 + left := stack[len(stack)-1] + // 高度x宽度 + tmp := heights[mid] * (i - left - 1) + if tmp > max { + max = tmp + } + } + stack = append(stack, i) + } + return max +} + +``` JavaScript: ```javascript diff --git a/problems/0090.子集II.md b/problems/0090.子集II.md index ea1eb4cd..9f935b60 100644 --- a/problems/0090.子集II.md +++ b/problems/0090.子集II.md @@ -261,7 +261,9 @@ class Solution: self.path.pop() ``` -### Python3 +### Python3 + +不使用used数组 ```python3 class Solution: def subsetsWithDup(self, nums: List[int]) -> List[List[int]]: @@ -288,6 +290,28 @@ class Solution: return res ``` +使用used数组 +```python3 +class Solution: + def subsetsWithDup(self, nums: List[int]) -> List[List[int]]: + result = [] + path = [] + nums.sort() + used = [0] * len(nums) + def backtrack(nums, startIdx): + result.append(path[:]) + for i in range(startIdx, len(nums)): + if i > startIdx and nums[i] == nums[i-1] and used[i-1] == 0: + continue + used[i] = 1 + path.append(nums[i]) + backtrack(nums, i+1) + path.pop() + used[i] = 0 + backtrack(nums, 0) + return result +``` + ### Go ```Go @@ -526,7 +550,7 @@ func subsetsWithDup(_ nums: [Int]) -> [[Int]] { ### Scala -不使用userd数组: +不使用used数组: ```scala object Solution { diff --git a/problems/0121.买卖股票的最佳时机.md b/problems/0121.买卖股票的最佳时机.md index 790bbd88..63ac5d04 100644 --- a/problems/0121.买卖股票的最佳时机.md +++ b/problems/0121.买卖股票的最佳时机.md @@ -464,6 +464,47 @@ function maxProfit(prices: number[]): number { }; ``` +C#: + +> 贪心法 + +```csharp +public class Solution +{ + public int MaxProfit(int[] prices) + { + int min = Int32.MaxValue; + int res = 0; + for (int i = 0; i < prices.Length; i++) + { + min = Math.Min(prices[i], min); + res = Math.Max(prices[i] - min, res); + } + return res; + } +} +``` + +> 动态规划 + +```csharp +public class Solution +{ + public int MaxProfit(int[] prices) + { + int[] dp = new int[2]; + int size = prices.Length; + (dp[0], dp[1]) = (-prices[0], 0); + for (int i = 0; i < size; i++) + { + dp[0] = Math.Max(dp[0], -prices[i]); + dp[1] = Math.Max(dp[1], dp[0]+prices[i]); + } + return dp[1]; + } +} +``` + @@ -471,3 +512,4 @@ function maxProfit(prices: number[]): number { + diff --git a/problems/0122.买卖股票的最佳时机II(动态规划).md b/problems/0122.买卖股票的最佳时机II(动态规划).md index f5f3f720..f2aec68b 100644 --- a/problems/0122.买卖股票的最佳时机II(动态规划).md +++ b/problems/0122.买卖股票的最佳时机II(动态规划).md @@ -169,8 +169,6 @@ class Solution { } ``` - - Python: > 版本一: @@ -253,8 +251,6 @@ func max(a,b int)int{ } ``` - - Javascript: ```javascript // 方法一:动态规划(dp 数组) @@ -331,9 +327,47 @@ function maxProfit(prices: number[]): number { }; ``` +C#: + +> 贪心法 + +```csharp +public class Solution +{ + public int MaxProfit(int[] prices) + { + int res = 0; + for (int i = 1; i < prices.Length; i++) + res += Math.Max(0, prices[i] - prices[i-1]); + return res; + } +} +``` + +> 动态规划 + +```csharp +public class Solution +{ + public int MaxProfit(int[] prices) + { + int[] dp = new int[2]; + dp[0] = -prices[0]; + + for (int i = 1; i < prices.Length; i++) + { + dp[0] = dp[0]>dp[1] - prices[i]?dp[0]:dp[1] - prices[i]; + dp[1] = dp[1] > dp[0] + prices[i] ? dp[1] : dp[0] + prices[i]; + } + return dp[1]; + } +} +``` +

+ diff --git a/problems/0127.单词接龙.md b/problems/0127.单词接龙.md index 4fa53046..2e30123d 100644 --- a/problems/0127.单词接龙.md +++ b/problems/0127.单词接龙.md @@ -31,7 +31,7 @@ # 思路 -以示例1为例,从这个图中可以看出 hit 到 cog的路线,不止一条,有三条,两条是最短的长度为5,一条长度为6。 +以示例1为例,从这个图中可以看出 hit 到 cog的路线,不止一条,有三条,一条是最短的长度为5,两条长度为6。 ![](https://code-thinking-1253855093.file.myqcloud.com/pics/20210827175432.png) diff --git a/problems/0216.组合总和III.md b/problems/0216.组合总和III.md index 3e3b8869..9fc949cc 100644 --- a/problems/0216.组合总和III.md +++ b/problems/0216.组合总和III.md @@ -416,24 +416,31 @@ func backTree(n,k,startIndex int,track *[]int,result *[][]int){ * @return {number[][]} */ var combinationSum3 = function(k, n) { - const backtrack = (start) => { - const l = path.length; - if (l === k) { - const sum = path.reduce((a, b) => a + b); - if (sum === n) { - res.push([...path]); - } - return; + let res = []; + let path = []; + let sum = 0; + const dfs = (path,index) => { + // 剪枝操作 + if (sum > n){ + return } - for (let i = start; i <= 9 - (k - l) + 1; i++) { + if (path.length == k) { + if(sum == n){ + res.push([...path]); + return + } + } + for (let i = index; i <= 9 - (k-path.length) + 1;i++) { path.push(i); - backtrack(i + 1); - path.pop(); + sum = sum + i; + index += 1; + dfs(path,index); + sum -= i + path.pop() } } - let res = [], path = []; - backtrack(1); - return res; + dfs(path,1); + return res }; ``` diff --git a/problems/0235.二叉搜索树的最近公共祖先.md b/problems/0235.二叉搜索树的最近公共祖先.md index ed65553f..c90b3d8c 100644 --- a/problems/0235.二叉搜索树的最近公共祖先.md +++ b/problems/0235.二叉搜索树的最近公共祖先.md @@ -328,13 +328,11 @@ var lowestCommonAncestor = function(root, p, q) { } if(root.val>p.val&&root.val>q.val) { // 向左子树查询 - let left = lowestCommonAncestor(root.left,p,q); - return left !== null&&left; + return root.left = lowestCommonAncestor(root.left,p,q); } if(root.val intersection(vector& nums1, vector& nums2) { @@ -310,6 +310,22 @@ impl Solution { } ``` +解法2: + +```rust +use std::collections::HashSet; +impl Solution { + pub fn intersection(nums1: Vec, nums2: Vec) -> Vec { + nums1 + .into_iter() + .collect::>() + .intersection(&nums2.into_iter().collect::>()) + .copied() + .collect() + } +} +``` + C: ```C int* intersection1(int* nums1, int nums1Size, int* nums2, int nums2Size, int* returnSize){ diff --git a/problems/0450.删除二叉搜索树中的节点.md b/problems/0450.删除二叉搜索树中的节点.md index 4ae092a2..d178596e 100644 --- a/problems/0450.删除二叉搜索树中的节点.md +++ b/problems/0450.删除二叉搜索树中的节点.md @@ -344,6 +344,48 @@ class Solution: return root ``` +**迭代法** +```python +class Solution: + def deleteNode(self, root: Optional[TreeNode], key: int) -> Optional[TreeNode]: + # 找到节点后分两步,1. 把节点的左子树和右子树连起来,2. 把右子树跟父节点连起来 + # root is None + if not root: return root + p = root + last = None + while p: + if p.val==key: + # 1. connect left to right + # right is not None -> left is None | left is not None + if p.right: + if p.left: + node = p.right + while node.left: + node = node.left + node.left = p.left + right = p.right + else: + # right is None -> right=left + right = p.left + # 2. connect right to last + if last==None: + root = right + elif last.val>key: + last.left = right + else: + last.right = right + # 3. return + break + else: + # Update last and continue + last = p + if p.val>key: + p = p.left + else: + p = p.right + return root +``` + ## Go ```Go // 递归版本 diff --git a/problems/0459.重复的子字符串.md b/problems/0459.重复的子字符串.md index 18de79d5..b7d86880 100644 --- a/problems/0459.重复的子字符串.md +++ b/problems/0459.重复的子字符串.md @@ -615,6 +615,37 @@ impl Solution { } ``` +>前缀表统一减一 + +```rust +impl Solution { + pub fn get_next(next_len: usize, s: &Vec) -> Vec { + let mut next = vec![-1; next_len]; + let mut j = -1; + for i in 1..s.len() { + while j >= 0 && s[i] != s[(j + 1) as usize] { + j = next[j as usize]; + } + if s[i] == s[(j + 1) as usize] { + j += 1; + } + next[i] = j; + } + next + } + pub fn repeated_substring_pattern(s: String) -> bool { + let s_chars = s.chars().collect::>(); + let next = Self::get_next(s_chars.len(), &s_chars); + if next[s_chars.len() - 1] >= 0 + && s_chars.len() % (s_chars.len() - (next[s_chars.len() - 1] + 1) as usize) == 0 + { + return true; + } + false + } +} +``` +

diff --git a/problems/0518.零钱兑换II.md b/problems/0518.零钱兑换II.md index e5c8b251..e29e2107 100644 --- a/problems/0518.零钱兑换II.md +++ b/problems/0518.零钱兑换II.md @@ -7,7 +7,7 @@ ## 518. 零钱兑换 II -[力扣题目链接](https://leetcode.cn/problems/coin-change-2/) +[力扣题目链接](https://leetcode.cn/problems/coin-change-ii/) 难度:中等 diff --git a/problems/0541.反转字符串II.md b/problems/0541.反转字符串II.md index 3dd6b1e8..238e6349 100644 --- a/problems/0541.反转字符串II.md +++ b/problems/0541.反转字符串II.md @@ -399,19 +399,42 @@ object Solution { } } ``` -版本二: 首先利用sliding每隔k个进行分割,随后转换为数组,再使用zipWithIndex添加每个数组的索引,紧接着利用map做变换,如果索引%2==0则说明需要翻转,否则原封不动,最后再转换为String +版本二: 首先利用grouped每隔k个进行分割,再使用zipWithIndex添加每个数组的索引,紧接着利用map做变换,如果索引%2==0则说明需要翻转,否则原封不动,最后再转换为String ```scala object Solution { def reverseStr(s: String, k: Int): String = { - s.sliding(k, k) - .toArray - .zipWithIndex - .map(v => if (v._2 % 2 == 0) v._1.reverse else v._1) + // s = "abcdefg", k = 2 + s.grouped(k) // Iterator ["ab", "cd", "ef", "g"] + .zipWithIndex // Iterator [("ab", 0), ("cd", 1), ("ef", 2), ("g", 3)] + .map { + case (subStr, index) => + if (index % 2 == 0) subStr.reverse else subStr + } .mkString } } ``` +版本三: (递归) +```scala +import scala.annotation.tailrec + +object Solution { + def reverseStr(s: String, k: Int): String = { + @tailrec // 这个函数已经优化成了尾递归 + def reverse(s: String, needToReverse: Boolean, history: String): String = { + // 截取前k个字符(判断是否翻转) + val subStr = if (needToReverse) s.take(k).reverse else s.take(k) + // 如果字符串长度小于k,返回结果 + // 否则,对于剩余字符串进行同样的操作 + if (s.length < k) history + subStr + else reverse(s.drop(k), !needToReverse, history + subStr) + } + reverse(s, true, "") + } +} +``` + Rust: ```Rust diff --git a/problems/0701.二叉搜索树中的插入操作.md b/problems/0701.二叉搜索树中的插入操作.md index 039c3b6d..2e899e22 100644 --- a/problems/0701.二叉搜索树中的插入操作.md +++ b/problems/0701.二叉搜索树中的插入操作.md @@ -330,6 +330,26 @@ class Solution: return root ``` +**递归法** - 无返回值 有注释 不用Helper function +```python +class Solution: + def insertIntoBST(self, root: Optional[TreeNode], val: int) -> Optional[TreeNode]: + if not root: # for root==None + return TreeNode(val) + if root.valval: + if root.left==None: # found the parent + root.left = TreeNode(val) + else: # not found, keep searching + self.insertIntoBST(root.left, val) + # return the final tree + return root +``` + **迭代法** 与无返回值的递归函数的思路大体一致 ```python @@ -337,16 +357,15 @@ class Solution: def insertIntoBST(self, root: TreeNode, val: int) -> TreeNode: if not root: return TreeNode(val) - parent = None + parent = None # 此步可以省略 cur = root # 用while循环不断地找新节点的parent while cur: + parent = cur # 首先保存当前非空节点作为下一次迭代的父节点 if cur.val < val: - parent = cur cur = cur.right elif cur.val > val: - parent = cur cur = cur.left # 运行到这意味着已经跳出上面的while循环, diff --git a/problems/1002.查找常用字符.md b/problems/1002.查找常用字符.md index 78eb1989..fd188660 100644 --- a/problems/1002.查找常用字符.md +++ b/problems/1002.查找常用字符.md @@ -451,6 +451,42 @@ object Solution { } } ``` + +Rust: + +```rust +impl Solution { + pub fn common_chars(words: Vec) -> Vec { + if words.is_empty() { + return vec![]; + } + let mut res = vec![]; + let mut hash = vec![0; 26]; + for i in words[0].bytes() { + hash[(i - b'a') as usize] += 1; + } + for i in words.iter().skip(1) { + let mut other_hash_str = vec![0; 26]; + for j in i.bytes() { + other_hash_str[(j - b'a') as usize] += 1; + } + for k in 0..26 { + hash[k] = hash[k].min(other_hash_str[k]); + } + } + + for (i, v) in hash.iter_mut().enumerate() { + while *v > 0 { + res.push(((i as u8 + b'a') as char).to_string()); + *v -= 1; + } + } + + res + } +} +``` +

diff --git a/problems/1221.分割平衡字符串.md b/problems/1221.分割平衡字符串.md index 94d7bca8..b587514a 100644 --- a/problems/1221.分割平衡字符串.md +++ b/problems/1221.分割平衡字符串.md @@ -117,7 +117,7 @@ class Solution: diff -= 1 else: diff += 1 - if tilt == 0: + if diff == 0: ans += 1 return ans ``` diff --git a/problems/栈与队列理论基础.md b/problems/栈与队列理论基础.md index da3a6dfa..66b86919 100644 --- a/problems/栈与队列理论基础.md +++ b/problems/栈与队列理论基础.md @@ -59,7 +59,7 @@ C++标准库是有多个版本的,要知道我们使用的STL是哪个版本 ![栈与队列理论3](https://img-blog.csdnimg.cn/20210104235459376.png) -**我们常用的SGI STL,如果没有指定底层实现的话,默认是以deque为缺省情况下栈的低层结构。** +**我们常用的SGI STL,如果没有指定底层实现的话,默认是以deque为缺省情况下栈的底层结构。** deque是一个双向队列,只要封住一段,只开通另一端就可以实现栈的逻辑了。