【数据结构-堆】堆

news2025/3/14 11:08:11

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。
img

  • 推荐:kuan 的首页,持续学习,不断总结,共同进步,活到老学到老
  • 导航
    • 檀越剑指大厂系列:全面总结 java 核心技术点,如集合,jvm,并发编程 redis,kafka,Spring,微服务,Netty 等
    • 常用开发工具系列:罗列常用的开发工具,如 IDEA,Mac,Alfred,electerm,Git,typora,apifox 等
    • 数据库系列:详细总结了常用数据库 mysql 技术点,以及工作中遇到的 mysql 问题等
    • 懒人运维系列:总结好用的命令,解放双手不香吗?能用一个命令完成绝不用两个操作
    • 数据结构与算法系列:总结数据结构和算法,不同类型针对性训练,提升编程思维,剑指大厂

非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨

博客目录

    • 一.堆简介
      • 1.什么是堆?
      • 2.大顶堆
      • 3.小顶堆
      • 4.JDK 的优先队列
      • 5.建堆
    • 二.堆题目
      • 1.堆排序
      • 2.数组中第 K 大元素-力扣 215 题
      • 3.数据流中第 K 大元素-力扣 703 题
      • 4.数据流的中位数-力扣 295 题

一.堆简介

1.什么是堆?

堆(Heap)是一种重要的数据结构,通常用于实现优先队列和一些其他算法。堆具有以下主要特点:

  1. 完全二叉树结构: 堆通常是一个完全二叉树,这意味着树中的每个节点都有最多两个子节点,除了最后一层,其他层都是满的。这种特性使得堆可以有效地使用数组来表示,因为数组的索引操作非常高效。

  2. 堆序性质: 堆分为两种主要类型,最小堆和最大堆,它们都具有堆序性质。在最小堆中,每个节点的值都小于或等于其子节点的值,根节点的值最小。在最大堆中,每个节点的值都大于或等于其子节点的值,根节点的值最大。

  3. 堆的操作: 堆支持一些基本操作,包括插入元素、删除根节点(最小或最大元素)、查找根节点(最小或最大元素),以及堆化操作(将一个无序数组或树转化为堆)。这些操作的时间复杂度通常为 O(log n),其中 n 是堆中元素的数量。

  4. 应用: 堆广泛用于解决各种问题,如优先队列(用于任务调度、Dijkstra 算法等)、堆排序算法、求中位数、Top K 问题、图算法(Prim 和 Kruskal 算法中的最小生成树等)等。由于其高效的插入和删除操作,堆在这些问题中表现出色。

  5. 实现: 堆可以用数组来表示。在数组中,根节点通常位于索引 0,对于节点 i,其左子节点位于 2i + 1,右子节点位于 2i + 2。这种表示方法使得堆的操作更加高效。堆可以是最小堆或最大堆,具体类型取决于问题需求。

  6. 平衡性: 堆是一种自平衡数据结构,即在插入和删除操作后,堆仍然保持堆序性质。这是通过堆化操作来实现的,它可以向上(上滤)或向下(下滤)调整节点的位置,以满足堆的要求。

堆是一种非常有用的数据结构,用于解决许多与优先级相关的问题和算法。最小堆和最大堆的差异在于它们的堆序性质,但它们都具有相似的操作和实现方式。理解堆的基本原理和操作对于编写高效的算法非常重要。

2.大顶堆

以大顶堆为例,相对于之前的优先级队列,增加了堆化等方法

public class MaxHeap {
    int[] array;
    int size;

    public MaxHeap(int capacity) {
        this.array = new int[capacity];
    }

    /**
     * 获取堆顶元素
     *
     * @return 堆顶元素
     */
    public int peek() {
      	//获取堆顶元素
        return array[0];
    }

    /**
     * 删除堆顶元素
     *
     * @return 堆顶元素
     */
    public int poll() {
      	//获取堆顶元素
        int top = array[0];
     		//交换堆顶和堆底
        swap(0, size - 1);
      	//容量--
        size--;
      	//堆顶下沉
        down(0);
        return top;
    }

