JavaScript算法|前 K 个高频元素、寻找峰值和合并区间、 搜索二维矩阵 II和计算右侧小于当前元素的个数

文章目录

    • 前 K 个高频元素
      • 方法一
      • 方法二
      • 代码
    • 寻找峰值
      • 方法一 取最大值
      • 方法二 暴力法
      • 方法三 二分法
    • 合并区间
      • 方法一 合并重叠
      • 方法二 合并重叠
    • 搜索二维矩阵 II
      • 方法一 暴力法
      • 方法二 相邻比较法
    • 计算右侧小于当前元素的个数
      • 方法一 暴力法
      • 方法二 排序法

前 K 个高频元素

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

示例 1:

输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

示例 2:

输入: nums = [1], k = 1
输出: [1]

说明:

你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。 你的算法的时间复杂度必须优于 O(n log n) , n 是数组的大小。

方法一

思路

这一题属于比较简单的算法题,整体的思路是需要开辟一个新的储存空间,对数组中数字的出现的次数进行记录,再对这个存储记录进行读取,进而得出前 K 个高频元素

详解

第一步,记录每个数出现的次数

  let map = new Map();for (let num of nums) { // 记录每个数出现的次数map.set(num, (map.get(num) || 0) + 1);}

第二步,设置一个数组 countOfNum,其第 i 个元素表示出现 i 次的元素数组

  let countOfNum = Array(nums.length);for (let key of map.keys()) {let value = map.get(key);if (countOfNum[value] === undefined) {countOfNum[value] = [key]} else {countOfNum[value].push(key)}}

第三步,从 countOfNum 末尾开始往头遍历,将非空元素都加入结果数组中,直到结果数组的大小等于K。

  let res = [];for (let i = countOfNum.length - 1; i >= 0 && res.length < k; i--) {if (countOfNum[i] !== undefined) {res = res.concat(countOfNum[i])}}return res;

代码

/*** @param {number[]} nums* @param {number} k* @return {number[]}*/
const topKFrequent = function(nums, k) {let map = new Map();for (let num of nums) { map.set(num, (map.get(num) || 0) + 1);}let countOfNum = Array(nums.length);for (let key of map.keys()) {let value = map.get(key);if (countOfNum[value] === undefined) {countOfNum[value] = [key]} else {countOfNum[value].push(key)}}let res = [];for (let i = countOfNum.length - 1; i >= 0 && res.length < k; i--) {if (countOfNum[i] !== undefined) {res = res.concat(countOfNum[i])}}return res;
};

复杂度分析

  • 时间复杂度:O(n)O(n)
    • 上述解法中,我们使用了一层 for 循环,里面的代码会执行 n 遍,它消耗的时间是随着 n 的变化而变化的,因此时间复杂度是 O(n)O(n)
  • 空间复杂度: O(n)O(n)
    • 上述解法中,我们额外声明的空间大小和输入规模成正比,所以空间复杂度为 O(n)O(n)

方法二

思路

整体思路同方法一,这一种方法我们使用 forEach 和 sort 简化了实现方案

详解

第一步,构建一个对象作为储存空间

  const hashTable = {}nums.forEach(item => {if (hashTable[item] === undefined) {hashTable[item] = 1} else {hashTable[item]++}})

第二步,根据存储的出现次数,对数组进行排序

hashTableArray = Object.keys(hashTable)
hashTableArray.sort((prev, next) => {return hashTable[next] - hashTable[prev]
})

第三步,截取数去的前K项,得到想要的结果

return hashTableArray.slice(0, k)

代码

/*** @param {number[]} nums* @param {number} k* @return {number[]}*/
var topKFrequent = function(nums, k) {const hashTable = {}nums.forEach(item => {if (hashTable[item] === undefined) {hashTable[item] = 1} else {hashTable[item]++}})hashTableArray = Object.keys(hashTable)hashTableArray.sort((prev, next) => {return hashTable[next] - hashTable[prev]})return hashTableArray.slice(0, k)
};

复杂度分析

  • 时间复杂度:O(n)O(n)
  • 空间复杂度: O(n)O(n)

寻找峰值

峰值元素是指其值大于左右相邻值的元素。 给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。 数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。 你可以假设 nums[-1] = nums[n] = -∞。

示例

输入: nums = [1,2,3,1]
输出: 2
解释: 3 是峰值元素,你的函数应该返回其索引 2。

方法一 取最大值

思路

取最大值法思路最简单,最大值必然就是其峰值。因为这是算法题,我们就不用 Math.max 了。直接一次循环解决问题。

详解

  1. 使用数组的 reduce 方法遍历数组,设其初始值为 0。
  2. 当遍历到的值大于上一次返回的下标所对应的值时返回当前下标。
  3. 遍历结束后所获取的值为最终答案。

代码

const findPeakElement = function (nums) {return nums.reduce((index, cur, i) => {if (nums[index] < cur) {return i;}return index;}, 0);
};

复杂度分析

  • 时间复杂度:O(n)O(n) 对于每个元素,通过遍历数组进行比较值的大小来寻找它所对应的目标元素,这将耗费 O(n)O(n) 的时间。

  • 空间复杂度:O(1)O(1)

    算法执行的过程中,声明的变量并不与数组的长度 nn 相关。故而空间复杂度为 O(1)O(1)。

方法二 暴力法

思路

暴力法很简单,遍历每个元素,并寻找到元素 n 大于元素 n + 1。则 n 就是我们要找的峰值。如果没有这个值,则数组的最后一个元素就是峰值。

详解

  1. 遍历数组找出第 i 个元素大于 i+1 个元素的元素的下标为结果。
  2. 如果遍历完成没有找到,则取元素最后一个值的下标为结果。

代码

const findPeakElement = function (nums) {// 如果全部从小到大排列,则峰值为最后一个元素let result = nums.length - 1;// 否则只要找出第 i 个元素大于 i+1 个元素,则第 i 个元素就是峰值for (let i = 0; i < nums.length - 1; i += 1) {if (nums[i] > nums[i + 1]) {result = i;break;}}return result;
};

复杂度分析

  • 时间复杂度:O(n)O(n) 对于每个元素,通过遍历数组进行比较值的大小来寻找它所对应的目标元素,这将耗费 O(n)O(n) 的时间。

  • 空间复杂度:O(1)O(1)

    算法执行的过程中,声明的变量并不与数组的长度 nn 相关。故而空间复杂度为 O(1)O(1)。

方法三 二分法

思路

将数组从中间分成两个数组 L 和 R。比较 L 最后一个值 l 与 R 的第一个值 r 的大小。如果 l > r 则数组 L 必有一个及以上原数组的峰值,取数组 L 再做上一步。反之则数组 R 必有一个及以上原数组的峰值,取数组 R 再做上一步。当数组长度为 1 时。其值为峰值。

详解

  1. 将目标数组从中间分成两个数组 L 和 R。
  2. 比较 L 最后一个值 l 与 R 的第一个值 r 的大小。
  3. 如果 l > r 则数组 L 必有一个及以上原数组的峰值,取数组 L 作为目标数组。
  4. 反之则数组 R 必有一个及以上原数组的峰值,取数组 R 作为目标数组。
  5. 目标数组长度为 1 则其值为峰值。
  6. 目标数组长度大于 1 则重复 1,2,3,4 步骤。直至目标数组长度为 1 为止。

代码

const findPeakElement = function (nums) {let lIndex = 0; // 虚拟数组第一个元素下标let rIndex = nums.length - 1; // 虚拟数组最后一个元素下标let mid; // 数组中间元素下标。while (lIndex < rIndex) { // 当数组长度不为 1 时。mid = Math.floor((lIndex + rIndex) / 2); // 取当前虚拟数组的中间元素的下标(当数组长度为偶数时取小的那个),可将虚拟元素隔开成两个数组。if (nums[mid] > nums[mid + 1]) { // 比较左边数组最后一个元素与右边数组的第一个元素的大小rIndex = mid; // 左边数组最后一个元素大、则取左边数组} else {lIndex = mid + 1; // 右边数组第一个元素大、则取右边数组}}return lIndex;
};

复杂度分析:

  • 时间复杂度:O(logn)O(logn)

    每次循环数组的长度都除以 2 。设 x 次循环之后 lIndex === rIndexlIndex===rIndex。也就是说 2 的 x 次方等于 n,那么 x = log2^nx=log2n 。也就是说当循环 log2^n 次以后,代码运行结束。因此这个代码的时间复杂度为:O(logn)O(logn)。

  • 空间复杂度:O(1)O(1)

    算法执行的过程中,声明的变量并不与数组的长度 n 相关。故而空间复杂度为 O(1)。

合并区间

给出一个区间的集合,请合并所有重叠的区间。

示例

输入: [[1,3],[2,6],[8,10],[15,18]],
输出: [[1,6],[8,10],[15,18]]。
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].

