牛牛如今有 n 張撲克牌,每張撲克牌都有點數和花色兩部分組成。點數爲 ‘1’ - ‘9’ 的正整數,花色爲 'C', 'D', 'H', 'S' 其中的一個,分別表示梅花、方塊、紅桃、黑桃。如今牛牛想按必定的順序把這n張牌扔掉。扔牌順序的規則以下:java
牛牛想知道他的扔牌順序是什麼,請返回扔牌順序的字符串 數組
備註:spa
對於 100% 的數據,1 ≤ n ≤ 10。
輸入code
"3C8D6H3D"
輸出字符串
"3D3C8D6H"
說明get
開始 n = 4,爲非素數,扔掉牌底的牌 3D n = 3,爲素數,扔掉牌頂的牌 3C n = 2,爲素數,扔掉牌頂的牌 8D n = 1,爲非素數,扔掉牌底的牌 6H
輸入數學
"8S8S8S8S8S8S8S"
輸出string
"8S8S8S8S8S8S8S"
說明it
由於全是8S,因此扔牌順序的每一張牌也都是8S
因爲 n 在 [1, 10] 上,故本題直接把全部素數列出來便可。沒什麼難度。class
時間複雜度:O(n)
空間複雜度:O(n)
/** * * @param x string字符串 字符串從前到後分別是從上到下排列的n張撲克牌 * @return string字符串 */ public String Orderofpoker (String x) { int n = x.length() / 2; int top = 0, bot = x.length() - 2; String res = ""; while(n > 0){ if(n == 2 || n == 3 || n == 5 || n == 7){ res += x.substring(top, top + 2); top += 2; }else{ res += x.substring(bot, bot + 2); bot -= 2; } n--; } return res; }
今天牛牛去遊樂園玩過山車項目,他以爲過山車在上坡下坡的過程是很是刺激的,回到家以後就受到啓發,想到了一個問題。若是把整個過山車的軌道看成是一個長度爲 n 的數組 num,那麼在過山車上坡時數組中的值是呈現遞增趨勢的,到了最高點之後,數組中的值呈現遞減的趨勢,牛牛把符合這樣先增後減規律的數組定義爲金字塔數組,請你幫牛牛在整個 num 數組中找出長度最長的金字塔數組,若是金字塔數組不存在,請輸出 0。
備註:
1 <= n <= 1000000,且 num 數組中的數 0 <= num[i] <= 1000000。
輸入
4,[1,2,3,1]
輸出
4
輸入
5,[1,5,3,3,1]
輸出
3
在遍歷的時候判斷是不是金字塔數組便可。當前數字 i 和前一個數字 j 比較有三種狀況:
時間複雜度:O(n)
空間複雜度:O(1)
/** * * @param n int整型 * @param num int整型一維數組 * @return int整型 */ public int getMaxLength (int n, int[] num) { // write code here int res = 0; int len = 1; boolean up = false; for(int i = 1; i < n; i++) { if(num[i] > num[i - 1]) { up = true; if(i > 1 && num[i - 1] < num[i - 2]) len = 1; len++; }else if(num[i] == num[i - 1]) { len = 1; up = false; }else { if(up) { len++; res = Math.max(len, res); } } } return res; }
金字塔數組長度 = 爬升階段長度 + 1 (塔頂) + 降低階段長度。
而降低階段
至關於從右往左遍歷時的爬升階段
。
所以分別用 l 數組
和 r 數組
記錄從左到右和從右到左的爬升階段長度。
若 l[i] 和 r[i] 都不爲 0,說明 i 是塔頂。
時間複雜度:O(n)
空間複雜度:O(n)
/** * * @param n int整型 * @param num int整型一維數組 * @return int整型 */ public int getMaxLength (int n, int[] num) { int res = 0; int[] l = new int[n]; int[] r = new int[n]; for(int i = 1; i < n; i++){ if(num[i] > num[i - 1]) l[i] = l[i - 1] + 1; } for(int i = n - 2; i >= 0; i--){ if(num[i] > num[i + 1]) r[i] = r[i + 1] + 1; } for(int i = 0; i < n; i++){ if(l[i] != 0 && r[i] != 0) res = Math.max(res, l[i] + r[i] + 1); } return res; }
牛牛最近在家裏看到一個棋盤,有 n m 個格子,在棋盤旁邊還放着 k 顆棋子,牛牛想把這 k 顆棋子所有放在 n m 的棋盤上,可是有一個限制條件:棋盤的第一行、第一列、最後一行和最後一列都必須有棋子。牛牛想知道這樣的棋子放法到底有多少種,答案須要對 1e9 + 7
取模。
備註:
2 <= n, m <= 30; 1 <= k <=1000
輸入
2,3,1
輸出
0
說明
就1顆棋子,因此沒法知足條件。
輸入
2,2,2
輸出
2
說明
咱們能夠把第1顆棋子放在左上角,第2顆棋子放在右下角;也能夠把第1顆棋子放在右上角,第2顆棋子放在左下角。故而有2种放法。
本題須要具有高中的數學知識:容斥原理和排列組合數。涉及的數學公式會在題解中給出,若是有看不明白的地方能夠自行查詢相關數學概念。
記行 i 上無棋子的集合爲 $S_{ri}$, 列 j 上無棋子的集合爲 $S_{cj}$。根據容斥原理,有
$$ \begin{aligned} res &= ∣S_{r1} ∩ S_{rn} ∩ S_{c1} ∩ S_{cm}∣ \hspace{100cm}\\ &= all - |S_{r1} ∪ S_{rn} ∪ S_{c1} ∪ S_{cm}∣\\ &= all - \sum_{C \subseteq U}(-1)^{size(C) - 1}|\cap_{e \in C} e| \end{aligned} $$
其中, $U = \{S_{r1}, S_{rn}, S_{c1}, S_{cm}\}$。
因爲 $U$ 中只包含四個集合,所以能夠用 4 個 bit 分別表示是否交集合 $S_i$。
總共有 $2^4 - 1 = 15$ 種交集狀況,再加上 all ,共計 16 種狀況。
排列組合數能夠利用公式 $C_m^n = C_{m - 1}^n + C_{m - 1}^{n - 1}$ 迭代計算得出。
final int mod = (int)1e9 + 7; /** * * @param n int整型 * @param m int整型 * @param k int整型 * @return int整型 */ public int solve (int n, int m, int k) { if(k < 2) return 0; int[][] C = initC(); int res = 0; for(int i = 0; i < 16; i++){ int r = n, c = m, cnt = 0; if((i & 1) != 0) {r--; cnt++;} if((i & 2) != 0) {r--; cnt++;} if((i & 4) != 0) {c--; cnt++;} if((i & 8) != 0) {c--; cnt++;} res = (res - ((cnt & 1) * 2 - 1) * C[r * c][k]) % mod; } return (res + mod) % mod; } public int[][] initC(){ int n = 1000; int[][] C = new int[1001][1001]; for(int i = 1; i <= n; i++) C[i][0] = C[i][i] = 1; for(int i = 2; i <= n; i++){ for(int j = 1; j < i; j++){ C[i][j] = (C[i - 1][j - 1] + C[i - 1][j]) % mod; } } return C; }
你們好,我是往西汪,一位堅持原創的新人博主。若是本文對你有幫助,請點贊、評論二連。你的支持是我創做路上的最大動力。謝謝你們!也歡迎來公衆號【往西汪】找我玩耍~