题一
代码如下:
import java.util.Scanner;
import java.util.Set;
import java.util.Stack;
import java.util.Arrays;
import java.util.stream.Collectors;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
private static int count;
private static Stack<Integer> path;
private static boolean[] visited;
private static Set<Integer> numSet;
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int N = in.nextInt();
count = 0;
path = new Stack<>();
visited = new boolean[N];
Integer[] sushu = {2,3,5,7,11,13,17,19};
numSet = Arrays.stream(sushu).collect(Collectors.toSet());
generatePailie(N);
System.out.println(count);
}
private static void generatePailie(int n) {
if(path.size() == n) {
count++;
return;
}
for(int i=1; i<=n; i++) {
if(visited[i-1]) continue;
if(path.size() == 0 || !numSet.contains(path.get(path.size()-1) + i)) {
visited[i-1] = true;
path.push(i);
generatePailie(n);
path.pop();
visited[i-1] = false;
}
}
}
}
解析
使用回溯法,直接遍历出所有可能,遇到不符合的就跳过即可。由于n最大为10,则两个元素之和最大为20,所以将2到20中所有的素数放入一个集合中以供查询。
题二
代码如下:
import java.util.Scanner;
import java.util.ArrayList;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
// 读取矩阵的行数和列数
int n = scanner.nextInt();
int m = scanner.nextInt();
// 准备备忘录
int[] yRowCounts = new int[n];
int[] oRowCounts = new int[n];
int[] uRowCounts = new int[n];
int[] yColCounts = new int[m];
int[] oColCounts = new int[m];
int[] uColCounts = new int[m];
// 读取矩阵
char[][] matrix = new char[n][m];
for (int i = 0; i < n; i++) {
String line = scanner.next();
for (int j = 0; j < m; j++) {
matrix[i][j] = line.charAt(j);
switch(matrix[i][j]) {
case 'y':
yRowCounts[i]++;
yColCounts[j]++;
break;
case 'o':
oRowCounts[i]++;
oColCounts[j]++;
break;
case 'u':
uRowCounts[i]++;
uColCounts[j]++;
break;
}
}
}
long count = 0;
for(int i=0; i<n; i++) {
for(int j=0; j<m; j++) {
switch(matrix[i][j]) {
case 'y':
count += (oRowCounts[i]*uColCounts[j] + oColCounts[j]*uRowCounts[i]);
break;
case 'o':
count += (yRowCounts[i]*uColCounts[j] + yColCounts[j]*uRowCounts[i]);
break;
case 'u':
count += (oRowCounts[i]*yColCounts[j] + oColCounts[j]*yRowCounts[i]);
break;
}
}
}
System.out.println(count);
scanner.close();
}
}
解析
假设第 i 行第 j 列的元素为 ‘o',则以该元素为直角顶点,所能形成符合题意的直角三角形的数量为第 i 行的 ’y' 元素个数乘以第 j 行的 'o' 元素个数,再加上第 i 行的 'o' 元素个数乘以第 j 行的 'y' 元素个数。基于此,我们可以在读取时计算某个元素在第几行和第几列的个数,然后后面在遍历计算直角三角形的个数。
题三
SQL语句如下:
select
res_t.name product_name,
res_t.total_sales,
row_number() over (
partition by
res_t.category
order by
res_t.total_sales desc
) category_rank
from
(
select
p.product_id,
p.name,
p.category,
o1.total_sales
from
products p,
(
select
product_id,
sum(quantity) total_sales
from
orders
group by
product_id
) o1
where
p.product_id = o1.product_id
order by
p.product_id
) res_t
order by
res_t.category asc,
res_t.total_sales desc;
解析
首先根据订单表按照产品id查询出各个产品的销售总量,然后联合产品表查询出产品id,名称,类型以及对应产品id的销售总量,并且根据产品id排序,最后使用row_number查询各产品类型中产品销量的排名。
题四
代码如下:
import java.util.Scanner;
import java.util.Arrays;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
int examples = in.nextInt();
for(int i=0; i<examples; i++) {
int n = in.nextInt();
int low = in.nextInt();
int high = in.nextInt();
long sum = 0L;
// 读取数组
int[] nums = new int[n];
for(int j=0; j<n; j++) {
nums[j] = in.nextInt();
sum += nums[j];
}
// 平均值不在区间内,则不能满足条件
double avg = sum * 1.0 / n;
if(avg < low || avg > high) {
System.out.println(-1);
continue;
}
Arrays.sort(nums);
long count = 0L;
long leftCount = 0L, rightCount = 0L;
for(int j=0; j<n; j++) {
if(nums[j] >= low) break;
leftCount += (low - nums[j]);
}
for(int j=n-1; j>=0; j--) {
if(nums[j] <= high) break;
rightCount += (nums[j] - high);
}
System.out.println(Math.max(leftCount, rightCount));
}
}
}
解析
首先要判断所有元素的平均值是否在指定区间内,如果是,则一定能达成目标,否则不能。
如果平均值在指定区间内,我们先将获取的元素进行排序,排序后的数组一定存在某个区间,该区间内的元素均在指定区间内。
对于未在区间内的元素,我们先分为左右两部分,左边的元素距离最近的是区间的下限,右边的元素距离最近的是区间的上限。
因此,我们分别计算左边元素距离下限需要多少次操作,右边元素距离上限需要多少次操作。而由于每次操作是一加一减,所以最终的操作数为左右两边共同的操作数加上左右两边溢出(也就是不在共同操作的范围内)的操作数,即左右两边操作数的最大值即为最终所需的操作数。
题五
代码如下:
import java.util.Scanner;
import java.util.HashMap;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
String binaryS = in.nextLine();
int[] dp = new int[binaryS.length()+1];
long sum = 0;
for(int i=0; i<binaryS.length(); i++) {
char c = binaryS.charAt(i);
if(c == '0') {
dp[i+1] = dp[i]+1;
}else {
dp[i+1] = dp[i] > 0 ? dp[i]-1 : 0;
}
sum += dp[i+1];
}
System.out.println(sum);
}
}
解析
这道题目使用动态规划即可解决。dp[i] 表示以第 i 个元素为结尾的好串数,在遍历过程中,遇到'0'则加一,遇到'1'则减一直至0。最后再计算总数即可。