单调栈用法

文章目录

  • 1. 单调栈
    • 1.1 理解单调栈(模板)
    • 1.2 每日温度
    • 1.3 子数组的最小值之和
    • 1.4 柱状图中最大的矩形
    • 1.5 最大矩形
    • 1.6 最大宽度坡
    • 1.7 去除重复字母

1. 单调栈

单调栈经典的用法:

对每个位置都求:

  • 当前位置的左侧比当前位置的数,且距离最近的位置
  • 当前位置的右侧比当前位置的数,且距离最近的位置

或者:

  • 当前位置的左侧比当前位置的数,且距离最近的位置
  • 当前位置的右侧比当前位置的数,且距离最近的位置

1.1 理解单调栈(模板)

image-20240309212339183

  1. 题目分析
单调栈顾名思义就是用栈来维护单调性。栈中存放的是数组元素的下标在本题思路:- 遍历nums数组,将数组元素按从小到大的顺序入栈- 若当前数组元素比栈顶元素小,则弹出栈顶元素,直到栈空或者栈顶元素小于当前元素为止如何记录距离某个元素左边最近且小与它的数的下标、右边最近且小于它的数的下标:- 在弹栈的时候,弹出元素就是目标元素- 小于目标元素、左边最近的元素就是弹出它后的栈顶元素,若栈为空,则为-1- 大于目标元素、右边最近的元素就是当前还未入栈的那个元素(迫使目标元素出栈的那个元素)- 当遍历到nums数组末位的时候,如果栈内还有元素,则依次弹出,右边最近且小于它的数没有,为-1,左边就是弹出它后的栈顶元素,若栈空,则为-1若nums数组中有值相同的元素,那么会有一种情况:- 假如将要入栈的元素的值等于栈顶元素的值,将栈顶元素弹出- 弹出后的目标元素的右边最近且小于它的数就是将要入栈的数(当然这只是暂时性的)- 记cur为目标元素,left为cur左边最近且小于cur的数,right同理。- 遍历完nums数组后,再从后向前遍历,找nums[cur] == nums[right]- 将cur的right重新赋值为right的right
  1. 代码实现
from collections import dequedef foundMonotoneStack(nums):n = len(nums)# 需要返回的二维数组ans = [[] for _ in range(n)]# 初始化栈s = deque()# 存入nums第一个元素的下标s.append(0)# 开始遍历数组for i in range(1, n):# 如果将要入栈的元素大于栈顶元素就入栈if nums[s[-1]] < nums[i]:s.append(i)continue# 如果将要入栈的元素小于等于栈顶元素,就挨着弹栈,直到栈空或者将要入栈的元素大于栈顶元素# 并在弹栈的过程中填入cur的left和rightwhile len(s) > 0 and nums[s[-1]] >= nums[i]:cur = s.pop()if len(s) > 0:ans[cur].append(s[-1])else:ans[cur].append(-1)ans[cur].append(i)# 最后记得将 将要入栈的元素 压栈s.append(i)# 遍历完数组后检查栈是否为空,不为空又继续弹,规则跟上面那个弹栈差不多while len(s) > 0:cur = s.pop()if len(s) > 0:ans[cur].append(s[-1])else:ans[cur].append(-1)ans[cur].append(-1)# 最后再检查nums[cur]是否等于nums[right],若等于,nums[right]就应该等于right的rightfor i in range(n - 1, -1, -1):if ans[i][1] != -1 and nums[i] == nums[ans[i][1]]:ans[i][1] = ans[ans[i][1]][1]return ans

image-20240309223756878

1.2 每日温度

image-20240309231131059

  1. 题目分析:
在当前位置,想要观察比当前温度更高的气温,需要等待的天数->
在当前位置,想要在右侧找到比当前位置的数更大的数,且距离最近,求这个距离这样就转换成了类似于模板的题目,只不过栈内元素是从大到小入栈
  1. 模板代码实现