    /**
     * 删除指定索引处元素
     *
     * @param index 索引
     * @return 被删除元素
     */
    public int poll(int index) {
        int deleted = array[index];
        swap(index, size - 1);
        size--;
        down(index);
        return deleted;
    }

    /**
     * 替换堆顶元素
     * @param replaced 新元素
     */
    public void replace(int replaced) {
        array[0] = replaced;
        down(0);
    }

    /**
     * 堆的尾部添加元素
     *
     * @param offered 新元素
     * @return 是否添加成功
     */
    public boolean offer(int offered) {
        if (size == array.length) {
            return false;
        }
        up(offered);
        size++;
        return true;
    }

    // 将 offered 元素上浮: 直至 offered 小于父元素或到堆顶
    private void up(int offered) {
        //默认插入位置在最后的index
        int child = size;
        while (child > 0) {
          	//父节点的位置
            int parent = (child - 1) / 2;
            //上浮
            if (offered > array[parent]) {
                array[child] = array[parent];
            } else {
                break;
            }
          	//把父节点的坐标给child
            child = parent;
        }
      	//不要忘了赋值
        array[child] = offered;
    }

    public MaxHeap(int[] array) {
        this.array = array;
        this.size = array.length;
        heapify();
    }

    // 建堆
    private void heapify() {
        // 如何找到最后一个非叶子节点  size / 2 - 1,并不断往前遍历
        for (int i = size / 2 - 1; i >= 0; i--) {
            down(i);
        }
    }

    // 将 parent 索引处的元素下潜: 与两个孩子较大者交换, 直至没孩子或孩子没它大
    private void down(int parent) {
      	//找到左孩子坐标
        int left = parent * 2 + 1;
        //找到右孩子坐标
        int right = left + 1;
        int max = parent;
        if (left < size && array[left] > array[max]) {
            max = left;
        }
        if (right < size && array[right] > array[max]) {
            max = right;
        }
        if (max != parent) { // 找到了更大的孩子
            swap(max, parent);
            down(max);
        }
    }

    // 交换两个索引处的元素
    private void swap(int i, int j) {
        int t = array[i];
        array[i] = array[j];
        array[j] = t;
    }

    public static void main(String[] args) {

        int[] array = {1, 2, 3, 4, 5, 6, 7};
        MaxHeap maxHeap = new MaxHeap(array);
        System.out.println(Arrays.toString(maxHeap.array));
    }
}

3.小顶堆

public class MinHeap {

    int[] array;
    int size;

    public MinHeap(int capacity) {
        this.array = new int[capacity];
    }

    public boolean isFull() {
        return size == array.length;
    }


    /**
     * 获取堆顶元素
     *
     * @return 堆顶元素
     */
    public int peek() {
        return array[0];
    }

    /**
     * 删除堆顶元素
     *
     * @return 堆顶元素
     */
    public int poll() {
        int top = array[0];
        swap(0, size - 1);
        size--;
        down(0);
        return top;
    }

    /**
     * 删除指定索引处元素
     *
     * @param index 索引
     * @return 被删除元素
     */
    public int poll(int index) {
        int deleted = array[index];
        swap(index, size - 1);
        size--;
        down(index);
        return deleted;
    }

    /**
     * 替换堆顶元素
     *
     * @param replaced 新元素
     */
    public void replace(int replaced) {
        array[0] = replaced;
        down(0);
    }

    /**
     * 堆的尾部添加元素
     *
     * @param offered 新元素
     * @return 是否添加成功
     */
    public boolean offer(int offered) {
        if (size == array.length) {
            return false;
        }
        up(offered);
        size++;
        return true;
    }

    // 将 offered 元素上浮: 直至 offered 小于父元素或到堆顶
    private void up(int offered) {
        int child = size;
        while (child > 0) {
            int parent = (child - 1) / 2;
            if (offered < array[parent]) {
                array[child] = array[parent];
            } else {
                break;
            }
            child = parent;
        }
        array[child] = offered;
    }

    public MinHeap(int[] array) {
        this.array = array;
        this.size = array.length;
        heapify();
    }

    // 建堆
    private void heapify() {
        // 如何找到最后这个非叶子节点  size / 2 - 1
        for (int i = size / 2 - 1; i >= 0; i--) {
            down(i);
        }
    }