方法一 合并重叠

思路:

从示例入手: 1.[1, 3] [2, 6] 是否可以合并只要对比 [1, 3]的最大值 3,[2, 6]的最小值 2,3 <= 2 ,则说明可以合并,否则不能。 2.[1, 3] [2, 6] [8,10],从3个来看,如果 [2, 6]的最大值6 <= [8,10]的最小值 8,则说明[2, 6] 不能和 [8,10],因此 [1, 3] [2, 6] 执行合并操作,[8,10] 继续与下一个数组执行步骤一。

详解:

1.对区间进行排序(升序)
2.从第一区间起取当前拟合并区间为a,
3.取下一区间为b(如果没有b了则输出a,退出)
4.如果a的尾 > b 的头 ,则合并为 a,否则输出a,把b作为a。
const merge = intervals => {intervals.sort((a, b) => {if (a[0] !== b[0]){return a[0] - b[0];}   return a[1] - b[1];});let len = intervals.length,ans = [], // 定义新数组start, end; // 遍历当前区间的最小值与最大值for (let i = 0; i < len; i++) {let s = intervals[i][0],e = intervals[i][1];if (start === undefined){start = s, end = e;} else if (s <= end){end = Math.max(e, end);} else {let part = [start, end];ans.push(part);start = s;end = e;}}if (start !== undefined) {let part = [start, end];ans.push(part);}return ans;
};