from collections import deque
def dailyTemperatures(temperatures):""":type temperatures: List[int]:rtype: List[int]"""n = len(temperatures)ans = [0] * n# 初始化栈s = deque()s.append(0)for i in range(1, n):# 如果将要入栈的元素的值小于栈顶元素的值,就入栈if temperatures[i] < temperatures[s[-1]]:s.append(i)continue# 如果将要入栈的元素的值大于等于栈顶元素的值,就不断弹出栈顶元素while len(s) > 0 and temperatures[i] >= temperatures[s[-1]]:cur = s.pop()# 这里只用考虑右边,所以简洁一些ans[cur] = i - curs.append(i)# 当遍历完数组后,后面一定没有比栈顶元素大的数了while len(s) > 0:cur = s.pop()ans[cur] = 0# 最后这里有点难想,我也是因为测试用例不通过,进而调试改进的,测试用例是下面这个# [34,80,80,34,34,80,80,80,80,34]for i in range(n - 1, -1, -1):if ans[i] != 0 and temperatures[i] == temperatures[i + ans[i]]:if ans[i + ans[i]] == 0:ans[i] = ans[i + ans[i]]else:ans[i] += ans[i + ans[i]]return ans

image-20240310001909684

  1. 模板代码改进
# 改进的地方就是,针对这个题而言,当栈顶元素等于将要入栈的元素时,入栈元素照常入栈,没有影响
# 这样也少了最下面那一个稍微难想的循环
from collections import deque
def dailyTemperatures(temperatures):""":type temperatures: List[int]:rtype: List[int]"""n = len(temperatures)ans = [0] * n# 初始化栈s = deque()s.append(0)for i in range(1, n):# 如果将要入栈的元素的值小于栈顶元素的值,就入栈if temperatures[i] <= temperatures[s[-1]]:s.append(i)continue# 如果将要入栈的元素的值大于等于栈顶元素的值,就不断弹出栈顶元素while len(s) > 0 and temperatures[i] > temperatures[s[-1]]:cur = s.pop()# 这里只用考虑右边,所以简洁一些ans[cur] = i - curs.append(i)# 当遍历完数组后,后面一定没有比栈顶元素大的数了while len(s) > 0:cur = s.pop()ans[cur] = 0return ans

image-20240310002328716

1.3 子数组的最小值之和

image-20240310135008741

  1. 题目思路
一般思路:找出所有的连续子数组,然后再求出每个子数组中的最小值进行累加如何利用单调栈的特性来做?- 一个最小值可能在多个子数组中出现- 在单调栈的模板中,我们有cur、left和right。* left表示在cur的左边、距离cur最近且小于cur的数的下标* right表示在cur的右边、距离cur最近且小于cur的数的下标- 那么在left到cur之间、cur到right之间的数一定是比cur大的数- 由这些数组成的连续子数组且包含cur,它们的最小值一定是cur位置的数,所以我们的目的就变成了计算这些数组的数目- 那么如何计算这些数组的数量呢?* 假如给定一系列下标:[left, a, b, c, cur, d, e, f, g, right]* 那么符合条件的子数组有:1. [a, b, c, cur]2. [a, b, c, cur, d]3. [a, b, c, cur, d, e]4. [a, b, c, cur, d, e, f]5. [a, b, c, cur, d, e, f, g]6. [b, c, cur]7. [b, c, cur, d]8. [b, c, cur, d, e]9. [b, c, cur, d, e, f]10.[b, c, cur, d, e, f, g]11.[c, cur]12.[c, cur, d]13.[c, cur, d, e]14.[c, cur, d, e, f]15.[c, cur, d, e, f, g]16.[cur]17.[cur, d]18.[cur, d, e]19.[cur, d, e, f]20.[cur, d, e, f, g]一共二十个* 可以看到由a开头的数组5个,b开头的5个,c开头的5个,cur开头的5个,一共是由left到cur中间的数包括cur来开头的,像这种由哪个开头的这类数组一共有cur-left种* 又可以看到由cur结尾的数组4个,d结尾的4个,e结尾的4个,f结尾的4个,g结尾的4个,一共是由cur到right中间的数包括cur来结尾的,像这种由哪个结尾的这类数组一共有right-cur种* 所以总共就有(cur-left)*(right-cur)种数组- 当将要入栈的元素的值等于栈顶元素的时候怎么办?* 找个特例自己看哪种合适* 本题中,照常弹栈即可
  1. 代码实现