    // 将 parent 索引处的元素下潜: 与两个孩子较大者交换, 直至没孩子或孩子没它大
    private void down(int parent) {
        int left = parent * 2 + 1;
        int right = left + 1;
        int min = parent;
        if (left < size && array[left] < array[min]) {
            min = left;
        }
        if (right < size && array[right] < array[min]) {
            min = right;
        }
        if (min != parent) { // 找到了更大的孩子
            swap(min, parent);
            down(min);
        }
    }

    // 交换两个索引处的元素
    private void swap(int i, int j) {
        int t = array[i];
        array[i] = array[j];
        array[j] = t;
    }
}

4.JDK 的优先队列

// 大顶堆
private PriorityQueue<Integer> left = new PriorityQueue<>( (a, b) -> b-a);
// 默认是小顶堆
private PriorityQueue<Integer> right = new PriorityQueue<>();

5.建堆

  1. 找到最后一个非叶子节点
  2. 从后向前,对每个节点执行下潜

一些规律

  • 一棵满二叉树节点个数为 2 h − 1 2^h-1 2h1,如下例中高度 h = 3 h=3 h=3 节点数是 2 3 − 1 = 7 2^3-1=7 231=7
  • 非叶子节点范围为 [ 0 , s i z e / 2 − 1 ] [0, size/2-1] [0,size/21]

算法时间复杂度分析

image-20230213114024607

下面看交换次数的推导:设节点高度为 3

本层节点数高度下潜最多交换次数(高度-1)
4567 这层410
23 这层221
1 这层132

每一层的交换次数为: 节点个数 ∗ 此节点交换次数 节点个数*此节点交换次数 节点个数此节点交换次数,总的交换次数为

$$
\begin{aligned}
& 4 * 0 + 2 * 1 + 1 * 2 \

& \frac{8}{2}*0 + \frac{8}{4}*1 + \frac{8}{8}*2 \

& \frac{8}{2^1}*0 + \frac{8}{2^2}*1 + \frac{8}{2^3}*2\

\end{aligned}
$$

∑ i = 1 h ( 2 h 2 i ∗ ( i − 1 ) ) \sum_{i=1}^{h}(\frac{2^h}{2^i}*(i-1)) i=1h(2i2h(i1))

在 https://www.wolframalpha.com/ 输入

Sum[\(40)Divide[Power[2,x],Power[2,i]]*\(40)i-1\(41)\(41),{i,1,x}]

推导出

2 h − h − 1 2^h -h -1 2hh1

其中 2 h ≈ n 2^h \approx n 2hn h ≈ log ⁡ 2 n h \approx \log_2{n} hlog2n,因此有时间复杂度 O ( n ) O(n) O(n)

二.堆题目

1.堆排序

算法描述

  1. heapify 建立大顶堆
  2. 将堆顶与堆底交换(最大元素被交换到堆底),缩小并下潜调整堆
  3. 重复第二步直至堆里剩一个元素

可以使用之前课堂例题的大顶堆来实现

int[] array = {1, 2, 3, 4, 5, 6, 7};
MaxHeap maxHeap = new MaxHeap(array);
System.out.println(Arrays.toString(maxHeap.array));
//判断堆的剩余元素个数
while (maxHeap.size > 1) {
  	//交换堆顶和堆底,把最大的移到堆底
    maxHeap.swap(0, maxHeap.size - 1);
  	//将堆底的元素排除
    maxHeap.size--;
  	//堆顶的元素需要下沉
    maxHeap.down(0);
}
System.out.println(Arrays.toString(maxHeap.array));

2.数组中第 K 大元素-力扣 215 题

小顶堆(可删去用不到代码)

class MinHeap {
    int[] array;
    int size;

    public MinHeap(int capacity) {
        array = new int[capacity];
    }

    private void heapify() {
        for (int i = (size >> 1) - 1; i >= 0; i--) {
            down(i);
        }
    }

    public int poll() {
        swap(0, size - 1);
        size--;
        down(0);
        return array[size];
    }

    public int poll(int index) {
        swap(index, size - 1);
        size--;
        down(index);
        return array[size];
    }

    public int peek() {
        return array[0];
    }

