5368. 找出數組中的幸運數
在整數數組中,如果一個整數的出現頻次和它的數值大小相等,我們就稱這個整數爲「幸運數」。
給你一個整數數組 arr,請你從中找出並返回一個幸運數。
如果數組中存在多個幸運數,只需返回 最大 的那個。
如果數組中不含幸運數,則返回 -1 。
示例 1:
輸入:arr = [2,2,3,4]
輸出:2
解釋:數組中唯一的幸運數是 2 ,因爲數值 2 的出現頻次也是 2 。
示例 2:
輸入:arr = [1,2,2,3,3,3]
輸出:3
解釋:1、2 以及 3 都是幸運數,只需要返回其中最大的 3 。
示例 3:
輸入:arr = [2,2,2,3,3]
輸出:-1
解釋:數組中不存在幸運數。
示例 4:
輸入:arr = [5]
輸出:-1
示例 5:
輸入:arr = [7,7,7,7,7,7,7]
輸出:7
提示:
1 <= arr.length <= 500
1 <= arr[i] <= 500
代碼
class Solution {
public int findLucky(int[] arr) {
Arrays.sort(arr);
int cnt = 0, i = 0, n = arr.length, pre = -1, num = 0;
for (i=n-1; i>=0; --i) {
num = arr[i];
if (num == pre) {
++cnt;
} else {
if (cnt == pre) {
return pre;
}
pre = num;
cnt = 1;
}
}
if (cnt == pre) {
return pre;
} else {
return -1;
}
}
}
5369. 統計作戰單位數
n 名士兵站成一排。每個士兵都有一個 獨一無二 的評分 rating 。
每 3 個士兵可以組成一個作戰單位,分組規則如下:
從隊伍中選出下標分別爲 i、j、k 的 3 名士兵,他們的評分分別爲 rating[i]、rating[j]、rating[k]
作戰單位需滿足: rating[i] < rating[j] < rating[k] 或者 rating[i] > rating[j] > rating[k] ,其中 0 <= i < j < k < n
請你返回按上述條件可以組建的作戰單位數量。每個士兵都可以是多個作戰單位的一部分。
示例 1:
輸入:rating = [2,5,3,4,1]
輸出:3
解釋:我們可以組建三個作戰單位 (2,3,4)、(5,4,1)、(5,3,1) 。
示例 2:
輸入:rating = [2,1,3]
輸出:0
解釋:根據題目條件,我們無法組建作戰單位。
示例 3:
輸入:rating = [1,2,3,4]
輸出:4
提示:
n == rating.length
1 <= n <= 200
1 <= rating[i] <= 10^5
代碼
class Solution {
public int numTeams(int[] rating) {
int n = rating.length, i = 0, j = 0, k = 0, cnt = 0;
for (i=0; i<n; ++i) {
for (j=i+1; j<n; ++j) {
for (k=j+1; k<n; ++k) {
if (rating[i] < rating[j] && rating[j] < rating[k]) {
++cnt;
} else if (rating[i] > rating[j] && rating[j] > rating[k]) {
++cnt;
}
}
}
}
return cnt;
}
}
5370. 設計地鐵系統
請你實現一個類 UndergroundSystem ,它支持以下 3 種方法:
- checkIn(int id, string stationName, int t)
編號爲 id 的乘客在 t 時刻進入地鐵站 stationName 。
一個乘客在同一時間只能在一個地鐵站進入或者離開。
2. checkOut(int id, string stationName, int t)
編號爲 id 的乘客在 t 時刻離開地鐵站 stationName 。
3. getAverageTime(string startStation, string endStation)
返回從地鐵站 startStation 到地鐵站 endStation 的平均花費時間。
平均時間計算的行程包括當前爲止所有從 startStation 直接到達 endStation 的行程。
調用 getAverageTime 時,詢問的路線至少包含一趟行程。
你可以假設所有對 checkIn 和 checkOut 的調用都是符合邏輯的。也就是說,如果一個顧客在 t1 時刻到達某個地鐵站,那麼他離開的時間 t2 一定滿足 t2 > t1 。所有的事件都按時間順序給出。
示例:
輸入:
[“UndergroundSystem”,“checkIn”,“checkIn”,“checkIn”,“checkOut”,“checkOut”,“checkOut”,“getAverageTime”,“getAverageTime”,“checkIn”,“getAverageTime”,“checkOut”,“getAverageTime”]
[[],[45,“Leyton”,3],[32,“Paradise”,8],[27,“Leyton”,10],[45,“Waterloo”,15],[27,“Waterloo”,20],[32,“Cambridge”,22],[“Paradise”,“Cambridge”],[“Leyton”,“Waterloo”],[10,“Leyton”,24],[“Leyton”,“Waterloo”],[10,“Waterloo”,38],[“Leyton”,“Waterloo”]]
輸出:
[null,null,null,null,null,null,null,14.0,11.0,null,11.0,null,12.0]
解釋:
UndergroundSystem undergroundSystem = new UndergroundSystem();
undergroundSystem.checkIn(45, "Leyton", 3);
undergroundSystem.checkIn(32, "Paradise", 8);
undergroundSystem.checkIn(27, "Leyton", 10);
undergroundSystem.checkOut(45, "Waterloo", 15);
undergroundSystem.checkOut(27, "Waterloo", 20);
undergroundSystem.checkOut(32, "Cambridge", 22);
undergroundSystem.getAverageTime("Paradise", "Cambridge"); // 返回 14.0。從 "Paradise"(時刻 8)到 "Cambridge"(時刻 22)的行程只有一趟
undergroundSystem.getAverageTime("Leyton", "Waterloo"); // 返回 11.0。總共有 2 躺從 "Leyton" 到 "Waterloo" 的行程,編號爲 id=45 的乘客出發於 time=3 到達於 time=15,編號爲 id=27 的乘客於 time=10 出發於 time=20 到達。所以平均時間爲 ( (15-3) + (20-10) ) / 2 = 11.0
undergroundSystem.checkIn(10, "Leyton", 24);
undergroundSystem.getAverageTime("Leyton", "Waterloo"); // 返回 11.0
undergroundSystem.checkOut(10, "Waterloo", 38);
undergroundSystem.getAverageTime("Leyton", "Waterloo"); // 返回 12.0
提示:
總共最多有 20000 次操作。
1 <= id, t <= 10^6
所有的字符串包含大寫字母,小寫字母和數字。
1 <= stationName.length <= 10
與標準答案誤差在 10^-5 以內的結果都視爲正確結果。
思路
用兩個map,一個保存上一次用戶進站信息,和當前出站用戶匹配;另一個保存當前統計到的兩個車站中的(總時間,次數)對,最後統一計算涉及到double
類型計算的求平均數操作只在需要計算平均數的時候做一次。
代碼
class UndergroundSystem {
private class CheckIn {
public String station;
public int time;
public CheckIn(String s, int t) {
station = s;
time = t;
}
}
private class Average {
public long sum;
public int time;
public Average(long s, int t) {
sum = s;
time = t;
}
public double doAverage() {
return ((double) sum) / ((double) time);
}
public void addPath(int cost) {
++time;
sum += (long)cost;
}
}
private HashMap<Integer, CheckIn> checkIns = new HashMap<>();
private HashMap<String, HashMap<String, Average>> paths = new HashMap<>();
public UndergroundSystem() {
}
public void checkIn(int id, String stationName, int t) {
checkIns.put(id, new CheckIn(stationName, t));
}
public void checkOut(int id, String stationName, int t) {
CheckIn ci = checkIns.get(id);
String bs = ci.station;
int bt = ci.time;
if (paths.containsKey(bs) && paths.get(bs).containsKey(stationName)) {
paths.get(bs).get(stationName).addPath(t - bt);
return;
}
if (!paths.containsKey(bs)) {
paths.put(bs, new HashMap<String, Average>());
}
paths.get(bs).put(stationName, new Average((long)(t-bt), 1));
}
public double getAverageTime(String startStation, String endStation) {
return paths.get(startStation).get(endStation).doAverage();
}
}
/**
* Your UndergroundSystem object will be instantiated and called as such:
* UndergroundSystem obj = new UndergroundSystem();
* obj.checkIn(id,stationName,t);
* obj.checkOut(id,stationName,t);
* double param_3 = obj.getAverageTime(startStation,endStation);
*/
5371. 找到所有好字符串
給你兩個長度爲 n 的字符串 s1 和 s2 ,以及一個字符串 evil 。請你返回 好字符串 的數目。
好字符串 的定義爲:它的長度爲 n ,字典序大於等於 s1 ,字典序小於等於 s2 ,且不包含 evil 爲子字符串。
由於答案可能很大,請你返回答案對 10^9 + 7 取餘的結果。
示例 1:
輸入:n = 2, s1 = “aa”, s2 = “da”, evil = “b”
輸出:51
解釋:總共有 25 個以 ‘a’ 開頭的好字符串:“aa”,“ac”,“ad”,…,“az”。還有 25 個以 ‘c’ 開頭的好字符串:“ca”,“cc”,“cd”,…,“cz”。最後,還有一個以 ‘d’ 開頭的好字符串:“da”。
示例 2:
輸入:n = 8, s1 = “leetcode”, s2 = “leetgoes”, evil = “leet”
輸出:0
解釋:所有字典序大於等於 s1 且小於等於 s2 的字符串都以 evil 字符串 “leet” 開頭。所以沒有好字符串。
示例 3:
輸入:n = 2, s1 = “gx”, s2 = “gz”, evil = “x”
輸出:2
提示:
s1.length == n
s2.length == n
1 <= n <= 500
1 <= evil.length <= 50
所有字符串都只包含小寫英文字母。
思路
數位dp的變形 + KMP。把問題規約爲求長度爲n
,小於等於目標串target
且不含子串pattern
的字符串個數,這就是countString
方法的功能。dp[i][j][s]
表示匹配到目標串target
位置到i-1
,匹配模式串pattern
位置到j
,狀態s
是一個二進制,s=0
表示之前的各位沒有達到上界(之前每一位都與目標串target
相等),s=1
表示達到上界。字符串匹配過程借鑑KMP算法的方式,計算next
數組。時間複雜度O(nm)
,n
爲目標串target
的長度,m
爲模式串pattern
的長度。
注意減法之後進行求餘出現負數的情況。
代碼
class Solution {
private static final int mod = 1000000007;
private int[][][] dp;
// dp[i][j][s]: match index of target string `i`; match index of pattern string `j`; binary state, 1 for reach upper bound
/**
* Calculate number of strings <= {@code str} and without substring {@code evil}
*/
private int countString(int n, String str, String evil) {
int m = evil.length(), i = 0, j = 0, k = 0, s = 0, ns = 0;
dp = new int[n+1][m][2];
// Calculate {@code next} array of {@code evil} by KMP
int[] next = new int[m];
for(j = 1 ; j < m ; ++j) {
while (evil.charAt(i) != evil.charAt(j) && i > 0) {
i = next[i-1];
}
if(evil.charAt(i) == evil.charAt(j)) {
++i;
next[j] = i;
}
else {
next[j] = 0;
}
}
// Do dynamic programming
char[] upperBounds = new char[2];
upperBounds[0] = 'z'; // s = 0
dp[0][0][1] = 1;
for (i=1; i<=n; ++i) {
for (j=0; j<m; ++j) {
upperBounds[1] = str.charAt(i-1); // s = 1
for (s=0; s<=1; ++s) {
for (char ch='a'; ch<=upperBounds[s]; ++ch) {
k = j;
while (ch != evil.charAt(k) && k > 0) {
k = next[k-1];
}
if (ch == evil.charAt(k)) {
++k;
}
if (k == m) {
continue;
}
if (s == 1 && ch == str.charAt(i-1)) {
ns = 1;
} else {
ns = 0;
}
dp[i][k][ns] = (dp[i][k][ns] + dp[i-1][j][s]) % mod;
}
}
}
}
// Calculate answer
int ans = 0;
for (j=0; j<m; ++j) {
for (s=0; s<=1; ++s) {
ans = (ans + dp[n][j][s]) % mod;
}
}
return ans;
}
public int findGoodStrings(int n, String s1, String s2, String evil) {
int tail = s1.contains(evil)? 0: 1, ans = 0;
ans = (countString(n, s2, evil) - countString(n, s1, evil)) % mod;
if (ans < 0) {
ans = ans + mod;
}
ans = (ans + tail) % mod;
return ans;
}
}