# 还是照常套模板from collections import dequedef sumSubarrayMins(arr):""":type arr: List[int]:rtype: int"""MAX = 10 ** 9 + 7n = len(arr)all = 0s = deque()s.append(0)# 大压小for i in range(1, n):if arr[i] > arr[s[-1]]:s.append(i)continuewhile len(s) > 0 and arr[i] <= arr[s[-1]]:cur = s.pop()if len(s) > 0:left = s[-1]else:# 如果栈内没元素,就表示cur的左边没有比它小的数了,此时cur-left=cur-(-1),是因为要包括0在内left = -1right = i# 同余原理all += (all + (cur - left) * (right - cur) * arr[cur]) % MAXs.append(i)while len(s) > 0:cur = s.pop()# 最后执行弹栈操作时,它们没有right,表示右边没有比它们小的数了,right-cur=n-cur,这也是因为需要将n-1包括进去right = nif len(s) > 0:left = s[-1]else:left = -1all += (all + (cur - left) * (right - cur) * arr[cur]) % MAXreturn all

image-20240310144314334

1.4 柱状图中最大的矩形

image-20240310145540738

  1. 题目思路
跟上个题的思路差不多找到cur的left和right:- cur:当前弹出栈的元素的下标- left:cur左边、距离cur最近且比cur小的数的下标- right:cur右边、距离cur最近且比cur小的数的下标每个cur的最大面积:(right-left-1) * heights[cur]
  1. 代码实现
from collections import dequedef largestRectangleArea(heights):""":type heights: List[int]:rtype: int"""max_area = 0n = len(heights)s = deque()s.append(0)for i in range(1, n):if heights[i] > heights[s[-1]]:s.append(i)continuewhile len(s) > 0 and heights[i] <= heights[s[-1]]:cur = s.pop()left = s[-1] if len(s) > 0 else -1right = imax_area = max(max_area, (right - left - 1) * heights[cur])s.append(i)while len(s) > 0:cur = s.pop()left = s[-1] if len(s) > 0 else -1right = nmax_area = max(max_area, (right - left - 1) * heights[cur])return max_area

image-20240310150901646

1.5 最大矩形

image-20240310153137614

  1. 题目分析
解决方法:转换为柱状图的解决思路首先,以上图为例:
以第一行为底,柱状图的大小为[1,0,1,0,0]
以第二行为底,柱状图的大小为[2,0,2,1,1]
以第三行为底,柱状图的大小为[3,1,3,2,2]
以第四行为底,柱状图的大小为[4,0,0,1,0]
循环三次,在每次循环中找最大的矩形面积即可
  1. 代码实现
from collections import dequedef maximalRectangle(matrix):""":type matrix: List[str]:rtype: int"""# 将matrix中的每个字符串变成一个整型列表matrix = [list(map(int, list(matrix[i]))) for i in range(len(matrix))]if len(matrix) == 0:return 0n = len(matrix)m = len(matrix[0])max_area = 0# 用来更新柱状图的信息temp_arr = [0] * mfor i in range(n):# 下面的循环就跟前面柱状图那个题的代码一样# 需要注意的是不要把i和j搞混了for j in range(m):temp_arr[j] = 0 if matrix[i][j] == 0 else (temp_arr[j] + matrix[i][j])s = deque()s.append(0)for j in range(1, m):if temp_arr[j] > temp_arr[s[-1]]:s.append(j)continuewhile len(s) > 0 and temp_arr[j] <= temp_arr[s[-1]]:cur = s.pop()left = s[-1] if len(s) > 0 else -1right = jmax_area = max(max_area, (right - left - 1) * temp_arr[cur])s.append(j)while len(s) > 0:cur = s.pop()left = s[-1] if len(s) > 0 else -1right = mmax_area = max(max_area, (right - left - 1) * temp_arr[cur])return max_area

image-20240310160037675

1.6 最大宽度坡

image-20240310162245209

  1. 题目思路
要求的是什么?求的是一段距离(也就是下标之差)cur的右边、距离cur最远、比cur大的数的下标cur的左边、距离cur最远、比cur小的数的下标单调栈压栈方式:小压大,比栈顶元素小的进栈,如果比栈顶元素大,就不用进栈,继续比较下一个。
如果比栈顶元素大的进栈了,那么后续遇到比这个栈顶元素大的,所形成的最大宽度坡一定比它下面那个元素所形成的最大宽度坡小。
因为它下面的那个本身值也比栈顶的小,并且位置也比栈顶的靠前一轮比较完后,栈内的元素从底到顶就是按照从大到小的顺序。然后再从尾到头遍历数组A,如果A[i]大于等于栈顶元素,就弹出栈顶元素,记录当前的宽度坡(始终记录最大的宽度坡);如果A[i]小于栈顶元素,就往前遍历A数组。
  1. 代码实现