    public boolean offer(int offered) {
        if (size == array.length) {
            return false;
        }
        up(offered);
        size++;
        return true;
    }

    public void replace(int replaced) {
        array[0] = replaced;
        down(0);
    }

    private void up(int offered) {
        int child = size;
        while (child > 0) {
            int parent = (child - 1) >> 1;
            if (offered < array[parent]) {
                array[child] = array[parent];
            } else {
                break;
            }
            child = parent;
        }
        array[child] = offered;
    }

    private void down(int parent) {
        int left = (parent << 1) + 1;
        int right = left + 1;
        int min = parent;
        if (left < size && array[left] < array[min]) {
            min = left;
        }
        if (right < size && array[right] < array[min]) {
            min = right;
        }
        if (min != parent) {
            swap(min, parent);
            down(min);
        }
    }

    // 交换两个索引处的元素
    private void swap(int i, int j) {
        int t = array[i];
        array[i] = array[j];
        array[j] = t;
    }
}

题解 1

public int findKthLargest(int[] numbers, int k) {
    MinHeap heap = new MinHeap(k);
    for (int i = 0; i < k; i++) {
        heap.offer(numbers[i]);
    }
    for (int i = k; i < numbers.length; i++) {
        if(numbers[i] > heap.peek()){
            heap.replace(numbers[i]);
        }
    }
    return heap.peek();
}

求数组中的第 K 大元素,使用堆并不是最佳选择,可以采用快速选择算法

题解 2

public int findKthLargest(int[] numbers, int k) {
  //小顶堆,先加入2个
  PriorityQueue<Integer> queue = new PriorityQueue<>();
  for (int i = 0; i < k; i++) {
      queue.add(numbers[i]);
  }
  //再加入后面剩下的
  for (int i = k; i < numbers.length; i++) {
      if (numbers[i] > queue.peek()) {
          queue.poll();
          queue.add(numbers[i]);
      }
  }
  return queue.peek();
}

3.数据流中第 K 大元素-力扣 703 题

上题的小顶堆加一个方法

class MinHeap {
    // ...
	public boolean isFull() {
        return size == array.length;
    }
}

题解 1

class KthLargest {

    private MinHeap heap;

    public KthLargest(int k, int[] nums) {
        heap = new MinHeap(k);
        for(int i = 0; i < nums.length; i++) {
            add(nums[i]);
        }
    }

    public int add(int val) {
        if(!heap.isFull()){
            heap.offer(val);
        } else if(val > heap.peek()){
            heap.replace(val);
        }
        return heap.peek();
    }

}

求数据流中的第 K 大元素,使用堆最合适不过

题解 2

private PriorityQueue<Integer> queue;
private int k = 0;

public E03Leetcode703_02(int k, int[] nums) {
    this.k = k;
    queue = new PriorityQueue();
    for (int num : nums) {
        add(num);
    }
}

// 此方法会被不断调用, 模拟数据流中新来的元素
public int add(int val) {
    if (queue.size() < k) {
        queue.offer(val);
    } else if (queue.peek() < val) {
        queue.poll();
        queue.offer(val);
    }
    return queue.peek();
}

4.数据流的中位数-力扣 295 题

可以扩容的 heap, max 用于指定是大顶堆还是小顶堆

public class Heap {
    int[] array;
    int size;
    boolean max;

    public int size() {
        return size;
    }

    public Heap(int capacity, boolean max) {
        this.array = new int[capacity];
        this.max = max;
    }

    /**
     * 获取堆顶元素
     *
     * @return 堆顶元素
     */
    public int peek() {
        return array[0];
    }

    /**
     * 删除堆顶元素
     *
     * @return 堆顶元素
     */
    public int poll() {
        int top = array[0];
        swap(0, size - 1);
        size--;
        down(0);
        return top;
    }

    /**
     * 删除指定索引处元素
     *
     * @param index 索引
     * @return 被删除元素
     */
    public int poll(int index) {
        int deleted = array[index];
        swap(index, size - 1);
        size--;
        down(index);
        return deleted;
    }

    /**
     * 替换堆顶元素
     *
     * @param replaced 新元素
     */
    public void replace(int replaced) {
        array[0] = replaced;
        down(0);
    }

