排序题目:计算右侧小于当前元素的个数

news2024/10/10 22:23:29

文章目录

  • 题目
    • 标题和出处
    • 难度
    • 题目描述
      • 要求
      • 示例
      • 数据范围
  • 前言
  • 解法一
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法二
    • 预备知识
    • 思路和算法
    • 代码
    • 复杂度分析
  • 解法三
    • 预备知识
    • 思路和算法
    • 代码
    • 复杂度分析

题目

标题和出处

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

出处:315. 计算右侧小于当前元素的个数

难度

8 级

题目描述

要求

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

示例

示例 1:

输入: nums   =   [5,2,6,1] \texttt{nums = [5,2,6,1]} nums = [5,2,6,1]
输出: [2,1,1,0] \texttt{[2,1,1,0]} [2,1,1,0]
解释:
5 \texttt{5} 5 的右侧有 2 \texttt{2} 2 个更小的元素( 2 \texttt{2} 2 1 \texttt{1} 1)。
2 \texttt{2} 2 的右侧有 1 \texttt{1} 1 个更小的元素( 1 \texttt{1} 1)。
6 \texttt{6} 6 的右侧有 1 \texttt{1} 1 个更小的元素( 1 \texttt{1} 1)。
1 \texttt{1} 1 的右侧有 0 \texttt{0} 0 个更小的元素。

示例 2:

输入: nums   =   [-1] \texttt{nums = [-1]} nums = [-1]
输出: [0] \texttt{[0]} [0]

示例 3:

输入: nums   =   [-1,-1] \texttt{nums = [-1,-1]} nums = [-1,-1]
输出: [0,0] \texttt{[0,0]} [0,0]

数据范围

  • 1 ≤ nums.length ≤ 10 5 \texttt{1} \le \texttt{nums.length} \le \texttt{10}^\texttt{5} 1nums.length105
  • -10 4 ≤ nums[i] ≤ 10 4 \texttt{-10}^\texttt{4} \le \texttt{nums[i]} \le \texttt{10}^\texttt{4} -104nums[i]104

前言

定义「逆序对」的概念如下:对于下标 i i i j j j,如果 i < j i < j i<j nums [ i ] > nums [ j ] \textit{nums}[i] > \textit{nums}[j] nums[i]>nums[j],则下标对 ( i , j ) (i, j) (i,j) 是一个逆序对。

这道题要求计算数组 nums \textit{nums} nums 中的每个元素右侧小于当前元素的个数,实质是计算每个元素右侧的元素中与当前元素形成逆序对的元素个数。

对于长度为 n n n 的数组,最朴素的计算逆序对的数量的方法是对于每个元素遍历其右边的元素并统计可以形成逆序对的元素个数,每个元素需要 O ( n ) O(n) O(n) 的时间计算逆序对的个数,总时间复杂度是 O ( n 2 ) O(n^2) O(n2)。由于数组 nums \textit{nums} nums 的长度最大为 1 0 5 10^5 105,因此 O ( n 2 ) O(n^2) O(n2) 的时间复杂度过高,必须使用时间复杂度更低的方法。

以下介绍三种时间复杂度 O ( n log ⁡ n ) O(n \log n) O(nlogn) 的计算逆序对数量的方法,分别是归并排序、线段树和树状数组。

解法一

思路和算法

由于逆序对和排序相关,因此可以使用排序的思想计算逆序对的数量。归并排序的过程中,每次将两个升序子数组合并,合并的过程中即可发现这两个升序子数组中的逆序对。因此可以在归并排序的过程中计算每个元素右侧的元素中与当前元素形成逆序对的元素个数。