from collections import dequedef maxWidthRamp(nums):""":type nums: List[int]:rtype: int"""n = len(nums)max_slope = 0s = deque()s.append(0)for i in range(1, n):if nums[i] < nums[s[-1]]:s.append(i)continuefor i in range(n - 1, -1, -1):while len(s) > 0 and nums[s[-1]] <= nums[i]:max_slope = max(max_slope, i - s.pop())return max_slope

image-20240310164450840

1.7 去除重复字母

image-20240310170359248

  1. 题目分析
首先,字符的顺序不能更改对于前面的字符,我们只需要统计一下它们的总出现次数,只要大于0,就能删除如何用单调栈来做呢?- 压栈的时候大压小,如果当前字符大于栈顶字符、且栈内没有该元素,压栈- 如果当前字符小于等于栈顶字符,判断栈顶字符出现的次数是否大于0,若大于就可以弹出,若小于0就不能弹出- 每一次压栈后,将这个字符的出现次数-1,并且将其标记为True,表示栈里面有这个元素- 每一次弹栈后,将这个字符标记为False,表示栈里没有这个元素了
  1. 下面的代码有点绕,也是自己测试了好久写出来的
from collections import dequedef removeDuplicateLetters(s):""":type s: str:rtype: str"""n = len(s)cnts = [0] * 26for i in range(n):cnts[ord(s[i]) - ord('a')] += 1marked = [False] * 26# 初始化栈stack = deque()stack.append(s[0])cnts[ord(s[0]) - ord('a')] -= 1marked[ord(s[0]) - ord('a')] = Truefor i in range(1, n):# 比栈顶字符大、且没在栈内出现过,入栈if marked[ord(s[i]) - ord('a')] == False and s[i] > stack[-1]:stack.append(s[i])marked[ord(s[i]) - ord('a')] = Truecnts[ord(s[i]) - ord('a')] -= 1continue# 栈不为空、当前字符小于等于栈顶字符、栈顶元素剩余出现次数大于0、且当前字符未在栈内出现,弹栈while len(stack) > 0 and s[i] <= stack[-1] and cnts[ord(stack[-1]) - ord('a')] > 0 and marked[ord(s[i]) - ord('a')] == False:marked[ord(stack[-1]) - ord('a')] = Falsestack.pop()# 如果当前字符连上面两个条件都不满足,但是它没在栈内出现过,入栈if marked[ord(s[i]) - ord('a')] == False:stack.append(s[i])marked[ord(s[i]) - ord('a')] = True# 如果在栈内出现过,就跳过这个字符,并且出现次数减一cnts[ord(s[i]) - ord('a')] -= 1# 将栈内字符拼接成一个字符串ans = [''] * len(stack)for i in range(len(ans) - 1, -1, -1):ans[i] = stack.pop()return ''.join(ans)

image-20240310200856515

  1. 精简版
from collections import dequedef removeDuplicateLetters(s):""":type s: str:rtype: str"""n = len(s)cnts = [0] * 26for i in range(n):cnts[ord(s[i]) - ord('a')] += 1marked = [False] * 26# 初始化栈stack = deque()stack.append(s[0])cnts[ord(s[0]) - ord('a')] -= 1marked[ord(s[0]) - ord('a')] = Truefor i in range(1, n):# 如果当前字符没在栈内出现if marked[ord(s[i]) - ord('a')] == False:# 如果栈内有字符、当前字符小于等于栈顶字符、且栈顶字符剩余出现次数大于0while len(stack) > 0 and s[i] <= stack[-1] and cnts[ord(stack[-1]) - ord('a')] > 0:marked[ord(stack[-1]) - ord('a')] = Falsestack.pop()# 如果栈空、当前字符大于栈顶字符、栈顶字符剩余出现次数等于0,就直接入栈stack.append(s[i])marked[ord(s[i]) - ord('a')] = True# 不管它入不入栈,它的剩余出现次数都要减1cnts[ord(s[i]) - ord('a')] -= 1# 将栈内字符拼接成一个字符串ans = [''] * len(stack)for i in range(len(ans) - 1, -1, -1):ans[i] = stack.pop()return ''.join(ans)