    /**
     * 堆的尾部添加元素
     *
     * @param offered 新元素
     */
    public void offer(int offered) {
        if (size == array.length) {
            grow();
        }
        up(offered);
        size++;
    }

    private void grow() {
        int capacity = size + (size >> 1);
        int[] newArray = new int[capacity];
        System.arraycopy(array, 0,
                newArray, 0, size);
        array = newArray;
    }

    // 将 offered 元素上浮: 直至 offered 小于父元素或到堆顶
    private void up(int offered) {
        int child = size;
        while (child > 0) {
            int parent = (child - 1) / 2;
            boolean cmp = max ? offered > array[parent] : offered < array[parent];
            if (cmp) {
                array[child] = array[parent];
            } else {
                break;
            }
            child = parent;
        }
        array[child] = offered;
    }

    public Heap(int[] array, boolean max) {
        this.array = array;
        this.size = array.length;
        this.max = max;
        heapify();
    }

    // 建堆
    private void heapify() {
        // 如何找到最后这个非叶子节点  size / 2 - 1
        for (int i = size / 2 - 1; i >= 0; i--) {
            down(i);
        }
    }

    // 将 parent 索引处的元素下潜: 与两个孩子较大者交换, 直至没孩子或孩子没它大
    private void down(int parent) {
        int left = parent * 2 + 1;
        int right = left + 1;
        int min = parent;
        if (left < size && (max ? array[left] > array[min] : array[left] < array[min])) {
            min = left;
        }
        if (right < size && (max ? array[right] > array[min] : array[right] < array[min])) {
            min = right;
        }
        if (min != parent) { // 找到了更大的孩子
            swap(min, parent);
            down(min);
        }
    }

    // 交换两个索引处的元素
    private void swap(int i, int j) {
        int t = array[i];
        array[i] = array[j];
        array[j] = t;
    }
}

题解 1

private Heap left = new Heap(10, false);
private Heap right = new Heap(10, true);

/**
 为了保证两边数据量的平衡
 <ul>
  <li>两边数据一样时,加入左边</li>
  <li>两边数据不一样时,加入右边</li>
 </ul>
 但是, 随便一个数能直接加入吗?
 <ul>
  <li>加入左边前, 应该挑右边最小的加入</li>
  <li>加入右边前, 应该挑左边最大的加入</li>
 </ul>
 */
public void addNum(int num) {
    if (left.size() == right.size()) {
        right.offer(num);
        left.offer(right.poll());
    } else {
        left.offer(num);
        right.offer(left.poll());
    }
}

/**
 * <ul>
 *     <li>两边数据一致, 左右各取堆顶元素求平均</li>
 *     <li>左边多一个, 取左边元素</li>
 * </ul>
 */
public double findMedian() {
    if (left.size() == right.size()) {
        return (left.peek() + right.peek()) / 2.0;
    } else {
        return left.peek();
    }
}

本题还可以使用平衡二叉搜索树求解,不过代码比两个堆复杂

题解 2

/**
 * 为了保证两边数据量的平衡
 * <ul>
 * <li>两边个数一样时,左边个数加一</li>
 * <li>两边个数不一样时,右边个数加一</li>
 * </ul>
 * 但是, 随便一个数能直接加入吗?
 * <ul>
 * <li>左边个数加一时, 把新元素加在右边,弹出右边最小的加入左边</li>
 * <li>右边个数加一时, 把新元素加在左边,弹出左边最小的加入右边</li>
 * </ul>
 */
public void addNum(int num) {
    if (left.size() == right.size()) {
        right.offer(num);
        left.offer(right.poll());
    } else {
        left.offer(num);
        right.offer(left.poll());
    }
}

/**
 * <ul>
 *     <li>两边数据一致, 左右各取堆顶元素求平均</li>
 *     <li>左边多一个, 取左边堆顶元素</li>
 * </ul>
 */
public double findMedian() {
    if (left.size() == right.size()) {
        return (left.peek() + right.peek()) / 2.0;
    } else {
        return left.peek();
    }
}

// 大顶堆
private PriorityQueue<Integer> left = new PriorityQueue<>(
        (a, b) -> Integer.compare(b, a)
);
// 默认是小顶堆
private PriorityQueue<Integer> right = new PriorityQueue<>();

