在整数数组中,如果一个整数的出现频次和它的数值大小相等,我们就称这个整数为「幸运数」。
给你一个整数数组 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;
}
}
}
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;
}
}
请你实现一个类 UndergroundSystem ,它支持以下 3 种方法:
编号为 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);
*/
给你两个长度为 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;
}
}