复杂度分析

  • 时间复杂度:O(n)O(n)
  • 空间复杂度:O(1)O(1)

方法二 合并重叠

思路

从示例入手: 1.申明一个变量用于存储合并的结果 res = [] 2.第一个数组直接放入res中,res = [[1, 3]] 3.对比 res中的 [1, 3] 和 下一个数组 [2 ,6],[1,3] 的最大值 3 <= [2, 6] 的最小值2,则 res = [[1, 6]] 4.继续对比 res中的 [1, 6] 和下一个数组 [8, 10],则 res = [[1, 6], [8, 10]] 5.然后 从 [8, 10] 开始 继续执行步骤三

详解

  1. 对区间进行排序(升序)
  2. 定义一个新的数组,用于存储新的数组区间。
  3. 从第二个值开始遍历原数组,比较当前区间的最小值是否大于新数组最后一个区间的最大值,如果满足则push进入新的数组;又或者比较当前区间的最大值是否大于新新数组的随后一个区间的最大值,若满足则将新数组的最后一个区间的最大值替换成当前区间的最大值。
const merge = function(intervals) {if (!intervals || intervals.length === 0) {return [];}let input = intervals.sort((a, b) => a[0] - b[0]);let res = [];res.push(input[0]);for(let i = 1, len = input.length; i < len; i++) {if (input[i][0] > res[res.length - 1][1]) {res.push(input[i]);} else if (input[i][1] > res[res.length - 1][1]){res[res.length - 1][1] = input[i][1];}}return res;
};

复杂度分析

  • 时间复杂度:O(n)O(n)

    该算法对含有 n 个结点的列表进行了一次遍历。因此时间复杂度为 O(n)O(n)。

  • 空间复杂度:O(n)O(n)

    该算法只开辟了额外空间用于存储结果,空间大小与数组长度n成正比。故空间复杂度为O(n)O(n)。

搜索二维矩阵 II

编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target。该矩阵具有以下特性:

每行的元素从左到右升序排列。 每列的元素从上到下升序排列。

示例

现有矩阵 matrix 如下:[[1,   4,  7, 11, 15],[2,   5,  8, 12, 19],[3,   6,  9, 16, 22],[10, 13, 14, 17, 24],[18, 21, 23, 26, 30]
]给定 target = 5,返回 true。给定 target = 20,返回 false。

方法一 暴力法

思路

题目只需找出二维数组中是否包含目标值,因此直接用两个 for 循环遍历二维矩阵的所有元素,找到目标元素则返回 true,遍历完仍未找到则返回 false。

详解

  1. 第一层 for 循环取到二维数组中所有的一维数组
  2. 第二层 for 循环中用两个索引值取到二维数组中每一个具体的值
  3. 将取到的每一个值和目标值作比较,若相同则返回 true
  4. 若直到所有循环结束还未找到与目标值相同的值则返回 false

代码

const searchMatrix = function (matrix, target) {for (let i = 0; i < matrix.length; i++) {for (let j = 0; j < matrix[i].length; j++) {if (matrix[i][j] === target) {return true;}}}return false;
};