考虑下标范围 [ low , high ] [\textit{low}, \textit{high}] [low,high] 的子数组的归并排序过程。当 low ≥ high \textit{low} \ge \textit{high} lowhigh 时,子数组的长度是 0 0 0 1 1 1,此时子数组已经符合升序。当 low < high \textit{low} < \textit{high} low<high 时,子数组的长度大于等于 2 2 2,归并排序的过程为将子数组分成两个更短的子数组,两个更短的子数组排序之后合并,具体过程如下。

  1. low \textit{low} low high \textit{high} high 的平均值 mid \textit{mid} mid,将下标范围 [ low , high ] [\textit{low}, \textit{high}] [low,high] 的子数组分成下标范围 [ low , mid ] [\textit{low}, \textit{mid}] [low,mid] 和下标范围 [ mid + 1 , high ] [\textit{mid} + 1, \textit{high}] [mid+1,high] 的两个子数组。

  2. 将下标范围 [ low , mid ] [\textit{low}, \textit{mid}] [low,mid] 和下标范围 [ mid + 1 , high ] [\textit{mid} + 1, \textit{high}] [mid+1,high] 的两个子数组分别排序,得到两个升序子数组。

  3. i i i j j j 分别表示下标范围 [ low , mid ] [\textit{low}, \textit{mid}] [low,mid] 和下标范围 [ mid + 1 , high ] [\textit{mid} + 1, \textit{high}] [mid+1,high] 的两个升序子数组中的待合并元素下标,初始时 i = low i = \textit{low} i=low j = mid + 1 j = \textit{mid} + 1 j=mid+1。当 i ≤ mid i \le \textit{mid} imid j ≤ high j \le \textit{high} jhigh 时,按照如下操作合并两个子数组,合并过程中需要保持排序的稳定性。

    • 如果 nums [ i ] ≤ nums [ j ] \textit{nums}[i] \le \textit{nums}[j] nums[i]nums[j],则将 nums [ i ] \textit{nums}[i] nums[i] 添加到合并后的结果中,然后将 i i i 1 1 1

    • 如果 nums [ i ] > nums [ j ] \textit{nums}[i] > \textit{nums}[j] nums[i]>nums[j],则将 nums [ j ] \textit{nums}[j] nums[j] 添加到合并后的结果中,然后将 j j j 1 1 1

  4. 当其中一个升序子数组的元素全部合并结束之后,将另一个升序子数组的元素依次添加到合并后的结果中。

由于合并过程保持排序的稳定性,因此当 nums [ i ] ≤ nums [ j ] \textit{nums}[i] \le \textit{nums}[j] nums[i]nums[j] 或者 j = high + 1 j = \textit{high} + 1 j=high+1 时,一定有 nums [ i ] > nums [ j − 1 ] \textit{nums}[i] > \textit{nums}[j - 1] nums[i]>nums[j1](如果 j = high + 1 j = \textit{high} + 1 j=high+1,则有 j − 1 = high j - 1 = \textit{high} j1=high),否则 nums [ i ] = nums [ j − 1 ] \textit{nums}[i] = \textit{nums}[j - 1] nums[i]=nums[j1],在合并 nums [ i ] \textit{nums}[i] nums[i] 之前合并 nums [ j − 1 ] \textit{nums}[j - 1] nums[j1] 与归并排序的稳定性矛盾。因此对于任意 mid + 1 ≤ k ≤ j − 1 \textit{mid} + 1 \le k \le j - 1 mid+1kj1 都有 nums [ i ] > nums [ k ] \textit{nums}[i] > \textit{nums}[k] nums[i]>nums[k],即在下标范围 [ mid + 1 , high ] [\textit{mid} + 1, \textit{high}] [mid+1,high] 的升序子数组中有 j − mid − 1 j - \textit{mid} - 1 jmid1 个数小于 nums [ i ] \textit{nums}[i] nums[i],将 j − mid − 1 j - \textit{mid} - 1 jmid1 加到 nums [ i ] \textit{nums}[i] nums[i] 对应的计数中。

为了记录每个元素右侧小于当前元素的个数,需要维护下标数组和计数数组,在归并排序计算逆序对的过程中同时对原数组和下标数组执行归并操作,确保原数组和下标数组中的每个元素分别对应。当更新一个元素对应的计数时,从下标数组得到该元素的下标,更新计数数组中该下标处的计数。

