小红认为一个排列是优美的,当且仅当对于任意i∈[1,n] , ai=n-ai+1成立,其中 n 代表排列的长度,ai 表示排列的第 i 个元素。她想知道 1-n 的所有优美排列中,字典序最大的是哪一个?注意,排列的定义为,若长度为 n 的序列中,1 到 n 都出现过且仅出现一次,则称该序列为一个排列。
输入描述
一个正整数n(1<=n<=10^5),代表排列的长度。
输出描述
一行n个正整数,用空格隔开。代表字典序最大的优美排列。
示例输入
2
输出
2 1
题解:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
while (n > 0) {
System.out.print(n-- + " ");
}
}
}
小红有一个长度为n字符串s,他需要从第 1 个字符走到第n个字符,他每次只能走到相邻的字符。当他从si走到si+1时,他会消耗si+1-si点体力值。si+1-si若是负数,意味着他将恢复|si+1-si|点体力值,若体力值消耗到小于 0,则小红将无法继续走。字符相减时字符’a’代表 1,字符’b’代表 2…以此类推。已知小红现在有k点体力值,他能否从s1走到sn。若能走到,请输出他的剩余体力值,否则输出 -1。
输入描述
第一行两个整数n,k(1<=n,k<=10^5)。 第二行一个长度为n字符串s.
输出描述
一行一个整数,表示他的剩余体力值。若无法走到,则输出 -1。
输入
5 2
abcca
输出
2
说明
初始处理第一个字符时,体力值为2。
处理第二个字符时,体力值为1。
处理第三个字符时,体力值为0。
处理第四个字符时,体力值为0。
处理第五个字符时,体力值为2。
最终输出2
示例2
输入输出示例仅供调试,后台判题数据一般不包含示例
输入
5 1
abcca
输出
-1
题解:
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int k = in.nextInt();
in.nextLine();
char[] cs = in.nextLine().toCharArray();
int index = 1;
while (index < n) {
if (k < cs[index] - cs[index - 1]) {
System.out.println(-1);
return;
}
k -= cs[index] - cs[index - 1];
index++;
}
System.out.println(k);
}
}
智能语音、自然语言理解是科大讯飞较核心的技术、且保持在了世界前沿水平。在自然语言理解中,自然语言处理(nlp)为一个常见的技术,本题的具体场景也和这个技术相关。自然语言处理(nlp)经常会需要解决一些字符串的子串问题。我们把它抽象为数组的连续子数组问题。当处理一个数组时,机器会存储数组的一些连续子数组。不过为了节省存储空间,当机器遇到多个完全相同的连续子数组时只会存储一次。现在有一个棘手的问题,给定了两个长度为n的数组,这两个数组均满足以下性质:1 到n恰好出现了一次,请你判断机器存储完所有的连续子数组时,一共存储了多少次。
输入描述
第一行输入一个正整数n,代表数组的长度。
第二行输入n个正整数ai,代表第一个数组。
第三行输入n个正整数bi,代表第二个数组。
1<=n<=2* 1 0 5 10^5 105
输出描述
机器存储的次数。
示例1
输入
3
1 2 3
2 3 1
输出
8
说明
[1],[2],[3],[1,2],[2,3],[3,1],[1,2,3],[2,3,1] 一共存储了8次。
题解:
对于两个子数组,最多需要存(1 + n) * n次,然后减去重复的次数。重复次数的计算,利用哈希表+双指针。
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] nums1 = new int[n];
int[] nums2 = new int[n];
int[] mpa = new int[n + 1];
int[] mpb = new int[n + 1];
for (int i = 0; i < n; i++) {
nums1[i] = in.nextInt();
//保存哈希
mpa[nums1[i]] = i;
}
for (int i = 0; i < n; i++) {
nums2[i] = in.nextInt();
//保存哈希
mpb[nums2[i]] = i;
}
//最多需要存(1 + n) * n次
long res = (long) (1 + n) * n;
for (int i = 0; i < n; i++) {
//找一个数组中同一个数在俩个数组出现的位置
int posa = mpa[nums1[i]];
int posb = mpb[nums1[i]];
int numSame = 0;
//如果相等,继续往后查,还相等加 1
while (posa < n && posb < n && nums1[posa] == nums2[posb]) {
numSame++;
posa++;
posb++;
}
//减去重复的
res -= numSame;
}
System.out.println("ans: "+res);
}
}
暴力(使用Map或者Set存所有出现组合):
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] nums1 = new int[n];
int[] nums2 = new int[n];
for (int i = 0; i < n; i++) {
nums1[i] = in.nextInt();
}
for (int i = 0; i < n; i++) {
nums2[i] = in.nextInt();
}
Map<String, String> resultMap = new LinkedHashMap<>();
for (int i = 0; i < nums1.length; i++) {
String s = "";
for (int j = i; j < nums1.length; j++) {
s += nums1[j] + "-";
if (!resultMap.containsKey(s)) {
resultMap.put(s, s);
}
}
}
for (int i = 0; i < nums2.length; i++) {
String s = "";
for (int j = i; j < nums2.length; j++) {
s += nums2[j] + "-";
if (!resultMap.containsKey(s)) {
resultMap.put(s, s);
}
}
}
System.out.println(resultMap.size());
}
}
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int n = in.nextInt();
int[] nums1 = new int[n];
int[] nums2 = new int[n];
for (int i = 0; i < n; i++) {
nums1[i] = in.nextInt();
}
for (int i = 0; i < n; i++) {
nums2[i] = in.nextInt();
}
//Map resultMap = new LinkedHashMap<>();
Set<String> resultSet = new HashSet<>();
for (int i = 0; i < nums1.length; i++) {
String s = "";
for (int j = i; j < nums1.length; j++) {
s += nums1[j] + "-";
if (!resultSet.contains(s)) {
resultSet.add(s);
}
}
}
for (int i = 0; i < nums2.length; i++) {
String s = "";
for (int j = i; j < nums2.length; j++) {
s += nums2[j] + "-";
if (!resultSet.contains(s)) {
resultSet.add(s);
}
}
}
System.out.println(resultSet.size());
}
}