复杂度分析

  • 时间复杂度:O(n^2)O(n2) 通过遍历二维矩阵的所有元素来寻找它所对应的目标元素,这将耗费 O(n^2)O(n2) 的时间。
  • 空间复杂度:O(1)O(1)

方法二 相邻比较法

思路

由于矩阵的行和列是排序的,从左到右递增,从上到下递增,所以对任意元素和目标值比较大小时,总可以去找相对较小(往左往上)或相对较大(往右往下)的值继续比较,直到找到目标值或找不到。

详解

  1. 直接取二维数组中左下角的值和目标值比较
  2. 若该值比目标值大,则向上查找(第一个索引减 1),若该值比目标值小,则向右查找(第二个索引加 1)
  3. 重复该操作,当查询值等于目标值时则返回 true
  4. 若直到查询值离开二维数组时还未找到目标值则返回 false

代码

const searchMatrix = function (matrix, target) {let j = matrix.length - 1;let i = 0;while (j >= 0 && i < matrix[0].length) {if (matrix[j][i] > target) {j--;} else if (matrix[j][i] < target) {i++;} else {return true;}}return false;
};

复杂度分析

  • 时间复杂度:O(n + m)O(n+m) 由于行只能运算 m 次,列只能运算 n 次,是两个变量之和,这将耗费 O(n + m)O(n+m) 的时间。
  • 空间复杂度:O(1)O(1) 用到了两个变量,其空间复杂度为 O(1)O(1)

计算右侧小于当前元素的个数

给定一个整数数组 nums,按要求返回一个新数组 counts。数组 counts 有该性质: counts[i] 的值是 nums[i] 右侧小于 nums[i] 的元素的数量。

示例

输入: [5,2,6,1]
输出: [2,1,1,0] 
解释:
5 的右侧有 2 个更小的元素 (2 和 1).
2 的右侧仅有 1 个更小的元素 (1).
6 的右侧有 1 个更小的元素 (1).
1 的右侧有 0 个更小的元素.

方法一 暴力法

思路

暴力法很简单,遍历每个元素 x,并遍历查找在其后边并且比它小的元素,进行累加,最后将统计出来的个数 push 到新开辟的数组中。

详解

算法流程:

  1. 声明一个数组用来存储最后的结果;
  2. 第一层循环用来遍历所有的元素;
  3. 循环体内先声明一个变量,初始值为 0,用来记录当前元素右边并且比当前元素小的个数;
  4. 接下来通过第二个循环来计算当前元素右边比它小的数,由于只需要计算它右边的数,所以第二个循环从第 i + 1 开始,遍历到数组的最后一个值即可。第二层循环体内通过 if 语句来判断比当前元素小的数,然后执行 num ++;

代码

const countSmaller = (nums) => {const newArr = [];for (let i = 0, len = nums.length; i < len; i += 1) {let num = 0;for (let j = i + 1; j < nums.length; j += 1) {if (nums[j] < nums[i]) {num += 1;}}newArr.push(num);}return newArr;
};

复杂度分析

  • 时间复杂度:O(n^2)O(n2) 对于每个元素,通过遍历数组的其余部分来寻找它所对应的目标元素,所以时间复杂度为 O(n^2)O(n2)。
  • 空间复杂度:O(n)O(n) 额外开辟了一个数组来存放结果,所以空间复杂度为 O(n)O(n)。

方法二 排序法

思路

首先将数组元素进行从小到大的排序,排序完成后,遍历原数组,找出原数组中当前元素在排序后的数组中的数组下标,即为该元素右侧比它小的个数,然后将排序后的数组中的这个元素删除。

例如: 原数组 nums = [5,2,6,1]; 排序后的数组为 newArr = [1,2,5,6]; 对原数组 nums 进行遍历,首先是元素 5,在 newArr 中其数组下标为 2,其右侧比它小的元素有2个;然后将 newArr 中的5这个元素删除,newArr = [1,2,6];接下来是元素2,在newArr中的下标为1,然后将 newArr 中的2这个元素删除,其右侧比它小的元素有1个;以此类推…

详解

算法流程:

  1. 将原数组从小到大排序,并声明一个新数组来存储;
  2. 声明一个数组用来存储最后的结果;
  3. 对原数组进行遍历;
  4. 通过数组的方法 indexOf 找到遍历的当前元素在排序后的数组中的位置,并赋值给变量index,该变量的值即为当前元素右侧比它小的个数;
  5. 通过数组的方法 splice ,把当前元素从原数组中删除;