觉得有用的话点个赞 👍🏻 呗。
❤️❤️❤️本人水平有限,如有纰漏,欢迎各位大佬评论批评指正!😄😄😄

💘💘💘如果觉得这篇文对你有帮助的话,也请给个点赞、收藏下吧,非常感谢!👍 👍 👍

🔥🔥🔥Stay Hungry Stay Foolish 道阻且长,行则将至,让我们一起加油吧!🌙🌙🌙

img

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

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

相关文章

嵌入式行业这个领域是否值得坚持

今日话题&#xff0c;嵌入式行业&#xff0c;特别是对于嵌入式新人&#xff0c;是否值得坚持这个领域&#xff1f;对于想要进入嵌入式行业的人来说&#xff0c;坚持是明智的选择。这个领域涉及硬件和软件&#xff0c;技术更新较慢&#xff0c;但它也为你提供了积累经验的机会。…

mysql学习查缺补漏1---基础部分(小滴课堂)

举例&#xff1a; DDL&#xff1a;建库&#xff0c;建表。 DML&#xff1a;对表的数据进行增删改操作。 DQL&#xff1a;对数据进行查询。 DCL&#xff1a;对用户的权限进行设置。 create table teacher as select * from student where 12; 该条语句只用于复制表结构&…

Kubernetes 使用configmap挂载卷给Pod内的nginx容器

目录 实验&#xff1a;使用configmap挂载卷给Pod内的nginx容器 1、创建nginx.conf配置文件&#xff08;必须由nginx镜像里的nginx.conf修改而来&#xff0c;防止出现配置不相似的情况出现&#xff0c;导致访问不了nginx网页&#xff09; 2、通过nginx.conf文件创建configmap容…

Java 代理模式之静态代理与动态代理

1&#xff0c;代理模式 代理模式给某一个对象提供一个代理对象&#xff0c;并由代理对象控制对原对象的引用。通俗的来讲代理模式就是我们生活中常见的中介。 代理模式的目的&#xff1a; &#xff08;1&#xff09;通过引入代理对象的方式来间接访问目标对象&#xff0c;防…

对话式人工智能(Conversational AI):提高模型的智能程度和扩展能力

对话式人工智能的趋势与挑战 对话式人工智能 (AI) 已经出现在许多家庭的客厅、汽车和在线购物体验中。聊天机器人、语音助手、智能扬声器、交互式语音识别系统&#xff1a;所有这些都是对话式 AI 的示例。由于该领域通过增强的客户体验提供了更多可访问性&#xff0c;因此吸引…

PHP自己的框架2.0结合容器技术(重构篇二)

目录 1、使用容器实现框架加载类运行 2、 创建框架容器类core/fm/Di.php 3、框架使用容器类来执行public/index.php 4、运行效果还是一样 1、使用容器实现框架加载类运行 2、 创建框架容器类core/fm/Di.php 什么是容器&#xff1f;容器就相当于盒子&#xff0c;把很多类放里…

录音怎么转换成mp3格式?支持二十多种格式

录音怎么转换成mp3格式&#xff1f;在我们的日常生活和工作中&#xff0c;录音是一项非常有用的工具&#xff0c;随着手机以及录音设备越来越普及化&#xff0c;让录音这件事情变得非常的简单&#xff0c;录音可以帮助我们解决非常多的事情。例如通过录音&#xff0c;我们可以记…

Linux C++ OpenVINO 物体检测 Demo

目录 main.cpp #include <iostream> #include <string> #include <vector> #include <openvino/openvino.hpp> #include <opencv2/opencv.hpp> #include <dirent.h> #include <stdio.h> #include <time.h> #include …

OJ练习第171题——复制带随机指针的链表

复制带随机指针的链表 力扣链接&#xff1a;138. 复制带随机指针的链表 题目描述 给你一个长度为 n 的链表&#xff0c;每个节点包含一个额外增加的随机指针 random &#xff0c;该指针可以指向链表中的任何节点或空节点。 构造这个链表的 深拷贝。 深拷贝应该正好由 n 个…

