動態規劃從入門到精通

目錄

動態規劃的詳解

動態規劃的應用

? ???機器人到達指定位置數

? ? ?換錢的最少貨幣數

? ? ?排成一條線的紙牌博弈問題

? ? ?象棋中馬的跳法

? ? ?Bob的生存概率?

? ? ?換錢的方法數?

動態規劃的總結

動態規劃的詳解

? ? ? ?暴力嘗試遞歸操作中有很多重復計算的操作,浪費時間。動態規劃就是減少暴力嘗試中重復計算的技巧,這種技巧就是一個大型套路,先寫出用嘗試的思路解決問題的遞歸函數,而不用操心時間復雜度,這個過程是無可替代的,沒有套路的,只能依靠個人智慧或者足夠多的經驗。

? ? ? ?但是怎么把嘗試的版本,優化成動態規劃,是有固定套路的,大體步驟如下:

? ? ? ?(1)找到什么可變參數可以代表一個遞歸狀態,也就是哪些參數一旦確定,返回值就確定了;

? ? ? ?(2)把可變參數的所有組合映射成一張表,有 1 個可變參數就是一維表,2 個可變參數就是二維表,......

? ? ? ?(3)最終答案要的是表中的哪個位置,在表中標出;

? ? ? ?(4)根據遞歸過程的 base case,把這張表的最簡單、不需要依賴其他位置的那些位置填好值;

? ? ? ?(5)根據遞歸過程非base case的部分,也就是分析表中的普遍位置需要怎么計算得到,那么這張表的填寫順序也就確定了;

? ? ? ?(6)填好表,返回最終答案在表中位置的值;

? ? ? ?對于代碼方面的修改也是有固定套路的,對于記憶化搜索的方法就是首先寫出嘗試的思路解決問題的遞歸函數,然后在此基礎上先改成記憶化搜索的程序,也就是添加上數組,記錄計算過的值,避免出現重復計算的過程,后面執行程序時對于計算過的直接使用不再重復計算。

? ? ? ?嚴格位置表依賴的方法是將按照上面的步驟將目標值和初始確定的值在程序中先確定出來,然后對遞歸程序進行適當更改即可完成。

動態規劃的應用

? ???機器人到達指定位置數

? ? ?【題目】 假設有排成一行的N個位置,記為1~N,N 一定大于或等于 2。開始時機器人在其中的 M 位置上(M一定是 1~N 中的一個),機器人可以往左走或者往右走,如果機器人來到1位置,那么下一步只能往右來到2 位置;如果機器人來到N位置,那么下一步只能往左來到 N-1 位置。規定機器人必須走K步,最終能來到P位置(P 也一定是 1~N 中的一個)的方法有多少種。給定四個參數 N、M、K、P,返回方法數。

