【快速選擇】解決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.pswp.cn/news/713489.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/713489.shtml
英文地址,請注明出處:http://en.pswp.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…

字符串函數 sscanf() 詳解

什么是 sscanf() 函數&#xff1f; sscanf() 函數是 C 語言中的一個標準庫函數&#xff0c;它的作用是從一個字符串中按照指定的格式提取數據&#xff0c;并將其存儲到對應的變量中。它的原型如下&#xff1a; int sscanf(const char *str, const char *format, ...);其中&am…

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;留言 主要內容實現了日志代碼設計的實…

在 Spring Boot 3.x 中使用 SpringDoc 2 / Swagger V3

SpringDoc V1 只支持到 Spring Boot 2.x springdoc-openapi v1.7.0 is the latest Open Source release supporting Spring Boot 2.x and 1.x. Spring Boot 3.x 要用 SpringDoc 2 / Swagger V3, 并且包名也改成了 springdoc-openapi-starter-webmvc-ui SpringDoc V2 https://s…

select,poll和epoll有什么區別

它們都是NIO中多路復用的三種實現機制&#xff0c;是由linux操作系統提供的。 用戶空間和內核空間&#xff1a;操作系統為了保證系統安全&#xff0c;將內核分為兩個部分&#xff0c;一個是用戶空間&#xff0c;一個是內核空間。用戶空間不能直接訪問底層的硬件設備&#xff0…

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

IT廉連看——Uniapp——配置文件pages [IT廉連看] 本堂課主要為大家介紹pages.json這個配置文件 一、打開官網查看pages.json可以配置哪些屬性。 下面邊寫邊講解 新建一個home頁面理解一下這句話。 以下一些頁面的通用配置 通用設置里我們可以對導航欄和狀態欄進行一些設…