Java 笔试【xc-0907】
面试要线下参加,是为了检验我的诚心吗?
题目的内容参考:https://www.nowcoder.com/discuss/529638802495721472
T1:相邻的数不能是合数
不知道咋做,用的 dfs。
public static void main11(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNextInt()) { // 注意 while 处理多个 case
int n = in.nextInt();
int ans = 0;
int[] arr = new int[n];
boolean[ ] visited = new boolean[n];
ans = dfs(0, visited, arr);
System.out.println(ans);
}
}
private static int dfs(int idx, boolean[] visited, int[] arr) {
if (idx == visited.length) return 1;
int ans = 0;
for (int i = 0; i < visited.length; i++) {
if (visited[i]) continue;
if (idx > 0 && isP(arr[idx - 1] + 1 + i + 1)) continue;
visited[i] = true;
arr[idx] = i;
ans += dfs(idx + 1, visited, arr);
arr[idx] = 0;
visited[i] = false;
}
return ans;
}
private static boolean isP(int num) {
switch (num) {
case 2:
case 4:
case 6:
case 8:
case 9:
case 10:
case 12:
case 14:
case 15:
case 16:
case 18:
case 20:
return false;
default:
return true;
}
}
T2:三角形
给出n*m的字符矩阵,求三点分别为y o u的直角三角形个数。只过了10%。
思路:记录 y 和 o 的位置,for 循环,获取合格的 u 的位置。时间复杂度 (n*m) * (n*m)。
这个思路错误的地方在于,我们其实只需要记录每行每列的 y 和 o,不需要记录每个 y 和 o。
public static void main22(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNextInt()) { // 注意 while 处理多个 case
int row = in.nextInt();
int col = in.nextInt();
List<int[]> ys = new ArrayList<>();
List<int[]> os = new ArrayList<>();
Map<Integer, Integer> xCnts = new HashMap<>();
Map<Integer, Integer> yCnts = new HashMap<>();
// Map<Integer, Integer> cnts = new HashMap<>();
Set<Integer> set = new HashSet<>();
for (int i = 0; i < row; i++) {
String str = in.next();
char[] cs = str.toCharArray();
for (int j = 0; j < col; j++) {
char c = cs[j];
switch (c) {
case 'y': ys.add(new int[]{i, j}); break;
case 'o': os.add(new int[]{i, j}); break;
case 'u':
add(xCnts, i);
add(yCnts, j);
set.add(i * col + j);
break;
default: break;
}
}
}
int ans = 0;
for (int[] y: ys) {
int x1 = y[0];
int y1 = y[1];
for (int[] o: os) {
int x2 = o[0];
int y2 = o[1];
if (x1 == x2) {
// 已经有水平线
ans += yCnts.getOrDefault(y1, 0) + yCnts.getOrDefault(y2, 0);
} else if (y1 == y2) {
// 已经有竖直线
ans += xCnts.getOrDefault(x1, 0) + xCnts.getOrDefault(x2, 0);
} else {
// {x1, y2}
// {x2, y1}
ans += set.contains(x1 * col + y2) ? 1 : 0;
ans += set.contains(x2 * col + y1) ? 1 : 0;
}
}
}
System.out.println(ans);
}
}
public static void add(Map<Integer, Integer> map, int key) {
if (map.containsKey(key)) {
map.put(key, map.get(key) + 1);
} else {
map.put(key, 1);
}
}
T3:数组操作次数
给出n个整数,每次可以选两个分别+1-1,求使得n个数都位于[l, r]的最少操作次数,不存在则输出-1枚举每个数,对小于左边界的数用一个变量记录差值,大于有边界的变量用另一个数记录差值,最后输出两个变量中大的那个。
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
while (in.hasNextInt()) { // 注意 while 处理多个 case
int t = in.nextInt();
for (int i = 0; i < t; i++) {
int n = in.nextInt();
int l = in.nextInt();
int r = in.nextInt();
int[] arr = new int[n];
long sum = 0L;
List<Integer> nums = new ArrayList<>();
long lack = 0;
long remain = 0;
for (int j = 0; j < n; j++) {
int num = in.nextInt();
arr[j] = num;
sum += num;
if (num < l || num > r) nums.add(num);
if (num < l) lack += l - num;
if (num > r) remain += num - r;
}
if (sum < (long)l * n || sum > (long)r * n) {
System.out.println(-1);
continue;
}
System.out.println(Math.max(lack, remain));
}
}
}
T4:好串
给一个0和1组成的字符串,求子串中有多少“好串”。对“好串”的定义是:所有的前缀子串中,0的数量全部严格大于1的数量。
思路:主要想法是用前缀和+单调栈。前缀和在遍历到 1 则加 1,遇到 0 则减 1。对于每一个左端点来说,合法的右端点是这个区间的前缀和值都大于等于左端点的前缀和值。因此考虑记录每一个位置的前缀和值,查询时用单调栈找到左端点的第一个小于左端点的前缀和值的位置,减一下就得到对应的区间对答案的贡献。时间复杂度O(nlogn)。
参考:https://www.nowcoder.com/feed/main/detail/17274cfeb3c143cdb4dc6e2bba0cd5df?sourceSSR=search
Java 后端笔经 文章被收录于专栏
Java 后端笔试经验
基恩士成长空间 451人发布