? ? ?【舉例】 N=5,M=2,K=3,P=3 上面的參數代表所有位置為1 2 3 4 5。機器人最開始在2位置上,必須經過3步,最后到達3位置。走的方法只有如下3種: (1)從2到1,從1到2,從2到3 (2)從2到3,從3到2,從2到3 (3)從2到3,從3到4,從4到3。所以返回方法數3。 N=3,M=1,K=3,P=3 上面的參數代表所有位置為1 2 3。機器人最開始在1位置上,必須經過3步,最后到達3位置。怎么走也不可能,所以返回方法數0。

    public static int ways1(int N, int M, int K, int P) {//使用暴力遞歸的方式解決問題,時間復雜度能達到O(2^k)// 參數無效直接返回0if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) {return 0;}// 總共N個位置,從M點出發,還剩K步,返回最終能達到P的方法數return walk(N, M, K, P);}// N : 位置為1 ~ N,固定參數// cur : 當前在cur位置,可變參數// rest : 還剩res步沒有走,可變參數// P : 最終目標位置是P,固定參數// 該函數的含義:只能在1~N這些位置上移動,當前在cur位置,走完rest步之后,停在P位置的方法數作為返回值返回public static int walk(int N, int cur, int rest, int P) {// 如果沒有剩余步數了,當前的cur位置就是最后的位置// 如果最后的位置停在P上,那么之前做的移動是有效的// 如果最后的位置沒在P上,那么之前做的移動是無效的if (rest == 0) {return cur == P ? 1 : 0;}// 如果還有rest步要走,而當前的cur位置在1位置上,那么當前這步只能從1走向2// 后續的過程就是,來到2位置上,還剩rest-1步要走if (cur == 1) {return walk(N, 2, rest - 1, P);}// 如果還有rest步要走,而當前的cur位置在N位置上,那么當前這步只能從N走向N-1// 后續的過程就是,來到N-1位置上,還剩rest-1步要走if (cur == N) {return walk(N, N - 1, rest - 1, P);}// 如果還有rest步要走,而當前的cur位置在中間位置上,那么當前這步可以走向左,也可以走向右// 走向左之后,后續的過程就是,來到cur-1位置上,還剩rest-1步要走// 走向右之后,后續的過程就是,來到cur+1位置上,還剩rest-1步要走// 走向左、走向右是截然不同的方法,所以總方法數要都算上return walk(N, cur + 1, rest - 1, P) + walk(N, cur - 1, rest - 1, P);}public static int ways2(int N, int M, int K, int P) {//使用記憶化搜索的方式解決問題,時間復雜度為O(M*K)// 參數無效直接返回0if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) {return 0;}int[][] dp = new int[K + 1][N + 1];//定義一個數組存放計算過的內容,作為緩存結構for(int i=0;i<=k;i++){for(int j=0;j<=N;j++){dp[i][j]= -1;}}// 總共N個位置,從M點出發,還剩K步,返回最終能達到P的方法數return walk2(N, M, K, P , dp);}// N : 位置為1 ~ N,固定參數// cur : 當前在cur位置,可變參數// rest : 還剩res步沒有走,可變參數// P : 最終目標位置是P,固定參數// 該函數的含義:只能在1~N這些位置上移動,當前在cur位置,走完rest步之后,停在P位置的方法數作為返回值返回public static int walk2(int N, int cur, int rest, int P,int[][] dp) {if(dp[rest][cur]!=-1){//如果某個值已經計算過,不需要再重復計算,直接返回return dp[rest][cur];}//還沒有計算過,每次返回之前把答案記錄下來if (rest == 0) {dp[rest][cur] = cur == P ? 1 : 0;return dp[rest][cur];}// 如果還有rest步要走,而當前的cur位置在1位置上,那么當前這步只能從1走向2// 后續的過程就是,來到2位置上,還剩rest-1步要走if (cur == 1) {dp[rest][cur] =walk2(N, 2, rest - 1, P);}// 如果還有rest步要走,而當前的cur位置在N位置上,那么當前這步只能從N走向N-1// 后續的過程就是,來到N-1位置上,還剩rest-1步要走else if (cur == N) {dp[rest][cur] =  walk2(N, N - 1, rest - 1, P);}else{dp[rest][cur] = walk2(N, cur + 1, rest - 1, P) + walk2(N, cur - 1, rest - 1, P);}return dp[rest][cur];}public static int ways3(int N, int M, int K, int P) {//嚴格位置表依賴的方式// 參數無效直接返回0if (N < 2 || K < 1 || M < 1 || M > N || P < 1 || P > N) {return 0;}int[][] dp = new int[K + 1][N + 1];//定義一個數組存放計算過的內容dp[0][P] = 1;//終點的位置在格子中標出來for (int i = 1; i <= K; i++) {//然后從第一行第一列開始,下面的過程根據遞歸的依賴性,進行改編for (int j = 1; j <= N; j++) {if (j == 1) {dp[i][j] = dp[i - 1][2];} else if (j == N) {dp[i][j] = dp[i - 1][N - 1];} else {dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j + 1];}}}return dp[K][M];}

? ? ?換錢的最少貨幣數

? ? ?【題目】給定數組 arr,arr中所有的值都為正數且不重復。每個值代表一種面值的貨幣,每種面值的貨幣可以使用任意張,再給定一個整數 aim,代表要找的錢數,求組成aim的最少貨幣數。

? ? ?【舉例】arr=[5,2,3],aim=20。4 張 5 元可以組成 20 元,其他的找錢方案都要使用更多張的貨幣,所以返回 4。arr=[5,2,3],aim=0。不用任何貨幣就可以組成0元,返回 0。arr=[3,5],aim=2。根本無法組成2元,錢不能找開的情況下默認返回-1。

    public static int minCoins1(int[] arr, int aim) {//暴力遞歸方式求解if (arr == null || arr.length == 0 || aim < 0) {return -1;}return process(arr, 0, aim);}// 當前考慮的面值是arr[i],還剩rest的錢需要找零// 如果返回-1說明自由使用arr[i..N-1]面值的情況下,無論如何也無法找零rest// 如果返回不是-1,代表自由使用arr[i..N-1]面值的情況下,找零rest需要的最少張數public static int process(int[] arr, int i, int rest) {if(rest < 0){return -1;}if(rest == 0){return 0;}//rest>0但是沒有錢if(i == arr.length){return -1;}//rest > 0并且也有硬幣,有兩種選擇int p1 = process(arr,i+1,rest);//表示不要下一個硬幣int p2Next = process(arr,i+1,rest-arr[i]);//表示要下一個硬幣if(p1 == -1&&p2Next == -1){return -1;}else{if(p1 = -1){return p2Next +1;//加1是因為p2Next表示要下一個硬幣}if(p2 = -1){return p1;}return Math.min(p1,p2Next+1);}}public static int minCoins2(int[] arr, int aim) {//記憶化搜索的動態規劃的方式求解if (arr == null || arr.length == 0 || aim < 0) {return -1;}int[][] dp = new int[arr.length+1][aim+1];//建立數組記錄計算的過程for(int i = 0;i <= arr.length; i++){//初始化for(int j = 0;j <= aim; j++){dp[i][j] = -2;}}return process2(arr, 0, aim,dp);}// 當前考慮的面值是arr[i],還剩rest的錢需要找零// 如果返回-1說明自由使用arr[i..N-1]面值的情況下,無論如何也無法找零rest// 如果返回不是-1,代表自由使用arr[i..N-1]面值的情況下,找零rest需要的最少張數public static int process2(int[] arr, int i, int rest , int[][] dp) {if(rest < 0){return -1;}if(dp[i][rest]!=-2){//如果已經計算過,直接返回return dp[i][rest];}if(rest == 0){dp[i][rest] = 0;}else if(i == arr.length){dp[i][rest] = -1;}else{//rest > 0并且也有硬幣,有兩種選擇int p1 = process2(arr,i+1,rest,dp);//表示不要下一個硬幣int p2Next = process2(arr,i+1,rest-arr[i],dp);//表示要下一個硬幣if(p1 == -1&&p2Next == -1){dp[i][rest] = -1;}else{if(p1 = -1){dp[i][rest] = p2Next +1;//加1是因為p2Next表示要下一個硬幣}else if(p2 = -1){dp[i][rest] = p1;}else{dp[i][rest] = Math.min(p1,p2Next+1);}}}return dp[i][rest];}public static int minCoins3(int[] arr, int aim) {//嚴格表結構的動態規劃方式求解if (arr == null || arr.length == 0 || aim < 0) {return -1;}int N = arr.length;int[][] dp = new int[N + 1][aim + 1];// 設置最后一排的值,除了dp[N][0]為0之外,其他都是-1//一些知道的初始位置設置好for (int col = 1; col <= aim; col++) {dp[N][col] = -1;}for(int row = 0;row <= N;row++){dp[row][0] = 0;}//把遞歸的過程放過來,然后根據表結構進行適當的改動for(int i = N-1; i>= 0;i--){for(int rest = 1;rest <= aim;rest++){int p1 = dp[i+1][rest];int p2Next = -1;if(rest - arr[i] >= 0){p2Next = dp[i+1][rest - arr[i]];}if(p1 == -1&&p2Next == -1){dp[i+1][rest] = -1;}else{if(p1 = -1){dp[i+1][rest] = p2Next +1;//加1是因為p2Next表示要下一個硬幣}if(p2 = -1){dp[i+1][rest] = p1;}dp[i+1][rest] = Math.min(p1,p2Next+1);}}}return dp[0][aim];}

? ? ?排成一條線的紙牌博弈問題

? ? ?【題目】給定一個整型數組 arr,代表數值不同的紙牌排成一條線。玩家A和玩家B依次拿走每張紙牌,規定玩家A先拿,玩家B后拿,但是每個玩家每次只能拿走最左或最右的紙牌,玩家A和玩 家B都絕頂聰明。請返回最后獲勝者的分數。

? ? ?【舉例】arr=[1,2,100,4]。開始時,玩家A只能拿走1或4。如果玩家A拿走1,則排列變為[2,100,4],接下來玩家B可以拿走2或4,然后繼續輪到玩家A。如果開始時玩家A拿走4,則排列變為[1,2,100],接下來玩家B可以拿走1或100,然后繼續輪到玩家A。玩家A作為絕頂聰明的人不會先拿4,因為拿4之后,玩家B將拿走100。所以玩家A會先拿1,讓排列變為[2,100,4],接下來玩家B 不管怎么選,100都會被玩家A拿走。玩家A會獲勝,分數為101。所以返回101。arr=[1,100,2]。 開始時,玩家A不管拿1還是2,玩家B作為絕頂聰明的人,都會把100拿走。玩家B會獲勝,分數為 100。所以返回100。

    public static int win1(int[] arr) {//暴力遞歸的方式求解if (arr == null || arr.length == 0) {return 0;}return Math.max(f(arr, 0, arr.length - 1), s(arr, 0, arr.length - 1));//先手和后手誰的分數多,誰獲勝}public static int f(int[] arr, int i, int j) {//先手函數if (i == j) {//如果只有一個數字,先手直接拿了return arr[i];}return Math.max(arr[i] + s(arr, i + 1, j), arr[j] + s(arr, i, j - 1));//如果不是只有一個數字,那么先手選擇拿左邊和右邊兩種情況下,最大的那一種情況}public static int s(int[] arr, int i, int j) {//后手函數if (i == j) {//如果只有一張牌,后手拿不到return 0;}return Math.min(f(arr, i + 1, j), f(arr, i, j - 1));//如果不只有一張牌,后手只能拿到剩下情況下最小的那種情況}//在范圍上嘗試的模型,行是不可能超過列的,左下角區域都是不存在的,先填對角線//動態規劃一定要畫圖操作,用最基礎的遞歸操作進行畫圖,找到格子之間的關系,然后遞歸的過程進行改寫public static int win2(int[] arr) {if (arr == null || arr.length == 0) {return 0;}//建立兩個格子int[][] f = new int[arr.length][arr.length];int[][] s = new int[arr.length][arr.length];for (int j = 0; j < arr.length; j++) {f[j][j] = arr[j];//對角線元素填上s[j][j] = 0;for (int i = j - 1; i >= 0; i--) {//只對右上角進行操作,兩個表互相依賴f[i][j] = Math.max(arr[i] + s[i + 1][j], arr[j] + s[i][j - 1]);s[i][j] = Math.min(f[i + 1][j], f[i][j - 1]);}}return Math.max(f[0][arr.length - 1], s[0][arr.length - 1]);}

? ? ?象棋中馬的跳法

? ? ?【題目】請同學們自行搜索或者想象一個象棋的棋盤,然后把整個棋盤放入第一象限,棋盤的最左下角是(0,0)位置。那么整個棋盤就是橫坐標上9條線、縱坐標上10條線的一個區域。給你三個 參數,x,y,k,返回如果“馬”從(0,0)位置出發,必須走k步,最后落在(x,y)上的方法數有多少種?

    public static int getWays(int x, int y, int step) {//暴力遞歸的方式求解return process(x, y, step);}public static int process(int x, int y, int step) {if (x < 0 || x > 8 || y < 0 || y > 9) {return 0;}//x,y位置越界,0種方法,無法到達if (step == 0) {//不能再動了return (x == 0 && y == 0) ? 1 : 0;//一開始在(0,0)位置,如果想要到達的就是(0,0)位置,那么已經到達,一種方法,如果不是那么無法到達}//不越界也可以跳,把跳一步可以跳到(x,y)位置的情況都寫出來return process(x - 1, y + 2, step - 1)+ process(x + 1, y + 2, step - 1)+ process(x + 2, y + 1, step - 1)+ process(x + 2, y - 1, step - 1)+ process(x + 1, y - 2, step - 1)+ process(x - 1, y - 2, step - 1)+ process(x - 2, y - 1, step - 1)+ process(x - 2, y + 1, step - 1);}public static int dpWays(int x, int y, int step) {//嚴格表結構的動態規劃方式求解//有三個可變參數,那么建立一個三維立體,其它的按照遞歸的程序和立體圖形各個之間的關系進行改寫if (x < 0 || x > 8 || y < 0 || y > 9 || step < 0) {return 0;}//這個立體之外的部分都是0int[][][] dp = new int[9][10][step + 1];//建立一個立體dp[0][0][0] = 1;//第0層的面只有(0,0)位置是1,其它都是0for (int h = 1; h <= step; h++) {//每一層處理,每一層只依賴于下一層的內容for (int r = 0; r < 9; r++) {for (int c = 0; c < 10; c++) {dp[r][c][h] += getValue(dp, r - 1, c + 2, h - 1);dp[r][c][h] += getValue(dp, r + 1, c + 2, h - 1);dp[r][c][h] += getValue(dp, r + 2, c + 1, h - 1);dp[r][c][h] += getValue(dp, r + 2, c - 1, h - 1);dp[r][c][h] += getValue(dp, r + 1, c - 2, h - 1);dp[r][c][h] += getValue(dp, r - 1, c - 2, h - 1);dp[r][c][h] += getValue(dp, r - 2, c - 1, h - 1);dp[r][c][h] += getValue(dp, r - 2, c + 1, h - 1);}}}return dp[x][y][step];}public static int getValue(int[][][] dp, int row, int col, int step) {//防止越界的函數,如果越界取0,如果沒有越界,拿到相應位置的值if (row < 0 || row > 8 || col < 0 || col > 9) {return 0;}return dp[row][col][step];}

? ? ?Bob的生存概率?

? ? ?【題目】給定五個參數n,m,i,j,k。表示在一個N*M的區域,Bob處在(i,j)點,每次Bob等概率的向上、下、左、右四個方向移動一步,Bob必須走K步。如果走完之后,Bob還停留在這個區域上, 就算Bob存活,否則就算Bob死亡。請求解Bob的生存概率,返回字符串表示分數的方式。

   public static String bob1(int N, int M, int i, int j, int K) {//暴力遞歸的方式求解long all = (long) Math.pow(4, K);//總的方法數位4的k次方,因為每一個位置的選擇有4種,一共走k步long live = process(N, M, i, j, K);long gcd = gcd(all, live);//概率就是活下來的除以總的return String.valueOf((live / gcd) + "/" + (all / gcd));}public static long process(int N, int M, int row, int col, int rest) {if (row < 0 || row == N || col < 0 || col == M) {return 0;}//如果越界,死亡if (rest == 0) {//如果已經走完也沒有越界,活下來return 1;}//Bob總體活下來的方法數,等于他往上,往下,往左,往右分別走一步且活下來的方法數long live = process(N, M, row - 1, col, rest - 1);live += process(N, M, row + 1, col, rest - 1);live += process(N, M, row, col - 1, rest - 1);live += process(N, M, row, col + 1, rest - 1);return live;}public static long gcd(long m, long n) {//求最大公約數return n == 0 ? m : gcd(n, m % n);}public static String bob2(int N, int M, int i, int j, int K) {//嚴格表結構的動態規劃的方式,同樣的按照遞歸的方式,分析立體結構的關系求解int[][][] dp = new int[N + 2][M + 2][K + 1];//建立一個立體for (int row = 1; row <= N; row++) {for (int col = 1; col <= M; col++) {dp[row][col][0] = 1;}}for (int rest = 1; rest <= K; rest++) {for (int row = 1; row <= N; row++) {for (int col = 1; col <= M; col++) {dp[row][col][rest] = dp[row - 1][col][rest - 1];dp[row][col][rest] += dp[row + 1][col][rest - 1];dp[row][col][rest] += dp[row][col - 1][rest - 1];dp[row][col][rest] += dp[row][col + 1][rest - 1];}}}long all = (long) Math.pow(4, K);long live = dp[i + 1][j + 1][K];long gcd = gcd(all, live);return String.valueOf((live / gcd) + "/" + (all / gcd));}

? ? ?換錢的方法數?

? ? ? ?有給定面值的零錢數在arr數組中,最終需要找零的錢數為aim,返回最終能夠找零的方法數。

public static int way1(int[] arr, int aim){//暴力遞歸方法的求解return process(arr,0,aim);//可以使用arr[0..]中的所有面值
}
//可以自由使用arr[index..]所有的面值
pubilc static int process(int[] arr,int index,int rest){if(index == arr.length){//如果已經沒有錢數可以選擇return rest == 0? 1:0;//那么如果不需要貨幣,只有一種方法,其它的返回0}int ways = 0;for(int zhang = 0; arr[index] * zhang <= rest; zhang ++){//只要選擇的面值乘以張數不超過總計需要的,就可以隨便選ways += process(arr,index + 1,rest - arr[index] * zhang);}return ways;
}
public static int ways2(int[] arr,int aim){//嚴格表結構的動態規劃的方式求解,沒有優化枚舉結構,還是對遞歸方式進行適當的改動即可if(arr == null||arr.length == 0){return 0;}int N = arr.length;int[][] dp = new int[N+1][aim+1];dp[N][0] = 1;for(int index = N-1;index >= 0;index--){for(int rest = 0;rest <= aim;rest++){int ways = 0;for(int zhang = 0;arr[index] * zhang <= rest;zhang ++){ways += dp[index+1][rest - arr[index] * zhang];}dp[index][rest] = ways;}}return dp[0][aim];
} 
public static int ways3(int[] arr,int aim){//嚴格表結構的動態規劃的方式求解,優化枚舉結構,其實也就是通過對格子中位置求解的觀察,發現枚舉行為和周圍格子的關系,利用這個關系減少優化(稱為斜率優化),對于同一行重復需要的內容,不再重新計算if(arr == null||arr.length == 0){return 0;}int N = arr.length;int[][] dp = new int[N+1][aim+1];dp[N][0] = 1;for(int index = N-1;index >= 0;index--){for(int rest = 0;rest <= aim;rest++){dp[index][rest] += dp[index][rest];//一個新的需要計算的格子,一定需要它下面的格子。if(rest - arr[index] >= 0){//如果還沒有湊夠dp[index][rest] += dp[index][rest - arr[index]];//加上自己同行減去本行的面值位置的值}}}return dp[0][aim];
} 

動態規劃的總結

? ? ? ?動態規劃首先最重要的就是嘗試,嘗試的方式有從左到右以及范圍嘗試等比較重要的嘗試方法,然后根據對題目的分析,寫出暴力遞歸方式的代碼,此時加上一個緩存數組,減少重復內容的重復計算,也就是改寫成記憶化搜索的動態規劃方式,此時并沒有研究各個變量之間的依賴性,只是加了一個緩存結構。后面再根據這些關系,畫出嚴格表結構,根據一些知道的內容,對表架構進行填充,表中需要求解的位置,根據記憶化搜索的代碼和暴力遞歸的代碼,分析出各個格子之間的關系,此時就可以根據暴力遞歸的代碼該寫出嚴格表結構的動態規劃的代碼,寫出嚴格表結構進行分析能夠對類似于枚舉行為的結構進行優化,這是非常重要的。

? ? ? ?而嘗試方法的好壞考慮的有兩個方面,一是可變參數的個數,可變參數的個數越少,分析嚴格表結構時維度越低,更簡單。二是單可變參數的維度,也就是一個參數的維度最好就是一個整數,這個是一定要保證的。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/164586.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/164586.shtml
英文地址,請注明出處:http://en.pswp.cn/news/164586.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

大模型增量預訓練參數說明

在增量預訓練過程中通常需要設置三類或四類參數,模型參數,數據參數,訓練參數,額外參數。 下面分別針對這四種參數進行說明。 歡迎關注公眾號 模型參數 model_type模型類型,例如bloom,llama,baichuan,qwen等。 model_name_or_path模型名稱或者路徑。 tokenizer_name_or…

JS數組常用的20種方法詳解(每一個方法都有例子,超全面,超好理解的教程,干貨滿滿)

目錄 1.會改變原數組的方法&#xff08;7種&#xff09; 1.push() 2.pop() 3.unshift() 4.shift() 5.reverse() 6.sort() 7.splice() 2.不改變原數組的方法&#xff08;13種&#xff0c;返回的新數組是從原數組淺拷貝來的&#xff09; 1.concat() 2.join() 3.slice…

12個最佳WordPress投票插件

您是否正在為您的網站尋找WordPress投票插件&#xff1f; WordPress投票插件可讓您輕松地在您的網站上進行民意調查&#xff0c;用戶可以投票。這是在收集見解的同時建立用戶參與度的有效策略。 在本文中&#xff0c;我們精心挑選了最好的WordPress投票插件&#xff0c;可幫助…

代碼隨想錄算法訓練營第五十二天|300.最長遞增子序列 674. 最長連續遞增序列 718. 最長重復子數組

文檔講解&#xff1a;代碼隨想錄 視頻講解&#xff1a;代碼隨想錄B站賬號 狀態&#xff1a;看了視頻題解和文章解析后做出來了 300.最長遞增子序列 class Solution: # 2516 ms, faster than 64.96%def lengthOfLIS(self, nums: List[int]) -> int:n len(nums)dp [1] * n…

從Discord的做法中學習 — 使用Golang進行請求合并

正如你可能之前看到的&#xff0c;Discord去年發布了一篇有價值的文章&#xff0c;討論了他們成功存儲了數萬億條消息。雖然有很多關于這篇文章的YouTube視頻和文章&#xff0c;但我認為這篇文章中一個名為“數據服務為數據服務”的部分沒有得到足夠的關注。在這篇文章中&#…

QT項目移植到VS+QT(RTI-DDS)

QT中.pro文件中include(./xxx.pri) pri文件如下定義 unset(FILENAMES)for(FILENAME, FILENAMES) {HEADERFILE $$PWD/$${FILENAME}.hif(exists($$HEADERFILE)) {HEADERS * $$HEADERFILE}SOURCEFILE $$PWD/$${FILENAME}.cppif(exists($$SOURCEFILE)) {SOURCES * $$SOURCEFILE}…

CSS-鼠標屬性篇

屬性名&#xff1a;cursor 功能&#xff1a;設置鼠標光標的樣式 屬性值&#xff1a; pointer&#xff1a;小手move&#xff1a;移動圖標text&#xff1a;文字選擇器crosshair&#xff1a;十字架wait&#xff1a;等待help&#xff1a;幫助 eg.html{ cursor: wait;}(此處使用css改…

SpringBoot——MVC原理

優質博文&#xff1a;IT-BLOG-CN 一、SpringMVC自動配置 SpringMVC auto-configuration&#xff1a;SpringBoot自動配置好了SpringMVC。以下是SpringBoot對SpringMVC的默認配置&#xff1a;[WebMvcAutoConfiguration] 【1】包括ContentNegotiatingViewResolver和BeanNameView…

Keil工程打開發現目標芯片無法選擇解決方案

買了一個開發板&#xff0c;配套有一些底層驅動的例程&#xff0c;打開后發現目標芯片無法選擇&#xff0c;對應的下載Flash FLM文件也無法選擇。從提示框中可以知道所提供的例程是Keil4的例程&#xff0c;我電腦上安裝的Keil版本是Keil版本&#xff0c;估計是這個原因導致工程…

C# 執行Excel VBA宏工具類

寫在前面 在Excel文檔的自動化處理流程中&#xff0c;有部分值需要通過已定義的宏來求解&#xff0c;所以延伸出了用C# 調用Excel中的宏代碼的需求。 首先要從NuGet中引入Microsoft.Office.Interop.Excel 類庫 using Excel Microsoft.Office.Interop.Excel; 代碼實現 /// &l…

HashMap,1.7與1.8的區別,HashMap的擴容方式有哪些

HashMap,1.7與1.8的區別 底層數據結構的區別 JDK 1.8之前&#xff1a; 1&#xff09;JDK1.8 之前HashMap 底層是數組和鏈表結合在一起使用也就是鏈表散列。 2&#xff09;HashMap 通過key 的hashCode 經過擾動函數處理過后得到hash 值&#xff0c;然后通過(n - 1&#xff09…

修改el-radio-group樣式,自定義單選組件

修改el-radio-group樣式,自定義單選組件 自定義組件 MyRadioGroup.vue <template><div class"btnsBox"><el-radio-group v-model"activeIndex" change"handleClick"><el-radio-buttonv-for"(item, index) in list&qu…

CSS3動畫

在CSS3中新增了一個很有意思的東西&#xff0c;那就是動畫&#xff0c;有了動畫我們可以做很多的事情&#xff0c;讓我為大家介紹一下動畫吧&#xff01; 本篇文章關于介紹動畫&#xff0c;利用小球移動為你們介紹一下動畫 默認樣式&#xff1a; <!DOCTYPE html> <ht…

普通話考試相關(一文讀懂)

文章目錄&#xff1a; 一&#xff1a;相關常識 1.考試報名時間 2.報名地方 費用 證件 3.考試流程 4.普通話等級說明 二&#xff1a;題型 三&#xff1a;技巧 1.前三題 2.命題說話 四&#xff1a;普通話考試題庫 1.在線題庫 2.下載題庫 一&#xff1a;相關常識 …

JavaEE(SpringMVC)期末復習

文章目錄 JavaEE期末復習一、單選題&#xff1a; JavaEE期末復習 一、單選題&#xff1a; 1.Spring的核?技術是&#xff08; A &#xff09;&#xff1f; A依賴注入 B.JdbcTmplate C.聲明式事務 D.資源訪問 Spring的核心技術包括依賴注入&#xff08;Dependency Injection&am…

【前端】js通過canvas獲取瀏覽器的唯一指紋可以當做唯一標識

【前端】js通過canvas獲取瀏覽器的唯一指紋可以當做唯一標識 <!DOCTYPE html> <html><head> <meta charset"utf-8" /> <meta name"viewport" content"widthdevice-width" /> <title>JS Bin</title> &…

解決Emmy Lua插件在IDEA或 Reder 沒有代碼提示的問題(設置文件關聯 增加對.lua.txt文件的支持)

目錄 Reder版本2019.x Reder版本2021.1.5x Reder版本2019.x 解決Emmy Lua插件在IDEA或 Reder 沒有代碼提示的問題(設置文件關聯 增加對.lua.txt文件的支持) Reder版本2021.1.5x 解決Emmy Lua插件在IDEA或 Reder 沒有代碼提示的問題(設置文件關聯 增加對.lua.txt文件的支持)…

java游戲制作-王者榮耀游戲

一.準備工作 首先創建一個新的Java項目命名為“王者榮耀”&#xff0c;并在src下創建兩個包分別命名為“com.sxt"、”com.stx.beast",在相應的包中創建所需的類。 創建一個名為“img”的文件夾來儲存所需的圖片素材。 二.代碼呈現 package com.sxt;import javax.sw…

Netty Review - 探索ByteBuf的內部機制

文章目錄 概念ByteBuf VS Java NIO BufferByteBuf實現類HeapByteBuf vs DirectByteBufPooledByteBuf vs UnpooledByteBuf其他 ByteBuf的實現機制 概念 ByteBuf是Netty中用于處理二進制數據的緩沖區 Netty的ByteBuf是一個可用于高效存儲和操作字節數據的數據結構。與傳統的Byt…

跳躍游戲[中等]

優質博文&#xff1a;IT-BLOG-CN 一、題目 給你一個非負整數數組nums&#xff0c;你最初位于數組的第一個下標 。數組中的每個元素代表你在該位置可以跳躍的最大長度。判斷你是否能夠到達最后一個下標&#xff0c;如果可以&#xff0c;返回true&#xff1b;否則&#xff0c;返…