Temu新手入门需要注意哪些细节?如何在Temu中添加尺码?

要在temu平台取得商业成功&#xff0c;创业者们必须注重商品策划和市场调研、关注市场动向和用户反馈、建立良好的互动和交流机制、发挥temu的优势和特点&#xff0c;本文介绍了temu新手入门需要注意细节以及如何在TEMU中添加尺码&#xff0c;快来学习一下吧。 temu新手入门需…

使用Javassist修改组件化 Router

工程目录图 请点击下面工程名称&#xff0c;跳转到代码的仓库页面&#xff0c;将工程 下载下来 Demo Code 里有详细的注释 代码&#xff1a;TransformDemo

Python中数据去重的重要性、技巧和实现代码

在数据处理和分析的过程中&#xff0c;数据去重是数据处理和分析的关键步骤之一。重复的数据会导致分析结果的偏差&#xff0c;影响决策的准确性。通过数据去重&#xff0c;我们可以确保分析所使用的数据集是干净、准确的&#xff0c;从而提高分析结果的可靠性&#xff0c;Pyth…

【LeetCode题目详解】第十章 单调栈part03 84.柱状图中最大的矩形(day60补)

本文章代码以c为例&#xff01; 一、力扣第84题&#xff1a;柱状图中最大的矩形 题目&#xff1a; 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该柱状图中&#xff0c;能够勾勒出来的矩形的最大面积。 …

【数据结构】—堆详解(手把手带你用C语言实现)

食用指南&#xff1a;本文在有C基础的情况下食用更佳 &#x1f525;这就不得不推荐此专栏了&#xff1a;C语言 ♈️今日夜电波&#xff1a;水星—今泉愛夏 1:10 ━━━━━━️&#x1f49f;──────── 4:23 …

掌控你的Mac——用Bookshelf Library简化文件管理

Bookshelf Library for Mac是一款高效的文件索引管理工具&#xff0c;它可以帮助你轻松整理和查找Mac上的所有文档和书籍。下面我们来看看这款工具的五个特点。 安装&#xff1a;Bookshelf Library for Mac(文件索引管理工具)v6.3.4激活版 第一&#xff0c;Bookshelf Library…

【广州华锐互动】工业零件拆装VR培训:无需前往现场,提高学习效率

工业零件拆装VR培训是一种新兴的培训方式&#xff0c;通过虚拟现实技术将设备拆解过程进行模拟&#xff0c;让学员在虚拟环境中进行实际操作和学习。这种培训方式具有许多益处&#xff0c;本文将对其进行详细阐述。 首先&#xff0c;工业零件拆装VR培训可以提高学员的学习效率。…

好用的软件测试框架有哪些?测试框架的作用是什么?

软件测试框架是现代软件开发过程中至关重要的工具&#xff0c;它可以帮助开发团队更加高效地进行测试和验证工作&#xff0c;从而大大提高软件质量和用户体验。 一、好用的软件测试框架 1. Selenium&#xff1a;作为一种开源的自动化测试框架&#xff0c;Selenium具有功能强大…

【Jmeter】什么是BeanShell?

一、什么是BeanShell&#xff1f; BeanShell是用Java写成的,一个小型的、免费的、可以下载的、嵌入式的Java源代码解释器&#xff0c;JMeter性能测试工具也充分接纳了BeanShell解释器&#xff0c;封装成了可配置的BeanShell前置和后置处理器&#xff0c;分别是 BeanShell Pre…

快速打造BI大屏 激活各行业数据价值

BI的概念普遍认为最早由Gartner公司提出&#xff0c;简单可理解为基于现代企业经营理论与信息应用技术系统对信息、数据进行挖掘、分析和处理&#xff0c;最终辅助商业决策的一个企业服务解决方案。 在企业数字化进程中&#xff0c;这样的解决方案主要以信息技术系统为底座&am…

力扣 -- 673. 最长递增子序列的个数

小算法&#xff1a; 通过一次遍历找到数组中最大值出现的次数&#xff1a; 利用这个小算法求解这道题就会非常简单了。 参考代码&#xff1a; class Solution { public:int findNumberOfLIS(vector<int>& nums) {int nnums.size();vector<int> len(n,1);auto…