代码

const countSmaller = (nums) => {const newArr = [...nums].sort((a, b) => a - b);const result = [];nums.forEach((n) => {const index = newArr.indexOf(n);result.push(index);newArr.splice(index, 1);});return result;
};

复杂度分析

  • 时间复杂度:O(nlogn)O(nlogn) 代码中 sort 函数的时间复杂度为 O(nlogn)O(nlogn),for 循环的时间复杂度为 O(n)O(n),因此整体的时间复杂度为 O(nlogn)O(nlogn)。
  • 空间复杂度:O(n)O(n) 申请了 2 个大小为 n 的数组空间,因此空间复杂度为 O(n)O(n)。

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

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

相关文章

前端工程化详解

目录 开发前1.使用脚手架工具2.使用编译工具 开发中1.代码规范2.公共方法抽离3.公共组件抽离4.公共样式抽离5.icon 图片 国际化文案 常量等静态数据规划管理6.业务模块区分7.项目版本管理工具8.开发IDE以及代码检查工具 开发结束1.单元测试2.项目打包3.项目发布 开发前 1.使用…

低代码信创开发核心技术(四)动态元数据系统设计

一、概述 在当今快速发展的信息技术领域&#xff0c;动态元数据系统扮演着至关重要的角色。它不仅能够提供数据的描述信息&#xff0c;还能动态地适应业务需求的变化&#xff0c;从而提高系统的灵活性和可扩展性。构建一个动态元数据系统意味着我们可以在不重启系统的情况下&a…

【机器学习】机器学习学习笔记 - 监督学习 - KNN线性回归岭回归 - 02

监督学习 KNN (k-nearest neighbors) KNN 是用 k 个最近邻的训练数据集来寻找未知对象分类的一种算法 from sklearn import neighbors# 分类 # 创建KNN分类器模型并进行训练 classifier neighbors.KNeighborsClassifier(num_neighbors, weightsdistance) classifier.fit(X,…

前端面试题合集

1.对前端监控的理解&#xff1f; 异常监控&#xff08;监控前端页面的报错&#xff09;> try / catch 、window.onerror、window.addEventListener、Vue.config.errorHandle JS 代码运行错误、语法错误等&#xff1b;AJAX 请求错误&#xff1b;静态资源加载错误&#xff1…

硬件21、接线端子XH2.54、2.54排针排母、2510接插件、PH2.0、町洋接线端子5.08、ISP接口JTAG插座

XH2.54端子的间距为2.54毫米&#xff0c;2.54排针排母的间距也是2.54mm&#xff0c;2510接插件也是2.54、而PH2.0端子的间距为2.0毫米&#xff0c;町洋接线端子插针间的距离是5.08mm&#xff0c;ISP接口JTAG插座针脚的间距一般也是2.54mm XH2.54 针脚间距为2.54mm 插头 接线…

如何使用 Internet Download Manager (IDM) 来加速和优化你的下载体验 IDM 6.41下载神器

在当今信息爆炸的时代&#xff0c;下载文件和媒体内容已成为我们日常生活的一部分。无论是工作学习还是娱乐休闲&#xff0c;我们都需要从互联网上下载各种资源。为了提高下载效率和确保文件完整性&#xff0c;选择一款优秀的下载管理软件至关重要。Internet Download Manager …

浅谈游戏机制

浅谈游戏机制 前言什么是游戏机制&#xff1f;机制组成机制类别结语 前言 最近在编写游戏开发文档的时候了解到游戏机制&#xff0c;第一次接触游戏机制的概念难免有些陌生&#xff0c;但感觉又跟常见&#xff0c;在网上查阅浏览了一些资料后了解到游戏机制还不止一个。 现在将…

vue echarts 柱状图 堆叠柱状图

echarts堆叠柱状图&#xff08;效果图在文章末尾&#xff09; 1、默认只显示 月度的 数据&#xff0c;手动点击 legend 季度的 数据才会显示&#xff1b; 2、监听左侧菜单栏的宽度变化&#xff0c;图表宽度自适应展示 <template><div><div id"barChart&q…

优雅实现uniapp返回上一页传参

在移动端应用中&#xff0c;表单设置组件往往作为独立的页面层级存在&#xff0c;以实现如时间选择等复杂功能。当用户在该组件页面内选定特定时间后&#xff0c;如何将这一选择结果高效、有序地传递回原页面&#xff0c;成为一个颇具挑战性的任务。尽管可以借助Vuex进行全局状…

