题目链接: https://www.lanqiao.cn/problems/735/learning/
这个题直接使用代码模拟就ok了,说实话如果考场上看到了我会直接自己抽牌算hhhh
由于知道最后的顺序和他抽的过程,那么我们就可以反着去模拟回初始状态,这里定义一个数组表示所有的牌,并且定义一个变量bottom指向目前的牌底,也就是说在bottom之前的元素实际都已经被抽出去,然后我们反向的过程就是从牌顶部(数组最后一个元素)取牌放到当前的底部位置,直到bottom指向数组开始位置
package daily;
import java.util.Arrays;
/**
* https://www.lanqiao.cn/problems/735/learning/
*
* @author Jia
*
*/
public class day3_13_1 {
public static void main(String[] args) {
// 这里直接定义字符数组了,所以没法定义10,用T替代了,也可以直接定义为字符串数组
char[] poke = { 'A', '2', '3', '4', '5', '6', '7', '8', '9', 'T', 'J', 'Q', 'K' };
int bottom = 12;// 标记现在的底部
for (int i = 0; i < poke.length; i++) {
pushBack(poke, bottom);
bottom--;
}
// 使用API输出时候会被[]括起来,使用replace去掉,然后将数组中的T换成10
System.out.println(Arrays.toString(poke).replace("T", "10").replace("[", "").replace("]", ""));
}
/**
* 把牌顶的元素放回牌底。就相当于把数组最后一个元素放到bottom指示的地方,同时把bottom之后的字符向后挪一位
*
* @param poke
* @param bottom
*/
private static void pushBack(char[] poke, int bottom) {
char temp = poke[poke.length - 1];
for (int i = poke.length - 1; i > bottom; i--) {
poke[i] = poke[i - 1];
}
poke[bottom] = temp;
}
}
题目链接: https://www.lanqiao.cn/problems/809/learning/
这题不太会,反正是dp,照不出来递推公式,我这个推出来有点太大了,正确答案应该是14位数
可以看看我这哪有问题。。前面13项调试都是正确的,后面的就不知道了
我的想法是从前往后看有多少二质数组合可以拼成x数,然后利用这个公式往后一直推下去,比如7的话,就需要查看1+6,2+5,3+4,然后可能性就是1+后面三种的组合数(两个数的可能性的乘积)
package daily;
import java.util.Arrays;
/**
* https://www.lanqiao.cn/problems/809/learning/
*
* @author Jia
*
*/
public class day3_13_2_wa {
public static void main(String[] args) {
int n = 2019;
long ans = 0l;
long[] sumIndex = constructPrimaryArr(n);
for (int i = 1; i < sumIndex.length; i++) {
for (int j = 1; j < i; j++) {
if (j < i - j) {
// System.out.println(i + " " + j + " " + (i - j));
// System.out.println(sumIndex[i] + " " + sumIndex[j] + " " + sumIndex[i - j]);
sumIndex[i] += sumIndex[j] * sumIndex[i - j];
// System.out.println(sumIndex[i]);
} else {
break;
}
}
}
for (int i = 0; i < sumIndex.length; i++) {
System.out.println(i + "\t" + sumIndex[i]);
}
System.out.println(sumIndex[2019]);
}
/**
* 构造一个素数数组
*
* @param n
*
* @return
*/
private static long[] constructPrimaryArr(int n) {
long[] arr = new long[n + 1];
Arrays.fill(arr, 1l);
arr[0] = 0l;
arr[1] = 0l;
for (int i = 2; i < arr.length; i++) {
if (arr[i] == 1) {
int j = i + i;
while (j < arr.length) {
arr[j] = 0l;
j += i;
}
}
}
return arr;
}
}
题目链接:https://www.lanqiao.cn/problems/179/learning/
这个题整体处理起来比较麻烦,但是思路不是很难,整体使用的还是贪心思想
前面数据处理的方法也有其他的,不一定非要使用HashMap,我用map主要是因为查找比较方便。
具体的处理逻辑在53-62行,对于每个帖子,通过一个大小为D的时间段去统计总共有多少点赞,如果使用双层循环的话很可能会超时,所以我是通过记录当前统计的这段时间的开始时间点,然后判断当前时间点的差值与开始时间点的差值是不是大于D,如果不大于D点赞数加一,如果大于D则要通过调整开始时间保证开始时间到当前节点的时间小于D即可。
package daily;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Scanner;
/**
* https://www.lanqiao.cn/problems/809/learning/
*
* @author Jia
*
*/
public class day3_13_3 {
public static void main(String[] args) {
// 读入数据
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int D = sc.nextInt();
int K = sc.nextInt();
Map<Integer, PostInfo> map = new HashMap<>();// 方便在获得到一个点赞的时候知道是哪一个帖子的
for (int i = 0; i < N; i++) {
int ts = sc.nextInt();
int id = sc.nextInt();
if (map.containsKey(id)) {
map.get(id).add(ts);
} else {
PostInfo PostInfo = new PostInfo();
PostInfo.add(ts);
map.put(id, PostInfo);
}
}
sc.close();
// 存储热帖的id
ArrayList<Integer> ansList = new ArrayList<>();
// 遍历所有人的被点赞集合,统计热帖
for (Entry<Integer, PostInfo> entry : map.entrySet()) {
// 查看所有数据
// System.out.println(entry.getKey() + " " + entry.getValue());
// 得到点赞列表并排序
ArrayList<Integer> tsList = entry.getValue().ts;
tsList.sort((a, b) -> a - b);// lambda表达式,传入(a,b),返回a-b,不熟悉的话可以直接传入匿名的Comparable也可以
int sum = 1;// 当前时间段内点赞总数
int beginTime = tsList.get(0);// 开始时间
int beginIndex = 0;// 开始时间的下标,用于判断下一个时间段开始时间
int max = 1;// 记录不同时间段内的最大点赞数
for (int i = 1; i < tsList.size(); i++) {
// 当该节点的时间超出当前统计的时间段时,需要将时间段向后推,直到包含该时间点
while (tsList.get(i) - beginTime >= D) {
sum--;
beginIndex++;
beginTime = tsList.get(beginIndex);
}
sum++;
max = Math.max(max, sum);
}
// 如果大于等于K,说明是热帖
if (max >= K) {
ansList.add(entry.getKey());
}
}
// 将结果排序后输出
ansList.sort((a, b) -> a - b);
for (int i = 0; i < ansList.size(); i++) {
System.out.println(ansList.get(i));
}
}
}
class PostInfo {
ArrayList<Integer> ts = new ArrayList<>();// 点赞时间列表
public void add(int t) {
ts.add(t);
}
@Override
public String toString() {
return ts.toString();
}
}
题目链接: http://lx.lanqiao.cn/problem.page?gpid=T2728
呃,这个题没完全过,这个方法还是有点类似于暴力求解的,过了7/8的测试数据,最后一个估计是数据量太大了
开始就想的是肯定不能暴力求解,如果暴力遍历肯定超时,然后就只能是先对三个数组排序,然后定义数组
package daily;
import java.util.Arrays;
import java.util.Scanner;
/**
* http://lx.lanqiao.cn/problem.page?gpid=T2728
*
* @author Jia
*
*/
public class day3_13_4 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int N = sc.nextInt();
int[] A = new int[N];
int[] B = new int[N];
int[] C = new int[N];
for (int i = 0; i < N; i++) {
A[i] = sc.nextInt();
}
for (int i = 0; i < N; i++) {
B[i] = sc.nextInt();
}
for (int i = 0; i < N; i++) {
C[i] = sc.nextInt();
}
sc.close();
// 对A、B、C进行排序
Arrays.sort(A);
Arrays.sort(B);
Arrays.sort(C);
long ans = 0L;// 记录最后结果
int[] ansB = new int[N];// B的该位比A的多少个数字大
int preA = A.length - 1;
// 统计B每位比A大的数量
for (int i = B.length - 1; i >= 0; i--) {
for (int j = preA; j >= 0; j--) {
if (B[i] > A[j]) {
preA = j;
ansB[i] = j + 1;
break;
}
}
}
// 逐位比较C和B,如果C比B大,ans加上ansB对应的数字(这里其实还可以优化的,让B从上一次结束的地方开始,但是总是有BUG,就只能这样了)
for (int i = 0; i < C.length; i++) {
for (int j = 0; j < B.length; j++) {
if (C[i] > B[j]) {
ans += ansB[j];
}
}
}
System.out.println(ans);
}
}
题目链接:https://www.lanqiao.cn/problems/184/learning/