image-20240310202113348

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/307101.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

openGauss_5.1.0 企业版快速安装及数据库连接:单节点容器化安装

目录 &#x1f4da;第一章 官网信息&#x1f4da;第二章 安装&#x1f4d7;下载源码&#x1f4d7;下载安装包&#x1f4d7;修改版本&#x1f4d7;解压安装包&#x1f4d7;运行buildDockerImage.sh脚本&#x1f4d7;docker操作&#x1f4d5;查看docker镜像&#x1f4d5;启动dock…

013_NaN_in_Matlab中的非数与调试方法

Matlab中的非数与调试方法 是什么&#xff1f; Matlab编程&#xff08;计算器使用&#xff09;中经常有个错误给你&#xff0c;这句话里可能包含一个关键词NaN。大部分学生都有过被 NaN 支配的痛苦记忆。 NaN 是 Not a Number 的缩写&#xff0c;表示不是一个数字。在 Matla…

负荷预测 | Matlab基于TCN-GRU-Attention单输入单输出时间序列多步预测

目录 效果一览基本介绍程序设计参考资料 效果一览 基本介绍 1.Matlab基于TCN-GRU-Attention单输入单输出时间序列多步预测&#xff1b; 2.单变量时间序列数据集&#xff0c;采用前12个时刻预测未来96个时刻的数据&#xff1b; 3.excel数据方便替换&#xff0c;运行环境matlab20…

R: 支持向量机(Support Vector Machine,简称SVM)

在数据科学和机器学习领域中&#xff0c;支持向量机&#xff08;Support Vector Machine&#xff0c;简称SVM&#xff09;是一种强大的监督学习算法&#xff0c;常用于分类和回归分析。它的优点之一是可以适用于复杂的数据集&#xff0c;并且在高维空间中表现良好。在本文中&am…

MindOpt APL向量化建模语法的介绍与应用(2)

前言 在数据科学、工程优化和其他科学计算领域中&#xff0c;向量和矩阵的运算是核心组成部分。MAPL作为一种数学规划语言&#xff0c;为这些领域的专业人员提供了强大的工具&#xff0c;通过向量式和矩阵式变量声明以及丰富的内置数学运算支持&#xff0c;大大简化了数学建模…

316_C++_xml文件解析成map,可以放到表格上 + xml、xlsx文件互相解析

xml文件例如&#xff1a; <?xml version"1.0" encoding"UTF-8" standalone"yes"?> <TrTable> <tr id"0" label"TR_PB_CH" text"CH%2"/> <tr id"4" label"TR_PB_CHN"…

Day:007(2) | Python爬虫:高效数据抓取的编程技术(scrapy框架使用)