当整个数组排序结束时,计数数组即为每个元素右侧小于当前元素的个数。

由于计算每个元素的逆序对数量以及合并两个升序子数组都需要遍历两个升序子数组,因此计算每个元素的逆序对数量并没有提升总时间复杂度,总时间复杂度和原始归并排序一样是 O ( n log ⁡ n ) O(n \log n) O(nlogn)

归并排序可以使用自顶向下的方式递归实现,也可以使用自底向上的方式迭代实现。对于同一个数组,使用自顶向下和自底向上两种方式实现的中间过程可能有所区别,但是都能得到正确的结果。

代码

以下代码为归并排序的自顶向下实现。

class Solution {
    public List<Integer> countSmaller(int[] nums) {
        int length = nums.length;
        int[] indices = new int[length];
        for (int i = 0; i < length; i++) {
            indices[i] = i;
        }
        List<Integer> counts = new ArrayList<Integer>();
        for (int i = 0; i < length; i++) {
            counts.add(0);
        }
        mergeSortAndCount(nums, indices, counts, 0, length - 1);
        return counts;
    }

    public void mergeSortAndCount(int[] nums, int[] indices, List<Integer> counts, int low, int high) {
        if (low >= high) {
            return;
        }
        int mid = low + (high - low) / 2;
        mergeSortAndCount(nums, indices, counts, low, mid);
        mergeSortAndCount(nums, indices, counts, mid + 1, high);
        merge(nums, indices, counts, low, mid, high);
    }

    public void merge(int[] nums, int[] indices, List<Integer> counts, int low, int mid, int high) {
        int currLength = high - low + 1;
        int[] tempNums = new int[currLength];
        int[] tempIndices = new int[currLength];
        int i = low, j = mid + 1, k = 0;
        while (i <= mid && j <= high) {
            if (nums[i] <= nums[j]) {
                tempNums[k] = nums[i];
                tempIndices[k] = indices[i];
                counts.set(indices[i], counts.get(indices[i]) + (j - mid - 1));
                i++;
            } else {
                tempNums[k] = nums[j];
                tempIndices[k] = indices[j];
                j++;
            }
            k++;
        }
        while (i <= mid) {
            tempNums[k] = nums[i];
            tempIndices[k] = indices[i];
            counts.set(indices[i], counts.get(indices[i]) + (j - mid - 1));
            i++;
            k++;
        }
        while (j <= high) {
            tempNums[k] = nums[j];
            tempIndices[k] = indices[j];
            j++;
            k++;
        }
        System.arraycopy(tempNums, 0, nums, low, currLength);
        System.arraycopy(tempIndices, 0, indices, low, currLength);
    }
}

以下代码为归并排序的自底向上实现。

class Solution {
    public List<Integer> countSmaller(int[] nums) {
        int length = nums.length;
        int[] indices = new int[length];
        for (int i = 0; i < length; i++) {
            indices[i] = i;
        }
        List<Integer> counts = new ArrayList<Integer>();
        for (int i = 0; i < length; i++) {
            counts.add(0);
        }
        for (int halfLength = 1, currLength = 2; halfLength < length; halfLength *= 2, currLength *= 2) {
            for (int low = 0; low < length - halfLength; low += currLength) {
                int mid = low + halfLength - 1;
                int high = Math.min(low + currLength - 1, length - 1);
                merge(nums, indices, counts, low, mid, high);
            }
        }
        return counts;
    }