构建数字化银行:现代化总架构探究

随着科技的迅速发展和用户需求的不断变化&#xff0c;传统银行业正迎来一场数字化转型的浪潮。在这个数字化时代&#xff0c;银行需要构建现代化的总架构&#xff0c;以适应快速变化的市场环境和客户需求。本文将深入探讨数字化银行的总架构设计理念、关键技术以及实践经验&…

【Python】使用 argparse 来加载yml文件的内容 - 2

继续上一节&#xff1a;【Python】YAML&#xff08;.yml&#xff09;文件简介以及python示例 - 1 使用 argparse 模块来读取 .yml 文件并不是直接由 argparse 完成的&#xff0c;但可以使用 argparse 来处理命令行参数&#xff0c;使得用户能够指定 .yml 配置文件的路径&#…

乘数而上,创邻科技入选2024数商典型应用场景“乘数榜”

4月18日&#xff0c;由浙江省科学技术协会指导的2024未来数商大会在杭州成功举办。本次大会以“场景突破 乘数而上”为主题&#xff0c;国际国内数商共聚未来科技城学术交流中心&#xff0c;聚焦数据要素市场的制度创新、数据治理、场景应用与生态构建等话题展开研讨。 大会现…

软件需求管理规程(Word原件2024)

软件开发人员及用户往往容易忽略信息沟通&#xff0c;这导致软件开发出来后不能很好地满足用户的需要&#xff0c;从而造成返工。而返工不仅在技术上给开发人员带来巨大的麻烦&#xff0c;造成人力、物力的浪费&#xff0c;而且软件的性能也深受影响。所以在软件项目开发周期的…

村集体建设用地,开发乡村旅游项目,土地如何审批?

以村集体建设用地,开发乡村旅游项目,土地如何审批? 乡村&#xff0c;作为承载乡村旅游产业的载体&#xff0c;在乡村振兴中扮演着非常重要的角色。 项目的落地&#xff0c;可靠的土地是必要的前提。集体建设用地如何审批&#xff1f;农转非又需要什么样的流程&#xff0c;具体…

StarRocks x Paimon 构建极速实时湖仓分析架构实践

Paimon 介绍 Apache Paimon 是新一代的湖格式&#xff0c;可以使用 Flink 和 Spark 构建实时 Lakehouse 架构&#xff0c;以进行流式处理和批处理操作。Paimon 创新性地使用 LSM&#xff08;日志结构合并树&#xff09;结构&#xff0c;将实时流式更新引入 Lakehouse 架构中。 …

什么ISP是住宅IP,和普通IP有什么区别?

ISP&#xff08;Internet Service Provider&#xff09;即互联网服务提供商&#xff0c;是向广大用户综合提供互联网接入业务、信息业务和增值业务的电信运营商。住宅IP&#xff0c;也称为家庭IP&#xff0c;是指由ISP分配给家庭或个人用户的IP地址。这些IP地址是真实的&#x…

Kotlin基础​​

数据类型 定义变量 var表示定义变量&#xff0c;可以自动推导变量类型&#xff0c;所以Int可以不用写。 定义常量 条件语句 if表达式可以返回值&#xff0c;该值一般写在if里的最后一行 类似switch的用法 区间 循环 a是标签&#xff0c;可以直接break到标签的位置&#xf…

【JVM】从i++到JVM栈帧

【JVM】从i到JVM栈帧 本篇博客将用两个代码例子&#xff0c;简单认识一下JVM与栈帧结构以及其作用 从i与i说起 先不急着看i和i&#xff0c;我们来看看JVM虚拟机&#xff08;请看VCR.JPG&#xff09; 我们初学JAVA的时候一定都听到过JAVA“跨平台”的特性&#xff0c;也就是…

18 JavaScript学习:错误

JavaScript错误 JavaScript错误通常指的是在编写JavaScript代码时发生的错误。这些错误可能是语法错误、运行时错误或逻辑错误。以下是对这些错误的一些常见分类和解释&#xff1a; 语法错误&#xff1a; 这类错误发生在代码编写阶段&#xff0c;通常是由于代码不符合JavaScrip…

Linux常用指令001

实验案例 创建一个和你名字同名的用户 在当前目录下创建名称为 1212的目录 进入到 1212 目录中 创建 a~d 目录 创建 1~10.txt 文件&#xff0c;如下 备份 创建一个和 1212 同一级目录的新目录 1313 将所有的文件和目录备份到 1313 目录中 在 1313目录中&#xff0c;查看…