算法——分治

思想:分而治之,将大问题转化为若干个相同或相似的子问题。快排的题目常见的方法是利用三指针法将数组分三块搭配随机选择基准元素的思想
image.png

颜色分类(分治_快排

颜色分类

题目解析

  1. 原地对它们进行排序,使得相同颜色的元素相邻,并按照红色、白色、蓝色顺序排列。
  2. 我们使用整数 0、 1 和 2 分别表示红色、白色和蓝色。
  3. 必须在不使用库内置的 sort 函数的情况下解决这个问题。

算法原理

  • 解法:三指针(数组分三块)
    • 将数组划分为三个区域,一部分区域全是0,一部分全是1,一部分全是2.定义i指针,用来扫描整个数组;left指针标记0区域的最右侧,right标记2区域的最左侧。image.png
    • 区间划分好,接下来我们就分类讨论每个区间应该怎么处理后,就可以写代码了。
    • 当i位置是0的情况:
      • 要把该元素加入左边的区间里,即加到left+1的位置。left+1这个位置是1,让i和left+1交换位置,然后让i++外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
      • 还有一种情况,当i的值等于left+1,即i此时所指的位置也是0,但是i是在left的后面,此时我们依旧要执行交换操作,执行交换操作的依然是left+1的位置和i的位置,但是相当于是自己和自己交换。交换完之后依旧要让left++,i++image.png
    • 当i位置是1的情况:要保证让1全部在left+1和i-1的区间内,所以让i++即可。
    • 当i位置是2的情况:此时我们要把他加入到right-1的位置,因为我们要把它加入到right最右边的区域的话,相当于是把他加入到right-1的区域。所以要i和right-1位置交换。并且要让right–。在交换完之前[i,right-1]这个区间全是待扫描的元素。当交换完之后,此时i所指的位置依旧是带扫描的元素,所以i不能++image.png
  • 当i和right相遇之后,此时没有待扫描的元素,此时停止循环。

下面模拟一下流程

  1. i所指元素是2,执行第三种情况,让i所指的元素和right-1位置的元素0交换,然后i不动,right–。

image.png

  1. 此时i指的元素是0,和left+1的位置(其实还是i所指的)元素0交换(那自己和自己交换就不动啦嘻嘻)。交换完之后让i++。left也++。交换完之后咱就发现目前而言左边区域就全是0.

image.png

3.然后i所指的元素是0,将left+1位置元素和他交换(还是自己和自己交换),交换完之后i++、left++
image.pngimage.png

  1. 接下来,i所指的元素是2,和right+1位置交换,交换完right–,i不动image.png
  2. 当i是1,很简单直接++

image.png

当i与right相遇停止循环。

代码实现

class Solution {
public:void sortColors(vector<int>& nums) {int n = nums.size();int left = -1, right = n, i = 0;while(i < right){if(nums[i] == 0) swap(nums[++left], nums[i++]);else if(nums[i] == 1) i++;else swap(nums[--right], nums[i]);}}
};

排序数组(分治_快排

排序数组

题目解析

用数组划分的思想实现快排从而解决这个问题

算法原理

  • 解法:快速排序:
    1. 普通版本:选择一个基准元素k,将原数组分成两部分,一部分小于等于k,另一部分全部大于k(这一步数据划分是关键,称为partation),此时选择的基准所在的位置就是排序之后所在的位置,此时只需要排序基准元素左右两边的数字即可;然后再选择一个基准元素,如此循环。但有一种极端情况,是数组元素全部重复的时候,时间复杂度就会退化为O(n2)image.png
    2. 数组分三块思想:时间复杂度O(n)
      1. 分三类情况讨论
        1. 当nums[i] < k,把当前位置元素加到左边的区域,执行交换操作,与left+1位置交换,然后left++,i也++
        2. 当nums[i] = k,i++
        3. 当nums[i] > k,交换nums,–rightimage.png
    3. 优化:用随机的方式选择基准元素,时间复杂度渐近到O(nlogn)
      1. 给定一个数组,一个左区间,一个右区间,要等概率的返回这个区间上的任意一个数。所以我们用随机数的方式选择基准元素。偏移量:r%(right-left+1)取值就是[0,n-1]。此时再让left加上偏移量就映射到这个区间随缘选一个点。image.png

代码实现

class Solution {
public:vector<int> sortArray(vector<int>& nums) {srand(time(NULL)); // 种下⼀个随机数种⼦qsort(nums, 0, nums.size() - 1);return nums;}// 快排void qsort(vector<int>& nums, int l, int r){if(l >= r) return;// 数组分三块int key = getRandom(nums, l, r);int i = l, left = l - 1, right = r + 1;while(i < right){if(nums[i] < key) swap(nums[++left], nums[i++]);else if(nums[i] == key) i++;else swap(nums[--right], nums[i]);}// [l, left] [left + 1, right - 1] [right, r]qsort(nums, l, left);qsort(nums, right, r);}int getRandom(vector<int>& nums, int left, int right){int r = rand();return nums[r % (right - left + 1) + left];}
};

数组中第k个最大元素(分治_快排)

数组中第k的最大元素

题目解析

本题是我们之前写过的TOP—K问题,共有四种问法:第K大、第K小、前K大、前K小。解决此问题有两种方法:一种是堆排序,时间复杂度O(nlogn);另一种就是这次的快速选择算法,时间复杂度O(n)。

  • 需要找的是数组排序后的第 k 个最大的元素

  • 设计并实现时间复杂度为 O(n) 的算法

算法原理

该算法是基于快排改良的
数组分三块+随机选择基准元素:

  1. 在l和r区间(区间两个端点),随机选择一个基准元素k,将区间分为三部分:<k =k >k。因为题目要求找出第k大元素,所以当我们可以确定处于上面三部分中的其中一部分时,另外两部分就不用考虑,这样就提高了效率。
  2. 我们设在<k的区间里有a个数,=k区间里有b个数,>k区间里有c个数,此时分三种情况讨论。因为题目中说了数组已经排过序,所以按照常理我们从>k区间里先去找,概率大一点。
    1. 落在 >key 区间的判断条件为:c>=k,因为题中要第k大的元素,这个区间里都是较大的数,当k小于等于c时,该数字一定在这个区间里。
    2. 落在 =key区间的判断条件:b+c>=k,这里我们约定如果在b情况,那么a情况绝对不成立。此时k>=c(范围为蓝色箭头所指),所以,那么>key区间里的数就会符合题意,直接返回key
    3. 当前两种情况都不成立时。说明k很大(范围为红色箭头所指),后两部分区间(里面存的都是较大的数)已经找了b+c个,所以还需要在<key区间里找第k-b-c大的数

image.png

代码实现

class Solution {
public:int findKthLargest(vector<int>& nums, int k){srand(time(NULL));return qsort(nums, 0, nums.size() - 1, k);}int qsort(vector<int>& nums, int l, int r, int k){if(l == r) return nums[l];// 1. 随机选择基准元素int key = getRandom(nums, l, r);// 2. 根据基准元素将数组分三块int left = l - 1, right = r + 1, i = l;while(i < right){if(nums[i] < key) swap(nums[++left], nums[i++]);else if(nums[i] == key) i++;else swap(nums[--right], nums[i]);}// 3. 分情况讨论int c = r - right + 1, b = right - left - 1;if(c >= k) return qsort(nums, right, r, k);else if(b + c >= k) return key;else return qsort(nums, l, left, k - b - c);}int getRandom(vector<int>& nums, int left, int right){return nums[rand() % (right - left + 1) + left];}
};

最小的K个数(分治_快排)

最小的k个数——库存管理III

题目解析

输入整数数组 arr ,找出其中最小的 个数。例如,输入4、5、1、6、2、7、3、8这8个数字,则最小的4个数字是1、2、3、4。

算法原理

  1. 解法一:排序:直接调用容器排序数组。然后把最小的k个数字摘出来。时间复杂度O(nlogn)
  2. 解法二:堆:创建一个大小为k的大根堆,存储的上限设为k,把所有的数依次丢入到大根堆里,最后堆里剩下的k个数就是最小的k个数.时间复杂度O(nlogk)
  3. 解法三:快速选择.随机选择基准元素+数组分三块。时间复杂度O(n)
    1. 题中要求第k小,所以从最左边的区间先开始分析。落在最左边区间的条件为a>k,再[l,left]区间里找
    2. (第一种情况不成立后再判断第二种)。落在=key区间的条件为a+b>=k,因为此时我们默认第一种情况不成立,说明此时k>=a,我们就在图中红线的区间里找,无论落在哪里,<key区间里的数就是符合题意的,直接返回
    3. (此时前两种情况不成立)说明k很大,此时区间在蓝色箭头所指的范围里已经找a+b个小的数,还要去>key区间里找最小的k-a-b小的数

image.png
快速选择算法仅仅是把最小的k个数丢到了前面,并没有把前面几个数字排序
这个算法是在递归的过程中直接去对应符合条件的区间里找数字,而不是去区间里排序。所以快速选择算法比快排更快。并且在《算法导论》里有证明,当我们用随机选择基准元素的方法时,我们的三个区间都是等概率划分的,此时他的时间复杂度会逼近与O(N)。

代码实现

class Solution {
public:vector<int> inventoryManagement(vector<int>& stock, int cnt) {srand(time(NULL));qsort(stock, 0, stock.size() - 1, cnt);//这里是快速选择,不是排序,所以我们只需要返回前k个数就行,里面是无序的return {stock.begin(), stock.begin() + cnt};}void qsort(vector<int>& stock, int l, int r, int cnt){if(l >= r) return;// 1. 随机选择⼀个基准元素 + 数组分三块int key = getRandom(stock, l, r);int left = l - 1, right = r + 1, i = l;while(i < right){if(stock[i] < key) swap(stock[++left], stock[i++]);else if(stock[i] == key) i++;else swap(stock[--right], stock[i]);}// [l, left][left + 1, right - 1] [right, r]
// 2. 分情况讨论int a = left - l + 1, b = right - left - 1;if(a > cnt) qsort(stock, l, left, cnt);else if(a + b >= cnt) return;else qsort(stock, right, r, cnt - a - b);}int getRandom(vector<int>& stock, int l, int r){return stock[rand() % (r - l + 1) + l];}
};

排序数组(分治_归并)

排序数组

题目解析

整数数组 nums,请你将该数组升序排列。

归并算法回顾

用归并算法给数组排序,首先先选择mid中间点,先把左边部分排序,排左边的时候相当于又是一个归并排序的过程,直至只剩下一个元素的时候,向上返回,排右边区间,直至剩下一个元素时,开始向上返回,当这一层都排完时,合并两个有序数组。相当于二叉树中的后序遍历,快排的过程是先把数组分两块,然后把左边继续用一个key值分成左右两部分。相当于前序遍历

合并有序数组时需要创建辅助数组
image.png

代码实现

class Solution {vector<int>tmp; //节省时间消耗
public:vector<int> sortArray(vector<int>& nums) {tmp.resize(nums.size());  //在归并前更改大小srand(time(NULL)); // 种下⼀个随机数种⼦mergeSort(nums, 0, nums.size() - 1);return nums;}void mergeSort(vector<int>& nums, int left, int right){if(left >= right) return;// 1. 选择中间点划分区间int mid = (left + right) >> 1;// [left, mid] [mid + 1, right]// 2. 把左右区间排序mergeSort(nums, left, mid);mergeSort(nums, mid + 1, right);// 3. 合并两个有序数组int cur1 = left, cur2 = mid + 1, i = 0;while(cur1 <= mid && cur2 <= right)tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur1++] : nums[cur2++];// 处理没有遍历完的数组while(cur1 <= mid) tmp[i++] = nums[cur1++];while(cur2 <= right) tmp[i++] = nums[cur2++];// 4. 还原for(int i = left; i <= right; i++)nums[i] = tmp[i - left];}
};

数组中的逆序对

数组中的逆序对

题目解析

逆序对:前面的数大于后面的数 image.png

算法原理

  1. 暴力枚举:把所有的二元组列举出来,判断是不是逆序对。先固定其中一个数,在这个数的后面的区间找找有几个比他小的数。两层for循环。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

  1. 左半部分->右半部分->一左一右:将数组从中间劈成两部分,求整个数组的逆序对的时候,先去求左边部分有a个逆序对,右边部分有b个逆序对。也就是说求a的时候不看b。接着分别在左区间挑一个,右区间挑一个;一左一右统计有c个逆序对,这样本质其实和遍历一样。最终a+b+b就是最终个数image.png
  2. **左半部分->左排序->右半部分->右排序->一左一右+排序:**这个与2相比,只是在一左一右的时候有些不同。在左边选完一个数后,只需要看右边区间有没有比这个数小就行。(+排序是为了和前半部分+排序保持一致,因为归并的子过程要相同)

image.png

  1. **利用归并排序解决:**先去搞左半部分有多少逆序对,如果数组很大,继续拆,…这个过程非常类似我们的归并过程。所以上面两种策略刚好对应递归排序。(我们这里只需要搞定一左一右+排序,因为左半部分+排序和右半部分+排序可以在递归中完成)。我们只需要算出一左一右有多少逆序对就行。此时数组升序。时间复杂度O(NlogN)

image.png


  • 策略一:找出该数之前有多少个比我大的数字

这时候在cur1之前的数都是比它小的,所以cur1之前的数就会比cur2之前的数字小,(因为cur1比cur2位置的数字小,cur1会先归并到辅助数组中)。我们找逆序对是在找到比我大的数之前,有多少数字能和我组成逆序对。所以我们分情况讨论:

  1. 当cur1[num] <= cur2[num]:说明此时还没有比cur2位置上大的数,就继续找,直到找到cur1位置大于cur2位置的数,所以让cur1++(本质上是先把cur1位置的数放到辅助数组里面,然后让cur1++)

  2. 当cur1[num] > cur2[num]:此时cur1后面的数全都比cur2大。我们就根据归并排序的以此比较,就找出了一堆比cur2大的数,此时我们用ret+=mid-cur1+1 记录cur1后面有多少个数字。并且让cur2++image.png

  3. 处理细节问题:如果数组降序,可以怎样处理呢

    1. 先选大的数归并到辅助数组里面,此时cur1和cur2左边的数都是比他们各自大 。
    2. 当cur1[num] > cur2[num]:此时统计一下cur1左边数字的个数,然后让cur1++,但此时会面临一个问题,如果cur1往后移动的数字依然比cur2大,此时再统计个数就重复统计了。因此策略1只能降序数组。

  • **策略2:找出该数之后有多少个比我小 ** 该策略只能用降序(因为升序也会重复统计)
    • 当升序时,此时我们固定nuns1,让较大的指针cur2放入辅助数组里外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传
    • 数组降序,此时各自左边部分的数字都比cur1和cur2大(cur2左边部分的数比cur1大)。当cur1的位置数比cur2大时,说明是cur1第一次比cur2大,此时比cur2后面的区间全都大.统计个数image.png

代码实现

class Solution {int tmp[50010];
public:int reversePairs(vector<int>& nums){return mergeSort(nums, 0, nums.size() - 1);}int mergeSort(vector<int>& nums, int left, int right){if(left >= right) return 0;int ret = 0;// 1. 找中间点,将数组分成两部分int mid = (left + right) >> 1;// [left, mid][mid + 1, right]// 2. 左边的个数 + 排序 + 右边的个数 + 排序ret += mergeSort(nums, left, mid);ret += mergeSort(nums, mid + 1, right);// 3. ⼀左⼀右的个数int cur1 = left, cur2 = mid + 1, i = 0;while(cur1 <= mid && cur2 <= right) // 升序的时候{if(nums[cur1] <= nums[cur2]){tmp[i++] = nums[cur1++];}else{ret += mid - cur1 + 1;tmp[i++] = nums[cur2++];}}// 4. 处理⼀下排序while(cur1 <= mid) tmp[i++] = nums[cur1++];while(cur2 <= right) tmp[i++] = nums[cur2++];for(int j = left; j <= right; j++)nums[j] = tmp[j - left];return ret;}
};
class Solution
{int tmp[50010];
public:int reversePairs(vector<int>& nums){return mergeSort(nums, 0, nums.size() - 1);}int mergeSort(vector<int>& nums, int left, int right){if(left >= right) return 0;int ret = 0;// 1. 找中间点,将数组分成两部分int mid = (left + right) >> 1;// [left, mid][mid + 1, right]// 2. 左边的个数 + 排序 + 右边的个数 + 排序ret += mergeSort(nums, left, mid);ret += mergeSort(nums, mid + 1, right);// 3. ⼀左⼀右的个数int cur1 = left, cur2 = mid + 1, i = 0;while(cur1 <= mid && cur2 <= right) // 降序的版本{if(nums[cur1] <= nums[cur2]){tmp[i++] = nums[cur2++];}else{ret += right - cur2 + 1;tmp[i++] = nums[cur1++];}}// 4. 处理⼀下排序while(cur1 <= mid) tmp[i++] = nums[cur1++];while(cur2 <= right) tmp[i++] = nums[cur2++];for(int j = left; j <= right; j++)nums[j] = tmp[j - left];return ret;}
};

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

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

题目解析

  • 返回的新数组要与原数组同等规模。
  • 返回该位置之后比他小的数字的个数

image.png

算法原理

归并排序(分治):因为要找比该位置小的数,所以我们可以用上到题的策略二——当前元素后面有多少个比我小的数。数组降序

  • 将数组劈成两部分,先将左边的结果找到,再将右边的结果找到。快速找到某一个位置之后比他小的数,就盯着cur1.此时开始讨论:
    • 当nums[cur1] <= nums[cur2]:此时没找到比cur1小的,那么让cur2++,继续向后移动
    • 当nums[cur1] > nums[cur2]:此时cur1比cur2右边部分的数字都大,此时要记录个数不能用ret记录,而是cur1对应的位置里面的ret(因为返回是通过数组形式)image.png
  • 那么问题来了,如何找nums元素对应的原始下标是多少呢?因为我们将原数组分治完之后排序了,所以此时下标已经乱了,当前位置的cur1并不是真实下标。
    • 我们可以搞一个index数组,专门记录nums数组当前位置元素的原始下标。然后无论nums数组中的元素怎么变,我们让他绑定移动
    • 我们一共要搞两个辅助数组tmp,一个是合并nums两个有序数组,另一个绑定

image.png

代码实现

class Solution 
{vector<int> ret;vector<int> index; // 记录 nums 中当前元素的原始下标int tmpNums[500010];int tmpIndex[500010];
public:vector<int> countSmaller(vector<int>& nums){int n = nums.size();ret.resize(n);index.resize(n);// 初始化⼀下 index 数组for(int i = 0; i < n; i++)index[i] = i;mergeSort(nums, 0, n - 1);return ret;}void mergeSort(vector<int>& nums, int left, int right)
{if(left >= right) return;
// 1. 根据中间元素,划分区间int mid = (left + right) >> 1;// [left, mid] [mid + 1, right]
// 2. 先处理左右两部分mergeSort(nums, left, mid);mergeSort(nums, mid + 1, right);// 3. 处理⼀左⼀右的情况int cur1 = left, cur2 = mid + 1, i = 0;while(cur1 <= mid && cur2 <= right) // 降序{if(nums[cur1] <= nums[cur2]){tmpNums[i] = nums[cur2];tmpIndex[i++] = index[cur2++];}else{   ret[index[cur1]] += right - cur2 + 1; // 重点 +会覆盖,所以要+=tmpNums[i] = nums[cur1];tmpIndex[i++] = index[cur1++];}}// 4. 处理剩下的排序过程while(cur1 <= mid){tmpNums[i] = nums[cur1];tmpIndex[i++] = index[cur1++];}while(cur2 <= right){tmpNums[i] = nums[cur2];tmpIndex[i++] = index[cur2++];}for(int j = left; j <= right; j++){nums[j] = tmpNums[j - left];index[j] = tmpIndex[j - left];}
}
};

翻转对

翻转对

题目解析

找两个数,使前面的数大于后面的数2倍
image.png

算法原理

分治: 将整个数组分治为两部分,求出左半部分翻转对数a,右半部分翻转对数为b,一左一右翻转对数为c,最后a+b+c即为所求。但有些细节问题

  1. 该题比较条件是前面的数大于后面的数二倍,此时就不能按照归并排序的流程进行。所以我们要在归并排序之前进行翻转对。利用两个数组有序的性质。我们可以在一次归并中用O(N)的时间复杂度搞定该层的翻转对的个数(利用单调性,使用同向双指针)image.png
    1. 策略一:计算当前元素后面有多少个比两倍还小的数,降序排列
      1. cur1不动,如果cur2当前所指的元素比cur1两倍还大,往后移。直到找到第一个比cur1两倍还小的(因为数组降序),记ret+=right-cur2+1
      2. 之后移动cur1时,不要让cur2回滚到之前的位置否则时间复杂度为O(n^2logn)。让cur2在第一个找到的比cur1小的位置继续往后移动即可。直到cur1移动到最后结束image.png
    2. 策略二:计算当前元素之前有多少个元素的一半比我大,升序排列
      1. cur2不动,如过当前cur2的位置比cur1位置的一半还要小,cur1右移。直到出现比cur1位置一半大的,记ret+=mid-cur1+1.然后cur2++,cur1同理只需要在当前位置向后移动即可,不需要会退到第一个位置。直到cur2移动到最后结束。image.png
  2. 合并两个有序数组

代码实现

class Solution 
{int tmp[50010];
public:int reversePairs(vector<int>& nums){return mergeSort(nums, 0, nums.size() - 1);}int mergeSort(vector<int>& nums, int left, int right){if(left >= right) return 0;int ret = 0;// 1. 先根据中间元素划分区间int mid = (left + right) >> 1;// [left, mid] [mid + 1, right]// 2. 先计算左右两侧的翻转对ret += mergeSort(nums, left, mid);ret += mergeSort(nums, mid + 1, right);// 3. 先计算翻转对的数量int cur1 = left, cur2 = mid + 1, i = left;while(cur1 <= mid) // 降序的情况{while(cur2 <= right && nums[cur2] >= nums[cur1] / 2.0) cur2++;if(cur2 > right)break;ret += right - cur2 + 1;cur1++;}// 4. 合并两个有序数组cur1 = left, cur2 = mid + 1;while(cur1 <= mid && cur2 <= right)tmp[i++] = nums[cur1] <= nums[cur2] ? nums[cur2++] : nums[cur1++];while(cur1 <= mid) tmp[i++] = nums[cur1++];while(cur2 <= right) tmp[i++] = nums[cur2++];for(int j = left; j <= right; j++)nums[j] = tmp[j];return ret;
}
};

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

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

相关文章

Oracle-应用会话集中在RAC集群一个节点问题

问题&#xff1a; 用户一套Oracle19c RAC集群&#xff0c;出现一个奇怪的现象&#xff0c;通过SCAN IP访问的连接会话都集中在节点一实例&#xff0c;而且用户并没有做任何的节点服务访问去控制会话的连接节点&#xff0c;比如常见的通过集群的高可用服务去控制应用访问连接集中…

Spring IOC—基于注解配置和管理Bean 万字详解(通俗易懂)

目录 一、前言 二、基于注解配置Bean 1.基本介绍 : 2.应用实例 : 3.注意事项 : 三、手动实现Spring 注解配置机制 1.需求 : 2.思路 : 3.实现 : 3.1 自定义注解类 3.2 自定义配置类 3.3 自定义容器类 3.4 在测试类中进行测试 四、自动装配 0.总述 : 1.AutoWired自动装…

LeetCode力扣每日一题(Java):69、x 的平方根

一、题目 二、解题思路 1、 我的思路 我的思路是直接循环暴力破解&#xff0c;定义计数器i&#xff0c;从1开始递增&#xff0c;直到i*i大于或等于x 于是有了如下代码 int i 1;while(true){if(i*i<x){i;}else if(i*ix){return i;}else{return i-1;}} 但提交之后超出了…

亚马逊、target、eBay、沃尔玛等平台采退、下卡,技术技巧大揭秘

今天想和大家分享一些关于做测评、采退和撸卡项目时所需的防关联和防封号环境的底层技术原理。这些内容相对比较复杂&#xff0c;相信很少有人能够完全掌握&#xff0c;因为涉及到一些比较高级的IT技术原理。 如果正在考虑开始做采退或者撸卡项目&#xff0c;或者已经在进行相…

libxls - 编译

文章目录 libxls - 编译概述笔记静态库工程测试控制台exe工程测试备注备注END libxls - 编译 概述 想处理.xls格式的excel文件. 查了一下libxls库可以干这个事. 库地址 https://github.com/libxls/libxls.git 但是这个库的makefile写的有问题, 在mingw和WSL下都编译不了. 好在…

高德地图绘制区域的地理围栏

官网示例 https://lbs.amap.com/demo/javascript-api-v2/example/overlayers/polygon-draw/ <!doctype html> <html> <head><meta charset"utf-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta …

黑马点评06分布式锁 2Redisson

实战篇-17.分布式锁-Redisson功能介绍_哔哩哔哩_bilibili 1.还存在的问题 直接实现很麻烦&#xff0c;借鉴已有的框架。 2.Redisson用法 3.Redisson可重入原理 在获取锁的时候&#xff0c;看看申请的线程和拿锁的线程是否一致&#xff0c;然后计算该线程获取锁的次数。一个方法…

爬虫chrome浏览器抓包说明

chrome浏览器抓包说明 目标&#xff1a;掌握chrome在爬虫中的使用 1. 新建隐身窗口&#xff08;无痕窗口&#xff09; 作用&#xff1a;在打开无痕窗口的时候&#xff0c;第一次请求某个网站是没有携带cookie的&#xff0c;和代码请求一个网站一样&#xff0c;这样就能够尽可…

堆与二叉树(上)

本篇主要讲的是一些概念&#xff0c;推论和堆的实现&#xff08;核心在堆的实现这一块&#xff09; 涉及到的一些结论&#xff0c;证明放到最后&#xff0c;可以选择跳过&#xff0c;知识点过多&#xff0c;当复习一用差不多&#xff0c;如果是刚学这一块的&#xff0c;建议打…

爬虫练习-获取imooc课程目录

代码&#xff1a; from bs4 import BeautifulSoup import requests headers{ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:94.0) Gecko/20100101 Firefox/94.0, }id371 #课程id htmlrequests.get(https://coding.imooc.com/class/chapter/id.html#Anchor,head…

实验三 MapReduce编程

实验目的&#xff1a; 1.掌握MapReduce的基本编程流程&#xff1b; 2.掌握MapReduce序列化的使用&#xff1b; 实验内容&#xff1a; 一、在本地创建名为MapReduceTest的Maven工程&#xff0c;在pom.xml中引入相关依赖包&#xff0c;配置log4j.properties文件&#xff0c;搭…

软信天成:产品信息管理(PIM)对零售行业有何意义?

产品信息管理&#xff08;PIM&#xff09;&#xff0c;通过快速收集、管理和共享横跨整个企业、合作伙伴和供应商的产品信息&#xff0c;整合分散在不同系统或部门的数据信息&#xff0c;创建实时、可信的产品数据源&#xff0c;及时获取整个企业详细、准确和一致的产品信息&am…

前端做表格导出

下面来介绍一下方法 在vue页面里写调用方法 //表头数据格式 column: [{ key: Photo, width: 70, height: 50, colWidth: 100, title: 图片, type: image },{ key: Name, colWidth: , title: 名称, type: text },{ key: Phone, colWidth: , title: 手机号, type: text },{key:…

使用Log4j与log4j2配置mybatisplus打印sql日志

环境&#xff1a;项目非完全spring项目&#xff0c;没有spring的配置文件。执行sql时老是不打印sql语句。因此进行修改&#xff0c;过程比较坎坷&#xff0c;记录一下。 我尝试使用log4j和log4j2进行配置 最终把这两种全部配置记录上 Log4j配置 如果项目用的是log4j需要进行配置…

【✅如何针对大Excel做文件读取?】

✅如何针对大Excel做文件读取&#xff1f; &#x1f7e9;如何针对大Excel做文件读取&#x1f7e9;XSSFWorkbook文件读取&#x1f7e9;EasyExcel文件读取 ✅扩展知识&#x1f7e9; EasyExcel简介&#x1f7e9;EasyExcel 为什么内存占用小&#xff1f; &#x1f7e9;如何针对大Ex…

欧盟健身单车出口BS EN ISO 20957安全报告测试

固定的训练器材.第10部分:带固定轮或无自由飞轮的训练自行车.附加特定安全要求和试验方法 作为欧洲固定式健身器材&#xff08;儿童用固定式健身器材不在此范围&#xff09;通用安全要求和测试方法的标准&#xff0c;涉及固定式健身器材精度、使用场所分类定义、稳定性、安全间…

Amazon CodeWhisperer 体验

文章作者&#xff1a;jiangbei 1. CodeWhisperer 安装 1.1 先安装 IDEA&#xff0c;如下图&#xff0c;IDEA2022 安装为例&#xff1a; 亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、活动与竞赛等。帮助中国开发者…

我的创作纪念日-IT从业者张某某

机缘 勿忘初心&#xff0c;牢记使命&#xff0c;我成为创作者的初心是什么呢&#xff1f;时间有些久了&#xff0c;回头看下自己的第一篇博客&#xff0c;还是略显青涩的&#xff0c;有种不忍直视的感觉。 我的第一篇博客&#xff0c;应该是想记录下工作中的一个演示项目&…

[Bond的杂货铺] CERTIFIED KUBERNETES ADMINISTRATOR 到货咯

Its been a long time. Mr. K8s. 既然接触了这么多年&#xff0c;2018年在1.11版就认识了&#xff0c;如今都到了1.28&#xff0c;拖到连与docker都分手了。所以&#xff0c;考一个&#xff0c;很合理吧。 分数是88&#xff0c;隐约感觉是因为有几处因为实在不想把光标移来移…

挑战内网安全难题,迅软DSE如何以管控之力助您一臂之力?

随着信息化程度的提高&#xff0c;政企单位面临更加复杂和不可控的内网安全问题。由于缺乏有效技术手段和完善的管理机制&#xff0c;企业内网管理长期处于被动状态&#xff0c;而在发生数据安全事件后的快速处置能力也相对薄弱。 迅软DSE桌面管理系统成为解决方案&#xff0c…