    public void merge(int[] nums, int[] indices, List<Integer> counts, int low, int mid, int high) {
        int currLength = high - low + 1;
        int[] tempNums = new int[currLength];
        int[] tempIndices = new int[currLength];
        int i = low, j = mid + 1, k = 0;
        while (i <= mid && j <= high) {
            if (nums[i] <= nums[j]) {
                tempNums[k] = nums[i];
                tempIndices[k] = indices[i];
                counts.set(indices[i], counts.get(indices[i]) + (j - mid - 1));
                i++;
            } else {
                tempNums[k] = nums[j];
                tempIndices[k] = indices[j];
                j++;
            }
            k++;
        }
        while (i <= mid) {
            tempNums[k] = nums[i];
            tempIndices[k] = indices[i];
            counts.set(indices[i], counts.get(indices[i]) + (j - mid - 1));
            i++;
            k++;
        }
        while (j <= high) {
            tempNums[k] = nums[j];
            tempIndices[k] = indices[j];
            j++;
            k++;
        }
        System.arraycopy(tempNums, 0, nums, low, currLength);
        System.arraycopy(tempIndices, 0, indices, low, currLength);
    }
}

复杂度分析

  • 时间复杂度: O ( n log ⁡ n ) O(n \log n) O(nlogn),其中 n n n 是数组 nums \textit{nums} nums 的长度。归并排序的时间复杂度是 O ( n log ⁡ n ) O(n \log n) O(nlogn)

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。下标数组需要 O ( n ) O(n) O(n) 的空间,自顶向下实现时需要递归调用栈的空间是 O ( log ⁡ n ) O(\log n) O(logn),自底向上实现时可以省略递归调用栈的空间。无论是自顶向下实现还是自底向上实现,归并过程需要 O ( n ) O(n) O(n) 的辅助空间。

解法二

预备知识

该解法涉及到线段树。线段树是一种二叉搜索树,将一个区间划分成两个更短的区间。线段树中的每个叶结点都是长度为 1 1 1 的区间,称为单元区间。

线段树支持区间的快速查询和修改。对于长度为 n n n 的区间,使用线段树查询特定子区间的元素个数以及修改特定子区间内的元素个数的时间是 O ( log ⁡ n ) O(\log n) O(logn)

有时,为了降低线段树的空间复杂度,需要使用离散化。

思路和算法

对于长度为 n n n 的数组,其中不同元素的个数最多有 n n n 个。由于计算逆序对数量只需要考虑元素的相对大小,因此可以使用离散化将区间长度限制在 n n n 以内。离散化的方法是计算数组 nums \textit{nums} nums 中的每个元素的名次,计算名次的方法是:新建数组 sorted \textit{sorted} sorted 并将数组 nums \textit{nums} nums 中的所有元素复制到数组 sorted \textit{sorted} sorted 中,然后对数组 sorted \textit{sorted} sorted 排序,排序之后, sorted [ i ] \textit{sorted}[i] sorted[i] 的名次为 i i i,如果 i > 0 i > 0 i>0 sorted [ i ] = sorted [ i − 1 ] \textit{sorted}[i] = \textit{sorted}[i - 1] sorted[i]=sorted[i1] sorted [ i ] \textit{sorted}[i] sorted[i] 的名次与 sorted [ i − 1 ] \textit{sorted}[i - 1] sorted[i1] 的名次相同。每个元素的名次都在范围 [ 0 , n − 1 ] [0, n - 1] [0,n1] 中,表示数组中的小于该元素的元素个数。

由于这道题要求计算每个元素右侧的元素中与当前元素形成逆序对的元素个数,因此遍历数组 nums \textit{nums} nums 的过程中需要确保每个元素右侧的元素已经遍历过,需要从右到左遍历数组 nums \textit{nums} nums 计算逆序对的数量。

创建线段树,用于存储数组 nums \textit{nums} nums 中的每个元素的名次。从右到遍历数组 nums \textit{nums} nums,对于每个元素 num \textit{num} num,其右侧的元素已经遍历过,其右侧的元素中的每个小于 num \textit{num} num 的元素都与 num \textit{num} num 组成一个逆序对,因此得到 num \textit{num} num 的名次 rank \textit{rank} rank,计算线段树的子区间 [ 0 , rank − 1 ] [0, \textit{rank} - 1] [0,rank1] 中的元素个数,该元素个数即为当前元素 num \textit{num} num 元素右侧小于 num \textit{num} num 的元素个数。得到当前元素右侧小于当前元素的个数之后,将 rank \textit{rank} rank 添加到线段树中,继续向左遍历元素并计算每个元素右侧小于当前元素的个数。遍历结束之后,即可得到数组 nums \textit{nums} nums 中的每个元素右侧小于当前元素的个数。

