【快速选择】解决TopK问题

目录

一、什么是TopK问题

二、优先级队列

优先级队列介绍

代码实现

三、使用优先级队列解决TopK问题

四、快速选择算法解决TopK问题

快速选择

图解快速选择

代码解决前k小个元素

五、优先级队列与快速选则算法比较

优先级队列

快速选择


一、什么是TopK问题

TopK问题就是在一个数组中寻找出最小(大)的前K个数,或者寻找出第K大(小)的数

常见TopK问题图示

常见TopK问题链接

最小的K个数_牛客题霸_牛客网给定一个长度为 n 的可能有重复值的数组,找出其中不去重的最小的 k 个数。例如数组元素是。题目来自【牛客题霸】icon-default.png?t=N7T8https://www.nowcoder.com/practice/6a296eb82cf844ca8539b57c23e6e9bf?tpId=295&tqId=23263&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj

寻找第K大_牛客题霸_牛客网

. - 力扣(LeetCode)

二、优先级队列

优先级队列介绍

优先级队列是一种数据结构,它根据元素的优先级来决定元素的插入和删除顺序。以下是一些关键特点:

  1. 基于优先级排序:每个元素在队列中都有一个优先级,优先级最高的元素会首先被移除。
  2. 使用特定数据结构:优先级队列通常可以使用堆(尤其是二叉堆)这种数据结构来实现,以保持队列的有序状态并高效地处理插入和删除操作。
  3. 应用广泛:它在很多算法中有广泛应用,如任务调度、最短路径寻找、事件驱动模拟等场合。
  4. 自定义比较:可以通过仿函数或运算符重载来支持自定义的数据类型和比较函数,从而定义元素的优先级。
  5. Java实现:在Java中,优先级队列可以通过最小堆来实现,其中的元素按照自然顺序或者根据提供的Comparator来确定优先级。
  6. 操作方法:主要操作包括插入元素(入队)和删除最高优先级的元素(出队)。
  7. 性能优化:由于内部结构的优化,即使在大量元素的情况下,优先级队列依然能够快速地确定下一个要处理的元素。

总的来说,优先级队列提供了一种有效的方式来管理那些需要按照特定顺序处理的元素,是许多复杂算法和系统设计中不可或缺的工具。

优先级队列博客

【数据结构】优先级队列(堆)与PriorityQueue_unsortedpriorityqueue增加复杂度为1的getmax-CSDN博客文章浏览阅读504次,点赞2次,收藏2次。比如一组数据 1 2 3 4 5 6,我们将他创建成一个大根堆时,我们先从最后一个位置所在的树开始进行调整,由于我们能获取到数组的长度,且根据堆的性质父亲节点的下标 * 2 + 1就孩子节点下标可知,知道孩子的下标(数组长度-1)就能知道父亲的下标。比如我们在大根堆 4 3 2 2 1 1的堆里插入11,先将11存在最后,然后拿他与父亲比较,如果大就交换,如果不比父亲大那他就是大根堆不需要调整,此时交换后,要继续更换父亲与儿子的位置重复比较交换操作,直到孩子下标小于或者等于0时不在需要调整。_unsortedpriorityqueue增加复杂度为1的getmaxhttps://blog.csdn.net/qq_61903414/article/details/128423670?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522170929235016777224499491%2522%252C%2522scm%2522%253A%252220140713.130102334.pc%255Fblog.%2522%257D&request_id=170929235016777224499491&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~blog~first_rank_ecpm_v1~rank_v31_ecpm-1-128423670-null-null.nonecase&utm_term=%E4%BC%98%E5%85%88%E7%BA%A7%E9%98%9F%E5%88%97&spm=1018.2226.3001.4450