Scrapy 数据的提取 Scrapy有自己的数据提取机制。它们被称为选择器。我们可以通过使用的选择器re、xpath、css提取数据 提示 不用再安装与引入Xpath,BS4 获得选择器 Response对象获取 正常使用 response.selector.xpath(//span/text()).get() response.selector.css(span::…

开发有哪些常见陷阱?

引言 在当今数字化时代&#xff0c;软件开发已成为推动科技进步和商业发展的重要引擎。然而&#xff0c;软件开发并非一帆风顺&#xff0c;其中蕴藏着许多陷阱和挑战。如何避免这些陷阱&#xff0c;提高软件开发的效率和质量&#xff0c;成为开发者们面临的重要问题 本文将深…

原型模式:复制对象的智能解决方案

在软件开发过程中&#xff0c;对象的创建可能是一个昂贵的操作&#xff0c;特别是当对象的初始化包括从数据库加载数据、进行IO操作或进行复杂计算时。原型模式是一种创建型设计模式&#xff0c;它通过复制现有的实例来创建新的对象实例&#xff0c;从而避免了类初始化时的高成…

单片机方案 发声毛绒小黄鸭

随着科技的不断进步&#xff0c;智能早教已经成为了新时代儿童教育的趋势。智能早教玩具&#xff0c;一款集互动陪伴、启蒙教育、情感培养于一身的高科技产品。它不仅能陪伴孩子成长&#xff0c;还能在游戏中启迪智慧&#xff0c;是家长和孩子的理想选择。 酷得电子方案开发特…

redis 数据迁移到rds2214(TongRDS-2.2.1.3.Load版 by lqw)

​ 文章目录 一.备份redis文件 vi redis.conf &#xff0c;看看有没有这两行设置&#xff0c;有的话改成跟下面的一致&#xff1a; appendonly yes appendfilename “appendonly.aof” 之后连接redis客户端&#xff0c;输入INFO persistence&#xff0c;如图所示即为开启成功…

使用Docker定时备份数据

文章目录 一、Docker镜像制作二、MySQL数据备份三、Minio数据备份四、数据跨服务器传输五、Nginx日志分割六、Docker启动七、Docker备份日志 一、Docker镜像制作 镜像制作目录 mc下载地址 - rsyncd.conf # https://download.samba.org/pub/rsync/rsyncd.conf.5port 873 uid …

远程桌面防火墙是什么?

远程桌面防火墙&#xff0c;是一种针对远程桌面应用的安全防护工具。它可以在保证远程桌面连接的便利性和高效性的对网络连接进行安全性的保护&#xff0c;防止未经授权的访问和潜在的安全风险。 远程桌面防火墙的主要功能是对远程桌面连接进行监控和管理。它通过识别和验证连接…

【题目】【信息安全管理与评估】2022年国赛高职组“信息安全管理与评估”赛项样题2

【题目】【信息安全管理与评估】2022年国赛高职组“信息安全管理与评估”赛项样题2 信息安全管理与评估 网络系统管理 网络搭建与应用 云计算 软件测试 移动应用开发 任务书&#xff0c;赛题&#xff0c;解析等资料&#xff0c;知识点培训服务 添加博主wx&#xff1a;liuliu548…

一起学习python——基础篇(18)

上一篇讲述了python中文件夹和文件的检测有无判断、文件夹和文件的创建、文件写入一些内容的方法、文件夹和文件的删除。 这一篇来说一下python的如何读取文件内容。 #文件的路径 testPath"D:/pythonFile/test.txt" #使用open方法&#xff0c;参数为r&#xff1a;表…

C++ 类和对象 上

目录 前言 什么是面向对象&#xff1f;什么是面向过程&#xff1f; 面向过程 面向对象 比较 类 引入 定义 实例化 类的大小 this指针 前言 今天我们来进入C类和对象的学习。相信大家一定听说过C语言是面向过程的语言&#xff0c;而C是面向对象的语言&#xff1f;那么他…

Android 纵向双选日历

这个日历的布局分两部分&#xff0c;一部分是显示星期几的LinearLayout&#xff0c;另外就是一个RecyclerView&#xff0c;负责纵向滚动了。 工具类&#xff1a; implementation com.blankj:utilcode:1.17.3上activity_calendar代码&#xff1a; <?xml version"1.0&…

【CSS面试题】Flex实现九宫格

考察知识&#xff1a; flex布局 水平垂直居中的实现 初始效果 代码关键&#xff1a;给父盒子添加以下属性 flex-wrap: wrap; /* 允许换行 */justify-content: space-around; /* 主轴对齐方式 */align-content: space-around; /* 多行在侧轴上的对齐方式 */<!DOCTYPE html&…

关于阿里云centos系统下宝塔面板部署django/中pip install mysqlclient失败问题的大总结/阿里云使用oss长期访问凭证

python版本3.12.0 项目的版本依赖 问题1 解决方案 sudo vim /etc/profile export MYSQLCLIENT_CFLAGS"-I/usr/include/mysql" export MYSQLCLIENT_LDFLAGS"-L/usr/lib64/mysql" Esc退出编辑模式 &#xff1a;wq退出并且保存 问题二 说是找不到 mysql.h头…

大数据入门之如何利用Phoenix访问Hbase

在大数据的世界里&#xff0c;HBase和Phoenix可谓是一对黄金搭档。HBase以其高效的列式存储和强大的数据扩展能力&#xff0c;成为大数据存储领域的佼佼者&#xff1b;而Phoenix则以其SQL化的操作方式&#xff0c;简化了对HBase的访问过程。今天&#xff0c;就让我们一起看看如…