代码

class Solution {
    public List<Integer> countSmaller(int[] nums) {
        List<Integer> counts = new ArrayList<Integer>();
        int length = nums.length;
        for (int i = 0; i < length; i++) {
            counts.add(0);
        }
        Map<Integer, Integer> ranks = getRanks(nums);
        SegmentTree st = new SegmentTree(length);
        for (int i = length - 1; i >= 0; i--) {
            int rank = ranks.get(nums[i]);
            counts.set(i, st.getCount(0, rank - 1));
            st.add(rank);
        }
        return counts;
    }

    public Map<Integer, Integer> getRanks(int[] nums) {
        int length = nums.length;
        int[] sorted = new int[length];
        System.arraycopy(nums, 0, sorted, 0, length);
        Arrays.sort(sorted);
        Map<Integer, Integer> ranks = new HashMap<Integer, Integer>();
        for (int i = 0; i < length; i++) {
            int num = sorted[i];
            if (i == 0 || num > sorted[i - 1]) {
                ranks.put(num, i);
            }
        }
        return ranks;
    }
}

class SegmentTree {
    int length;
    int[] tree;

    public SegmentTree(int length) {
        this.length = length;
        this.tree = new int[length * 4];
    }

    public int getCount(int start, int end) {
        return getCount(start, end, 0, 0, length - 1);
    }

    public void add(int rank) {
        add(rank, 0, 0, length - 1);
    }

    private int getCount(int rangeStart, int rangeEnd, int index, int treeStart, int treeEnd) {
        if (rangeStart > rangeEnd) {
            return 0;
        }
        if (rangeStart == treeStart && rangeEnd == treeEnd) {
            return tree[index];
        }
        int mid = treeStart + (treeEnd - treeStart) / 2;
        if (rangeEnd <= mid) {
            return getCount(rangeStart, rangeEnd, index * 2 + 1, treeStart, mid);
        } else if (rangeStart > mid) {
            return getCount(rangeStart, rangeEnd, index * 2 + 2, mid + 1, treeEnd);
        } else {
            return getCount(rangeStart, mid, index * 2 + 1, treeStart, mid) + getCount(mid + 1, rangeEnd, index * 2 + 2, mid + 1, treeEnd);
        }
    }

    private void add(int rank, int index, int start, int end) {
        if (start == end) {
            tree[index]++;
            return;
        }
        int mid = start + (end - start) / 2;
        if (rank <= mid) {
            add(rank, index * 2 + 1, start, mid);
        } else {
            add(rank, index * 2 + 2, mid + 1, end);
        }
        tree[index] = tree[index * 2 + 1] + tree[index * 2 + 2];
    }
}

复杂度分析

  • 时间复杂度: O ( n log ⁡ n ) O(n \log n) O(nlogn),其中 n n n 是数组 nums \textit{nums} nums 的长度。每个元素在线段树中的查询和更新操作都需要 O ( log ⁡ n ) O(\log n) O(logn) 的时间,时间复杂度是 O ( n log ⁡ n ) O(n \log n) O(nlogn)

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。创建线段树需要 O ( n ) O(n) O(n) 的空间。

解法三

预备知识

该解法涉及到树状数组。树状数组也称二叉索引树,由 Peter M. Fenwick 发明,因此又称 Fenwick 树。树状数组支持快速计算数组的前缀和与区间和,以及快速修改。对于长度为 n n n 的区间,使用树状数组查询特定子区间的区间和以及修改特定子区间内的元素值的时间是 O ( log ⁡ n ) O(\log n) O(logn)