代码实现
import java.util.Arrays;/*** @author 1886**/
public class PriorityQueue <T extends Comparable<T>> {// 优先级队列底层模拟堆的数组private Object[] queue;// 记录当前优先级队列元素个数private int size;private static final int DEFAULT_INITIAL_CAPACITY = 11;/*** 默认构造方法*/public PriorityQueue() {this.queue = new Object[DEFAULT_INITIAL_CAPACITY];}/*** 指定大小* @param capacity*/public PriorityQueue(int capacity) {this.queue = new Object[capacity];}/*** 传入指定数组* @param queue*/public PriorityQueue(T[] queue) {// 1.初始化成员变量this.queue = queue;this.size = queue.length;// 2.将数组进行大根堆调整HeapIfy();}
}
/*** @author 1886**/
public class PriorityQueue <T extends Comparable<T>> {// 优先级队列底层模拟堆的数组private Object[] queue;// 记录当前优先级队列元素个数private int size;private static final int DEFAULT_INITIAL_CAPACITY = 11;/*** 默认构造方法*/public PriorityQueue() {this.queue = new Object[DEFAULT_INITIAL_CAPACITY];}/*** 指定大小* @param capacity*/public PriorityQueue(int capacity) {this.queue = new Object[capacity];}/*** 传入指定数组* @param queue*/public PriorityQueue(T[] queue) {// 1.初始化成员变量this.queue = queue;this.size = queue.length;// 2.将数组进行大根堆调整heapIfy();}/*** 堆化*/private void heapIfy() {for (int parent = (this.size - 1 - 1) >> 1; parent >= 0; parent--) {siftDown(parent, this.size);}}/*** 向下调整* @param parent 父亲节点下标* @param len    向下调整的结束位置*/private void siftDown(int parent, int len) {// 计算出孩子节点位置int child = parent * 2 + 1;// 开始向下调整while (child < len) {// 寻找出两个孩子节点中最大的if (child + 1 < len && ((T)queue[child]).compareTo(((T)queue[child + 1])) < 0) {child++;}// 与父亲节点进行判断,如果孩子节点比父亲节点大就进行调整 否则调整完毕if (((T)queue[child]).compareTo(((T)queue[parent])) < 0) {break;} else {T tmp = (T)queue[child];queue[child] = (T)queue[parent];queue[parent] = tmp;parent = child;child = parent * 2 + 1;}}}
}
import java.util.Arrays;/*** @author 1886**/
public class PriorityQueue <T extends Comparable<T>> {// 优先级队列底层模拟堆的数组private Object[] queue;// 记录当前优先级队列元素个数private int size;private static final int DEFAULT_INITIAL_CAPACITY = 11;/*** 默认构造方法*/public PriorityQueue() {this.queue = new Object[DEFAULT_INITIAL_CAPACITY];}/*** 指定大小* @param capacity*/public PriorityQueue(int capacity) {this.queue = new Object[capacity];}/*** 传入指定数组* @param queue*/public PriorityQueue(T[] queue) {// 1.初始化成员变量this.queue = queue;this.size = queue.length;// 2.将数组进行大根堆调整heapIfy();}/*** 入队操作* @param data 进入优先级队列的数据*/public void offer(T data) {// 如果优先级队列满 进行扩容if (this.size == this.queue.length) {grow();}// 将元素放到末尾this.queue[this.size] = data;// 进行向上调整siftUp(this.size++);}/*** 出队操作* @return*/public T poll() {// 如果为空就返回空if (this.size == 0) return null;// 将堆顶元素与最后一个位置进行交换T top = (T)queue[0];queue[0] = this.queue[this.size - 1];queue[this.size - 1] = top;// 删除元素this.size--;// 向下调整siftDown(0, this.size);// 返回return top;}/*** 排序*/public void sort() {int len = this.size - 1;while (len >= 0) {T tt = (T) queue[0];queue[0] = queue[len];queue[len] = tt;siftDown(0, len--);}}/*** 堆化*/private void heapIfy() {for (int parent = (this.size - 1 - 1) >> 1; parent >= 0; parent--) {siftDown(parent, this.size);}}/*** 向上调整* @param child*/private void siftUp(int child) {// 计算出父亲节点的下标int parent = (child - 1) / 2;// 开始向上调整while (child > 0) {if (((T)queue[child]).compareTo((T)queue[parent]) >= 0) {T tmp = (T)queue[child];queue[child] = (T)queue[parent];queue[parent] = tmp;child = parent;parent = (child - 1) / 2;} else {break;}}}/*** 向下调整* @param parent 父亲节点下标* @param len    向下调整的结束位置*/private void siftDown(int parent, int len) {// 计算出孩子节点位置int child = parent * 2 + 1;// 开始向下调整while (child < len) {// 寻找出两个孩子节点中最大的if (child + 1 < len && ((T)queue[child]).compareTo(((T)queue[child + 1])) < 0) {child++;}// 与父亲节点进行判断,如果孩子节点比父亲节点大就进行调整 否则调整完毕if (((T)queue[child]).compareTo(((T)queue[parent])) < 0) {break;} else {T tmp = (T)queue[child];queue[child] = (T)queue[parent];queue[parent] = tmp;parent = child;child = parent * 2 + 1;}}}/*** 扩容方法*/private void grow() {this.queue = Arrays.copyOf(this.queue, this.queue.length * 2);}private void display() {for (Object x : this.queue) {System.out.println(x);}}
}