有时,为了降低树状数组的空间复杂度,需要使用离散化。

思路和算法

计算每个元素右侧小于当前元素的个数也可以使用树状数组实现。

首先使用离散化将区间长度限制在 n n n 以内,然后创建树状数组,用于存储数组 nums \textit{nums} nums 中的每个元素的名次。从右到左遍历数组 nums \textit{nums} nums,对于每个元素 num \textit{num} num,得到 num \textit{num} num 的名次 rank \textit{rank} rank,计算树状数组的子区间 [ 0 , rank + 1 ] [0, \textit{rank} + 1] [0,rank+1] 中的元素个数,该元素个数即为即为当前元素 num \textit{num} num 元素右侧小于 num \textit{num} num 的元素个数。得到当前元素右侧小于当前元素的个数之后,将 rank \textit{rank} rank 添加到树状数组中,继续向左遍历元素并计算每个元素右侧小于当前元素的个数。遍历结束之后,即可得到数组 nums \textit{nums} nums 中的每个元素右侧小于当前元素的个数。

代码

class Solution {
    public List<Integer> countSmaller(int[] nums) {
        List<Integer> counts = new ArrayList<Integer>();
        int length = nums.length;
        for (int i = 0; i < length; i++) {
            counts.add(0);
        }
        Map<Integer, Integer> ranks = getRanks(nums);
        BinaryIndexedTree bit = new BinaryIndexedTree(length);
        for (int i = length - 1; i >= 0; i--) {
            int rank = ranks.get(nums[i]);
            counts.set(i, bit.getCount(0, rank - 1));
            bit.add(rank);
        }
        return counts;
    }

    public Map<Integer, Integer> getRanks(int[] nums) {
        int length = nums.length;
        int[] sorted = new int[length];
        System.arraycopy(nums, 0, sorted, 0, length);
        Arrays.sort(sorted);
        Map<Integer, Integer> ranks = new HashMap<Integer, Integer>();
        for (int i = 0; i < length; i++) {
            int num = sorted[i];
            if (i == 0 || num > sorted[i - 1]) {
                ranks.put(num, i);
            }
        }
        return ranks;
    }
}

class BinaryIndexedTree {
    int length;
    int[] tree;

    public BinaryIndexedTree(int length) {
        this.length = length;
        this.tree = new int[length + 1];
    }

    public int getCount(int start, int end) {
        return getPrefixSum(end + 1) - getPrefixSum(start);
    }

    public void add(int index) {
        index++;
        while (index <= length) {
            tree[index]++;
            index += lowbit(index);
        }
    }

    private int getPrefixSum(int index) {
        int sum = 0;
        while (index > 0) {
            sum += tree[index];
            index -= lowbit(index);
        }
        return sum;
    }

    private static int lowbit(int x) {
        return x & (-x);
    }
}

复杂度分析

  • 时间复杂度: O ( n log ⁡ n ) O(n \log n) O(nlogn),其中 n n n 是数组 nums \textit{nums} nums 的长度。每个元素在树状数组中的查询和更新操作都需要 O ( log ⁡ n ) O(\log n) O(logn) 的时间,时间复杂度是 O ( n log ⁡ n ) O(n \log n) O(nlogn)

  • 空间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。创建树状数组需要 O ( n ) O(n) O(n) 的空间。

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

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

相关文章

ceph基础

ceph基础搭建 存储基础 传统的存储类型&#xff1a; DAS设备&#xff1a; SAS,SATA,SCSI,IDW,USB 无论是那种接口&#xff0c;都是存储设备驱动下的磁盘设备&#xff0c;而磁盘设备其实就是一种存储是直接接入到主板总线上去的。直连存储。 NAS设备: NFS CIFS FTP 几乎所有的…

商标恶意维权形式及应对策略

在商业领域&#xff0c;商标恶意维权的现象时有出现&#xff0c;给正常的市场秩序和企业经营带来了不良影响。以下将介绍其常见形式及应对方法。 一、商标恶意维权的形式1、囤积商标后恶意诉讼。一些人或企业大量注册与知名品牌相似或具有一定通用性的商标&#xff0c;并非用于…

留学生毕业论文设计问卷questionnaire的基本步骤

在上一期内容中&#xff0c;小编介绍了留学毕业论文的定量研究和相关的问卷设计。然而在一些研究中&#xff0c;定量研究和问卷数据并不能满足我们的研究需求。这种情况下&#xff0c;我们可以采取其他的数据收集方式&#xff0c;例如observation&#xff0c;case study和inter…

软件设计之SSM(11)

软件设计之SSM(11) 路线图推荐&#xff1a; 【Java学习路线-极速版】【Java架构师技术图谱】 尚硅谷新版SSM框架全套视频教程&#xff0c;Spring6SpringBoot3最新SSM企业级开发 资料可以去尚硅谷官网免费领取 学习内容&#xff1a; Springboot 配置文件整合SpringMVC整合Dr…

【学术会议征稿】第十届能源资源与环境工程研究进展国际学术会议(ICAESEE 2024)

第十届能源资源与环境工程研究进展国际学术会议&#xff08;ICAESEE 2024&#xff09; 2024 10th International Conference on Advances in Energy Resources and Environment 第十届能源资源与环境工程研究进展国际学术会议&#xff08;ICAESEE 2024&#xff09;定于2024年…

拓扑排序与入度为0的结点算法解析及实现

拓扑排序与入度为0的结点算法解析及实现 算法思想时间复杂度分析伪代码C语言实现环路检测结论拓扑排序是一种用于有向无环图(DAG, Directed Acyclic Graph)的重要操作,它可以对图中的结点进行排序,使得对于每一条有向边 (u, v),顶点 u 在排序中都出现在顶点 v 之前。本文介…

Qt和c++面试集合

目录 Qt面试 什么是信号&#xff08;Signal&#xff09;和槽&#xff08;Slot&#xff09;&#xff1f; 什么是Meta-Object系统&#xff1f; 什么是Qt的MVC模式&#xff1f; 1. QT中connect函数的第五个参数是什么&#xff1f;有什么作用&#xff1f; 3. 在QT中&#xff…

ROS2官方文档(2024-10-10最新版)

ROS 2 Documentation — ROS 2 Documentation: Jazzy documentation (armfun.cn) ROS 2 文档 — ROS 2 文档&#xff1a;Humble 文档 (armfun.cn) 翻译中文方法&#xff1a;使用windows11自带Edge浏览器打开&#xff0c;右上角点击翻译为中文

pytest框架之fixture测试夹具详解

前言 大家下午好呀&#xff0c;今天呢来和大家唠唠pytest中的fixtures夹具的详解&#xff0c;废话就不多说了咱们直接进入主题哈。 一、fixture的优势 ​ pytest框架的fixture测试夹具就相当于unittest框架的setup、teardown&#xff0c;但相对之下它的功能更加强大和灵活。 …

DBMS-3.3 SQL(3)——DML的INSERT、UPDATE、DELETE空值的处理DCL

本文章的素材与知识来自李国良老师和王珊老师。 DML——INSERT、UPDATE、DELETE 一. INSERT 1.语法 &#xff08;1&#xff09;INTO子句 &#xff08;2&#xff09;VALUES子句 &#xff08;3&#xff09;示例 2.插入子查询 若插入的是子查询则不需要VALUES子句 二. UPDATE …

大数据法律监督模型平台实现常态化法律监督

大数据法律监督模型平台充分挖掘大数据价值&#xff0c;利用大数据关联、碰撞、比对&#xff0c;从海量数据中自动筛查出法律监督线索&#xff0c;推送给检察官&#xff0c;有利于提升法律监督质效。 大数据法律监督模型平台建设目标 1、提升监察机关主动监督、精准…