三、使用优先级队列解决TopK问题

从上面优先级队列的介绍可知道,我们只需要创建出一个大小为K的优先级队列。当我们求前K的最小的元素时,我们只需要创建出一个大小为K的大根堆。首先让数组中k个元素进入堆中,然后从k+1开始遍历数组,在遍历过程中与堆顶的元素进行比较,这个时候堆顶的元素一定是这个堆中最大的一个,如果此时的值比堆顶的元素小就让这个元素替换堆顶的元素,依次往复,在遍历完整个数组后,这个堆中就会存储前K个最小元素。相反如果要寻找出最小的前K个数就创建大根堆重复操作

前K小的元素

public ArrayList<Integer> GetLeastNumbers_Solution (int[] input, int k) {// write code hereArrayList<Integer> ret = new ArrayList<>();if (k <= 0 || input == null) return ret;PriorityQueue<Integer> queue = new PriorityQueue<>(k, (o1, o2)->{return o2 - o1;});for (int i = 0; i < input.length; i++) {if (i < k) queue.offer(input[i]);else {if (input[i] < queue.peek()) {queue.poll();queue.offer(input[i]);}}}while (!queue.isEmpty()) {ret.add(queue.poll());}return ret;}
import java.util.*;/*** @author 1886**/public class Solution {static class PriorityQueue <T extends Comparable<T>> {// 优先级队列底层模拟堆的数组private Object[] queue;// 记录当前优先级队列元素个数private int size;private static final int DEFAULT_INITIAL_CAPACITY = 11;/*** 默认构造方法*/public PriorityQueue() {this.queue = new Object[DEFAULT_INITIAL_CAPACITY];}/*** 指定大小* @param capacity*/public PriorityQueue(int capacity) {this.queue = new Object[capacity];}/*** 传入指定数组* @param queue*/public PriorityQueue(T[] queue) {// 1.初始化成员变量this.queue = queue;this.size = queue.length;// 2.将数组进行大根堆调整heapIfy();}/*** 入队操作* @param data 进入优先级队列的数据*/public void offer(T data) {// 如果优先级队列满 进行扩容if (this.size == this.queue.length) {grow();}// 将元素放到末尾this.queue[this.size] = data;// 进行向上调整siftUp(this.size++);}/*** 出队操作* @return*/public T poll() {// 如果为空就返回空if (this.size == 0) return null;// 将堆顶元素与最后一个位置进行交换T top = (T)queue[0];queue[0] = this.queue[this.size - 1];queue[this.size - 1] = top;// 删除元素this.size--;// 向下调整siftDown(0, this.size);// 返回return top;}/*** 排序*/public void sort() {int len = this.size - 1;while (len >= 0) {T tt = (T) queue[0];queue[0] = queue[len];queue[len] = tt;siftDown(0, len--);}}/*** 堆化*/private void heapIfy() {for (int parent = (this.size - 1 - 1) >> 1; parent >= 0; parent--) {siftDown(parent, this.size);}}/*** 向上调整* @param child*/private void siftUp(int child) {// 计算出父亲节点的下标int parent = (child - 1) / 2;// 开始向上调整while (child > 0) {if (((T)queue[child]).compareTo((T)queue[parent]) >= 0) {T tmp = (T)queue[child];queue[child] = (T)queue[parent];queue[parent] = tmp;child = parent;parent = (child - 1) / 2;} else {break;}}}/*** 向下调整* @param parent 父亲节点下标* @param len    向下调整的结束位置*/private void siftDown(int parent, int len) {// 计算出孩子节点位置int child = parent * 2 + 1;// 开始向下调整while (child < len) {// 寻找出两个孩子节点中最大的if (child + 1 < len && ((T)queue[child]).compareTo(((T)queue[child + 1])) < 0) {child++;}// 与父亲节点进行判断,如果孩子节点比父亲节点大就进行调整 否则调整完毕if (((T)queue[child]).compareTo(((T)queue[parent])) < 0) {break;} else {T tmp = (T)queue[child];queue[child] = (T)queue[parent];queue[parent] = tmp;parent = child;child = parent * 2 + 1;}}}public T peek() {return this.size == 0 ? null : (T)queue[0];}/*** 扩容方法*/private void grow() {this.queue = Arrays.copyOf(this.queue, this.queue.length * 2);}private void display() {for (Object x : this.queue) {System.out.println(x);}}
}/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param input int整型一维数组 * @param k int整型 * @return int整型ArrayList*/public ArrayList<Integer> GetLeastNumbers_Solution (int[] input, int k) {// write code hereArrayList<Integer> ans = new ArrayList<>();if (k <= 0 || input == null) return ans;PriorityQueue<Integer> queue = new PriorityQueue<>(k);for (int i = 0; i < input.length; i++) {if (i < k) queue.offer(input[i]);else if (input[i] < queue.peek()) {queue.poll();queue.offer(input[i]);}}while (queue.peek() != null) {ans.add(queue.poll());}return ans;}
}

四、快速选择算法解决TopK问题

快速选择

快速选择算法(Quickselect)是用于在未排序的数组中查找第k小或第k大元素的高效算法,它的时间复杂度为O(n)。该算法与快速排序有密切的联系,但它不对整个数组进行完整的排序,而是只关注于找到所需的特定顺序的元素。以下是它的一些关键点:

  1. 基本思想
  • 选择一个基准值(pivot),按照这个基准值将数组分为两部分,左侧部分的所有元素都小于等于基准值,右侧部分的所有元素都大于基准值。
  1. 递归搜索
  • 确定基准值的位置后,根据k与基准值的位置关系,选择数组的哪一部分继续进行递归搜索。如果k小于基准值的索引,则在第一部分(小于等于基准值的部分)继续搜索;否则,在第二部分(大于基准值的部分)继续搜索。
  1. 时间复杂度
  • 快速选择算法的平均时间复杂度为O(n),但最坏情况下的时间复杂度会退化到O(n^2)。尽管如此,由于其不需要完全排序数组,它在实际操作中通常比完全的排序算法更加高效。
  1. 实际应用
  • 快速选择算法及其变种是在实际应用中最常使用的高效选择算法之一,尤其适用于解决Top K问题等场景。

总的来说,快速选择算法是一种基于快速排序的选择算法,它高效地解决了在不完全排序的数组中寻找特定顺序元素的问题,并因此在各种算法竞赛和实际应用场景中得到了广泛的使用。

图解快速选择

图解

对下面这个数组寻找到前k小的元素

首先我随机生成一个下标指向一个基准元素

然后使用一个指针指向开始位置依次往后遍历,如果当前元素比基准元素大则将该元素放在末尾,也就是基准元素后面,如果比当前元素小则将他放在基准元素前面

此时遍历指针i指向的值比基准元素大,此时需要执行以下操作进行交换:swap(arr[--e], arr[i])

此时进行将遍历指针指向的元素与基准元素进行比较依次重复此操作,当遍历指针指向的元素比基准元素小时执行:swap(arr[i++], arr[++s]) ,当与基准元素相等时只需要执行i++即可。当遍历指针与末尾指针e相遇时即可停止。

此时在l到s,e到r重复执行上述操作,知道l >= r时结束递归就是基于快速选择的快排算法。但是此时我们需要寻找前k小个元素,而数组已经被分成了三部分

此时我们可以通过判断k是否小于等于a,如果k小于等于a那么前k小的元素一定是在左边这段区域,如果k小于等于a+b时说明此时第k小就在中间这个区域,只需要返回他就可以。如果上面两种情况都不成立,那么我们只需要区右边区域找到第k - a - b个最小的元素,找到该元素后,该元素之前的元素就是最小的K个数

代码解决前k小个元素

最小的K个数_牛客题霸_牛客网给定一个长度为 n 的可能有重复值的数组,找出其中不去重的最小的 k 个数。例如数组元素是。题目来自【牛客题霸】icon-default.png?t=N7T8https://www.nowcoder.com/practice/6a296eb82cf844ca8539b57c23e6e9bf?tpId=295&tqId=23263&ru=/exam/oj&qru=/ta/format-top101/question-ranking&sourceUrl=%2Fexam%2Foj

#include <vector>
class Solution {
public:
/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可** * @param input int整型vector * @param k int整型 * @return int整型vector*/
int rand_num(int l, int r) {srand(time(0));return rand() % (r - l + 1) + l;
}int qselect(vector<int>& arr, int l, int r, int k) {if (l >= r) return arr[l];int i = l, s = l - 1, e = r + 1, x = arr[rand_num(l,r)];while (i < e) {if (arr[i] > x) swap(arr[i], arr[--e]);else if (arr[i] < x) swap(arr[i++], arr[++s]);else i++;}int a = s - l + 1, b = e - s - 1;if (a >= k) return qselect(arr, l, s, k);else if (a + b >= k) return x;else return qselect(arr, e, r, k - a - b);
}vector<int> GetLeastNumbers_Solution(vector<int>& input, int k) {// write code herevector<int> ans(k);if (k <= 0 || input.size() < 1) return ans;qselect(input, 0, input.size() - 1, k);for (int i = 0; i < k; i++) ans[i] = input[i];return ans;
}
};

null有一个整数数组,请你根据快速排序的思路,找出数组中第 k 大的数。 给定一个整数数组。题目来自【牛客题霸】icon-default.png?t=N7T8https://www.nowcoder.com/practice/e016ad9b7f0b45048c58a9f27ba618bf?tpId=295&tqId=44581&ru=%2Fpractice%2F6a296eb82cf844ca8539b57c23e6e9bf&qru=%2Fta%2Fformat-top101%2Fquestion-ranking&sourceUrl=%2Fexam%2Foj

import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*** @param a int整型一维数组* @param n int整型* @param K int整型* @return int整型*/private int randNum(int l, int r) {Random random = new Random();return l + random.nextInt(r - l + 1);}private void swap(int[] arr, int i, int j) {int t = arr[i];arr[i] = arr[j];arr[j] = t;}private int qSelect(int[] arr, int l, int r, int k) {if (l >= r) return arr[l];int i = l, s = l - 1, e = r + 1, x = arr[randNum(l, r)];while (i < e) {if (arr[i] > x) swap(arr, i, --e);else if (arr[i] < x) swap(arr, ++s, i++);else i++;}int c = r - e + 1, b = e - s - 1;if (c >= k) return qSelect(arr, e, r, k);else if (b + c >= k) return x;else return qSelect(arr, l, s, k - c - b); }public int findKth (int[] a, int n, int K) {// write code herereturn qSelect(a, 0, n - 1, K);}
}

五、优先级队列与快速选则算法比较

优先级队列

使用优先级队列(通常实现为堆)解决TopK问题的时间复杂度是O(NlogK)。具体分析如下:

  1. 建堆:首先对K个元素进行建堆操作,建堆的时间复杂度是O(K)。这是因为堆的构建过程涉及到对K个元素进行排序,以形成一个最大堆或最小堆。
  2. 维护堆:然后遍历剩余的N-K个元素,对于每个元素,执行堆调整操作以维护堆的性质。每次插入或删除操作的时间复杂度是O(logK),因为堆的高度大约是logK,而单次堆调整的时间复杂度与堆的高度成正比。因此,对于N-K个元素的遍历,总的时间复杂度是O((N-K)logK)。
  3. 总时间复杂度:综合以上两个步骤,总的时间复杂度是O(K + (N-K)logK),由于通常情况下K远小于N,可以简化为O(NlogK)。
快速选择

快速选择算法的平均时间复杂度是 O(N),但最坏情况下的时间复杂度是 O(N^2)。以下是关于快速选择算法时间复杂度的详细分析:

  1. 平均时间复杂度
  • 在平均情况下,快速选择算法的时间复杂度是O(N)。这是因为每次分区操作平均只需要遍历数组的一半长度。在快速选择算法中,我们选择一个枢纽元素(pivot),并将数组分为两部分,一部分包含小于枢纽的元素,另一部分包含大于枢纽的元素。这个过程与快速排序相似,但是快速选择只递归地处理包含第K小元素的那一部分数组,而不是整个数组。由于每次递归调用处理的数组大小大约减半,所以平均时间复杂度为O(N)。
  1. 最坏情况时间复杂度
  • 在最坏的情况下,如果每次选择的枢纽都是最大或最小元素,那么每次分区操作只能减少一个元素的大小,导致需要进行N次分区操作,因此最坏情况下的时间复杂度是O(N^2)。为了减少这种情况的发生,可以通过随机选择枢纽来提高算法的效率。
  1. 优化措施
  • 为了优化快速选择算法并避免最坏情况的发生,可以采用“中位数的中位数”作为枢纽,这种方法被称为BFPRT算法。通过计算近似中位数并将其作为枢纽,可以有效地将数组分为大致相等的两部分,从而保持算法的平均时间复杂度。
  1. 数学推导
  • 快速选择算法的时间复杂度也可以通过数学归纳法进行推导。可以将数组分成若干组,每组选取中位数,然后从中选取中位数的中位数作为枢纽。这样的分组策略可以保证至少有一部分数组的大小显著减少,从而在数学上证明算法的平均时间复杂度为O(N)。具体的推导过程涉及到递归式和分组策略的详细分析。

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

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

相关文章

Linux Seccomp 简介

文章目录 一、简介二、架构三、Original/Strict Mode四、Seccomp-bpf五、seccomp系统调用六、Linux Capabilities and Seccomp6.1 Linux Capabilities6.2 Linux Seccomp 参考资料 一、简介 Seccomp&#xff08;secure computing&#xff09;是Linux内核中的一项计算机安全功能…

软考 系统分析师系列知识点之需求获取(7)

所属章节&#xff1a; 第11章. 软件需求工程 第2节. 需求获取 需求获取是一个确定和理解不同的项目干系人的需求和约束的过程。需求获取是一件看上去很简单、做起来却很难的事情。需求获取是否科学、准备是否充分&#xff0c;对获取出来的结果影响很大&#xff0c;这是因为大部…

Leetcode刷题(十八)

一、203. 移除链表元素 代码&#xff1a; class Solution:def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:while head and head.val val:head head.nextpre, cur head, headwhile cur:if cur.val val:pre.next cur.nextelse:p…

全闪存加速信创数据库数仓一体机解决方案

立足行业&#xff0c;深度解读 在新的大数据生态中&#xff0c;传统数据库/数据仓库技术和产品成为大数据生态中的组成部分&#xff0c;对结构化数据的存储和计算进行支撑。 数据库&数据仓库一体机是高端、核心数据管理产品&#xff0c;在我国党政、银行、交通等领域广泛…

nginx出现 “414 request-uri too large”

nginx出现 “414 request-uri too large” 1.修改传参方式 POST 2.字段能变成后端获取就自己获取&#xff0c;不用前端传 3.修改nginx配置&#xff0c;添加client_header_buffer_size 512k;large_client_header_buffers 4 512k;配置

2022年CSP-J认证 CCF信息学奥赛C++ 中小学初级组 第一轮真题-完善程序题解析

2022CCF认证第一轮&#xff08;CSP-J&#xff09;真题 三、完善程序题 第一题 枚举因数 从小到大打印正整数n的所有正因数。试补全枚举程序 #include <iostream> using namespace std;int main(){int n;cin >> n;vector<int> fac;fac.reserve((int)ceil(…

C++的引用

目录 引用 常引用 指针与引用的关系 小拓展 引用的价值 做形参 传值、传引用的效率比较 做返回值 函数传值返回 函数传引用返回&#xff08;错误示范&#xff09; 野引用&#xff08;错误示范&#xff09; 引用的正常应用 值和引用作为返回值类型的性能比较 引用和…

spring-boot-starter-parent和spring-boot-dependencies介绍

springboot项目的pom文件中&#xff0c;我们经常看见这样(下图)两种springboot的版本依赖管理方式&#xff1b;图片中的这两种依赖声明方式任意用其中一种都可以。文章后面会简单阐述一下区别和使用场景。 事例中完整的pom文件 <?xml version"1.0" encoding&quo…

阿尔卡特Adixen ADP/ADS 系列 2 干泵使用说明

阿尔卡特Adixen ADP/ADS 系列 2 干泵使用说明

HTML教程(3)——常用标签(1)

一、图片标签 1.场景&#xff1a;在网页中显示图片 2.基本写法&#xff1a; <img src""> 3.特点&#xff1a;单标签&#xff0c;img标签需要展示对应的效果&#xff0c;需要借助其属性进行设置 4常用属性&#xff1a; src&#xff1a;其属性值为目标图片…

【框架】Spring 框架重点解析

Spring 框架重点解析 1. Spring 框架中的单例 bean 是线程安全的吗&#xff1f; 不是线程安全的 Spring 框架中有一个 Scope 注解&#xff0c;默认的值是 singleton&#xff0c;即单例的&#xff1b;因为一般在 Spring 的 bean 对象都是无状态的&#xff08;在生命周期中不被…

解决Mybatis报Type interface *.*Mapper is not known to the MapperRegis

解决Mybatis报Type interface *.*Mapper is not known to the MapperRegis 问题发现问题解决方法一&#xff1a;检查Mapper文件的namespace路径是否正确方法二&#xff1a;使用其他方法是否正确 问题发现 在学习MyBatis框架的时候&#xff0c;不使用 XML 构建 SqlSessionFacto…

Project_Euler-44 题解

Project_Euler-44 题解 题目 思路 题目给出了一个性质&#xff0c;让我在对应性质的数据中找出目标值&#xff0c;这种问题首先想到的就是枚举。 我们可以枚举 P k P_k Pk​ &#xff0c;对于每一个 P k P_k Pk​ &#xff0c;我们再枚举 P j P_j Pj​&#xff0c; P j P_…

【ue5】滑铲系统蓝图笔记

大致逻辑如下&#xff1a; 一、导入动画 滑铲蹲待机蹲行走 导入到文件夹中 可以右键设置颜色&#xff0c;便于区分。 二、调整动画 1.启动根运动 启动根运动后&#xff0c;人物才可以位移&#xff0c;不然只能在原地。 打开动画序列&#xff0c;勾选启用根运动Enabled…

用node或者vscode开启一个简单的本地server服务器,加载html网页

使用Live Server 想要加载本地html页面可以快速能让它在你本地浏览器中打开&#xff0c;可以有好多种方式&#xff0c;如果你有使用vscode&#xff0c;可以安装一个插件&#xff1a;Live Server&#xff0c;然后直接在vscode中直接右键就可以开启这个服务&#xff1a; 安装好之…

C++基于多设计模式下的同步异步日志系统day2

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;C基于多设计模式下的同步&异步日志系统 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 主要内容实现了日志代码设计的实…

select,poll和epoll有什么区别

它们都是NIO中多路复用的三种实现机制&#xff0c;是由linux操作系统提供的。 用户空间和内核空间&#xff1a;操作系统为了保证系统安全&#xff0c;将内核分为两个部分&#xff0c;一个是用户空间&#xff0c;一个是内核空间。用户空间不能直接访问底层的硬件设备&#xff0…

IT廉连看——Uniapp——配置文件pages

IT廉连看——Uniapp——配置文件pages [IT廉连看] 本堂课主要为大家介绍pages.json这个配置文件 一、打开官网查看pages.json可以配置哪些属性。 下面边写边讲解 新建一个home页面理解一下这句话。 以下一些页面的通用配置 通用设置里我们可以对导航栏和状态栏进行一些设…

Android修行手册-集成Python开发环境

Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC &#x1f449;关于作者 专注于Android/Unity和各种游戏开发技巧&#xff0c;以及各种资源分…

Apache Flink连载(三十五):Flink基于Kubernetes部署(5)-Kubernetes 集群搭建-1

🏡 个人主页:IT贫道-CSDN博客 🚩 私聊博主:私聊博主加WX好友,获取更多资料哦~ 🔔 博主个人B栈地址:豹哥教你学编程的个人空间-豹哥教你学编程个人主页-哔哩哔哩视频 目录 ​编辑