基于DCGM+Prometheus+Grafana的GPU监控方案

目录 前言一、指标导出器1、DCGM&#xff1a;获取远程节点的信息 2、 DCGM-Exporter收集多节点信息更改收集指标 二、 Prometheus - From metrics to insight修改配置文件查看收集结果 三、Grafana仪表板展示导入数据源创建仪表板更多仪表板 前言 基于DCGM&#xff08;NVIDIA …

[SAP ABAP] LIKE TABLE OF

LIKE TABLE OF语句是用来参照结构体(工作区)对象定义内表数据类型的语句 在SAP ABAP中有标准表&#xff0c;排序表和哈希表三种内表数据类型 *定义标准表 DATA: <ty_tab_standard_name> LIKE [STANDARD] TABLE OF <dtype> [WITH NON-UNIQUE KEY <k1 k2 ... kn…

Python自动给课本文字标注拼音

环境&#xff1a; Ubuntu20.04&#xff0c;ubuntu20.04自带python版本 3.8.10&#xff0c;pip的版本是 20.0.2 pip install pypinyin # 安装失败&#xff0c;检查更新pip确保pip是最新版本&#xff1a; pip install --upgrade pip 检查是否安装成功 pip show pypinyin pinyin…

【电路笔记】-求和运算放大器

求和运算放大器 文章目录 求和运算放大器1、概述2、反相求和放大器3、同相求和放大器4、减法放大器5、应用5.1 音频混合器5.2 数模转换器 (DAC)6、总结1、概述 在我们之前有关运算放大器的大部分文章中,仅将一个输入应用于反相或非反相运算放大器的输入。在本文中,将讨论一种…

Python从入门到高手6.1节-字符串的定义与编码

目录 6.1.1 理解字符串 6.1.2 字符串的类型名 6.1.3 字符的数字编码 5.1.4 常用的字符编码 6.1.5 字符串的默认编码 6.1.6 字符串的编码与解码 6.1.7 转义字符详解 6.1.8 对字符串进行迭代 6.1.9 大神薯条老师 6.1.1 理解字符串 在Python中使用英文引号括住的都是字符…

CAS存在的问题及在Java中的解决方式

CAS 介绍 CAS 可以保证对共享变量操作的原子性 CAS全称Compare And Swap&#xff0c;比较与交换&#xff0c;是乐观锁的主要实现方式。CAS在不使用锁的情况下实现多线程之间的变量同步。ReentrantLock内部的AQS和原子类内部都使用了CAS。 CAS算法涉及到三个操作数&#xff1a;需…

ICDE 2024最新论文分享|BEEP:容量约束下能够对抗异常干扰的航运动态定价系统

论文简介 本推文详细介绍了上海交通大学高晓沨教授和陈贵海教授团队发表在顶级学术会议ICDE 2024上发表的最新论文《Corruption Robust Dynamic Pricing in Liner Shipping under Capacity Constraint》&#xff0c;该论文的学生作者为胡永祎、李雪嫣、魏熙锴&#xff0c;合作…

Mac电脑word文档误删,4个方法快速恢复

对于使用Mac的用户来说&#xff0c;丢失重要的Word文档可能会为学习或工作带来严重的影响。不过&#xff0c;幸运的是&#xff0c;关于mac word 文档恢复方法还是有很多的&#xff0c;通常帮助Mac用户轻松找回丢失的word文档。接下来&#xff0c;小编将介绍一些在Mac上恢复丢失…

dayu_widgets-加载组件:MLoading和MLoadingWrapper

一、使用场景 点击按钮加载数据&#xff0c;但是查询数据需要一定的耗时&#xff0c;这段时间需要显示加载中的UI来进行遮罩。 二、使用效果 三、使用案例 # 学习笔记 MLoading控件 import asyncio from PySide2.QtWidgets import QWidget, QApplication, QVBoxLayout, QPus…