128. 小美的排列询问
题目描述
小美拿到了一个排列。她想知道在这个排列中,x 和 y 是否是相邻的。你能帮帮她吗?排列是指一个长度为 n 的数组,其中 1 到 n 每个元素恰好出现一次。
输入描述
第一行输入一个正整数 n(1 <= n <= 200000),代表排列的长度。
第二行输入 n 个正整数 ai,代表排列的元素。
第三行输入两个正整数 x 和 y(1 <= ai, x, y <= n),用空格隔开。
保证 x != y
输出描述
如果 x 和 y 是相邻的,输出 Yes;否则输出 No。
输入示例
4
1 4 2 3
2 4
输出示例
Yes
提示信息
输入的排列是 1 4 2 3,x = 2,y = 4,2 和 4 是相邻的。输出 Yes.
import java.util.*;
class Main{
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Map<Integer, Integer> map = new HashMap<>();
for(int i = 0; i < n; i++){
map.put(sc.nextInt(), i);
}
int num1 = sc.nextInt();
int num2 = sc.nextInt();
int index1 = map.get(num1);
int index2 = map.get(num2);
if(index2 - index1 == 1 || index1 - index2 == 1){
System.out.println("Yes");
}else{
System.out.println("No");
}
}
}
129. 小美走公路
题目描述
有一个环形的公路,上面共有 n 站,现在给定了顺时针第 i 站到第 i + 1 站之间的距离(特殊的,也给出了第 n 站到第 1 站的距离)。小美想沿着公路第 x 站走到第 y 站,她想知道最短的距离是多少?
输入描述
第一行输入一个正整数 n(1 <= n <= 10^5),代表站的数量。
第二行输入 n 个正整数 ai(1 <= ai <= 10^9),前 n - 1 个数代表顺时针沿着公路走,i 站到第 i + 1 站之间的距离;
最后一个正整数代表顺时针沿着公路走,第 n 站到第 1 站的距离。
第三行输入两个正整数 x 和 y(1 <= x, y <= n),代表小美的出发地和目的地。
输出描述
一个正整数,代表小美走的最短距离。
输入示例
3
1 2 2
2 3
输出示例
2
构建一个环形链表,距离需要用long
来定义。
import java.util.*;
class Main{
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
int[] nums = new int[]{63, 21, 84, 54, 94, 74, 51, 65};
int sum = 0;
for(int i = 0; i < nums.length; i++){
sum += nums[i];
}
int n = sc.nextInt();
ListNode head = new ListNode();
ListNode tail = head;
long distance = 0;
for(int i = 0; i < n; i++){
int num = sc.nextInt();
ListNode node = new ListNode(num);
tail.next = node;
tail = node;
distance += num;
}
tail.next = head.next;
tail = tail.next;
int left = sc.nextInt(), right = sc.nextInt();
long cur = 0;
if (left < right){
for(int i = 1; i < left; i++){
tail = tail.next;
}
for(int i = left; i < right; i++){
cur += tail.val;
tail = tail.next;
}
}else{
for(int i = 1; i < right; i++){
tail = tail.next;
}
for(int i = right; i < left; i++){
cur += tail.val;
tail = tail.next;
}
}
System.out.println(Math.min(cur, distance - cur));
}
}
class ListNode{
int val;
ListNode next;
ListNode(){}
ListNode(int val){
this.val = val;
}
}
130. 小美的蛋糕切割
题目描述
小美有一个矩形的蛋糕,共分成了 n 行 m 列,共 n * m 个区域,每个区域是一个小正方形,已知蛋糕每个区域都有一个美味度。
她想切一刀把蛋糕切成两部分,自己吃一部分,小团吃另一部分。
小美希望两个人吃的部分的美味度之和尽可能接近,请你输出|s1 - s2|的最小值。(其中 s1 代表小美吃的美味度,s2 代表小团吃的美味度)。
请务必保证,切下来的区域都是完整的,即不能把某个小正方形切成两个小区域。
输入描述
第一行输出两个正整数 n 和 m(1 <= n, m <= 10^3),代表蛋糕区域的行数和列数。
接下来的 n 行,每行输入 m 个正整数 aij(1 <= aij <= 10^4),用来表示每个区域的美味度。
输出描述
一个整数,代表|s1-s2|的最小值。
输入示例
2 3
1 1 4
5 1 4
输出示例
0
提示信息
把蛋糕像这样切开:
1 1 | 4
5 1 | 4
左边蛋糕美味度之和是 8 右边蛋糕美味度之和是 8 所以答案是 0。
import java.util.*;
class Main{
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
int m = sc.nextInt();
int n = sc.nextInt();
int sum = 0;
int[][] cake = new int[m][n];
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
cake[i][j] = sc.nextInt();
sum += cake[i][j];
}
}
int res = sum;
int pre = 0;
//横切
for(int i = 0; i < m; i++){
for(int j = 0; j < n; j++){
pre += cake[i][j];
}
res = Math.min(res, Math.abs(pre - (sum - pre)));
}
pre = 0;
//竖切
for(int i = 0; i < n; i++){
for(int j = 0; j < m; j++){
pre += cake[j][i];
}
res = Math.min(res, Math.abs(pre - (sum - pre)));
}
System.out.println(res);
}
}
131. 小美的字符串变换
题目描述
小美拿到了一个长度为 n 的字符串,她希望将字符串从左到右平铺成一个矩阵
(先平铺第一行,然后是第二行,以此类推,矩阵有 x 行 y 列,必须保证 x * y=n,即每 y 个字符换行,共 x 行)。
该矩阵的权值定义为这个矩阵的连通块数量。小美希望最终矩阵的权值尽可能小,你能帮小美求出这个最小权值吗?
注:我们定义,上下左右四个方向相邻的相同字符是连通的。
输入描述
第一行输入一个正整数 n(1 <= n <= 10^4),代表字符串的长度。
第二行输入一个长度为 n 的、仅由小写字母组成的字符串。
输出描述
输出一个整数表示最小权值。
输入示例
9
aababbabb
输出示例
2
提示信息
平铺为 3 * 3 的矩阵:
aab
abb
abb
共有 2 个连通块,4 个 a 和 5 个 b。
利用dfs进行求解,本质上就是求岛屿数量问题leetcode200,只不过需要自己进行建图处理。
import java.util.*;
class Main{
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
int len = sc.nextInt();
String s = sc.next();
char[] ch1 = s.toCharArray();
int res = Integer.MAX_VALUE;
for(int i = 1; i * i <= len; i++){
if(len % i != 0) continue;
int m = i;
int n = len / i;
char[][] ch = new char[m][n];
int index = 0;
for(int x = 0; x < m; x++){
for(int y = 0; y < n; y++){
ch[x][y] = ch1[index];
index++;
}
}
int cnt = 0;
for(int x = 0; x < m; x++){
for(int y = 0; y < n; y++){
if(ch[x][y] != '0'){
char flag = ch[x][y];
dfs(ch, x, y, m, n, flag);
cnt++;
}
}
}
res = Math.min(res, cnt);
ch = new char[n][m];
index = 0;
for(int x = 0; x < n; x++){
for(int y = 0; y < m; y++){
ch[x][y] = ch1[index];
index++;
}
}
cnt = 0;
for(int x = 0; x < n; x++){
for(int y = 0; y < m; y++){
if(ch[x][y] != '0'){
char flag = ch[x][y];
dfs(ch, x, y, n, m, flag);
cnt++;
}
}
}
res = Math.min(res, cnt);
}
System.out.println(res);
}
public static void dfs(char[][] ch, int x, int y, int m, int n, char flag){
if(!inArea(x, y, m, n) || ch[x][y] != flag) return;
ch[x][y] = '0';
dfs(ch,x-1,y,m,n,flag);
dfs(ch,x+1,y,m,n,flag);
dfs(ch,x,y-1,m,n,flag);
dfs(ch,x,y+1,m,n,flag);
}
public static boolean inArea(int x, int y, int m, int n){
if(x < 0 || y < 0 || x >= m || y >= n) return false;
return true;
}
}
132. 小美的树上染色
题目描述
小美拿到了一棵树,每个节点有一个权值。初始每个节点都是白色。
小美有若干次操作,每次操作可以选择两个相邻的节点,如果它们都是白色且权值的乘积是完全平方数,小美就可以把这两个节点同时染红。
小美想知道,自己最多可以染红多少个节点?
输入描述
第一行输入一个正整数 n(1 <= n <= 10^5),代表节点的数量。
第二行输入 n 个正整数 ai(1 <= ai <= 10^9),代表每个节点的权值。
接下来的 n - 1 行,每行输入两个正整数 u,v(1 <= u, v <= n),代表节点 u 和节点 v 有一条边连接。
输出描述
输出一个整数,表示最多可以染红的节点数量。
输入示例
3
3 3 12
1 2
2 3
输出示例
2
提示信息
可以染红第二个和第三个节点。
请注意,此时不能再染红第一个和第二个节点,因为第二个节点已经被染红。 因此,最多染红 2 个节点。
dfs+List记录相邻节点
import java.util.*;
class Main{
static long[] weights;
static List<List<Integer>> neiborhoods;
static boolean[] isRed;
static int res = 0;
public static void main (String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
weights = new long[n + 1];
isRed = new boolean[n + 1];
for(int i = 1; i <= n; i++){
weights[i] = sc.nextInt();
}
neiborhoods = new ArrayList<>(n + 1);
for(int i = 0; i <= n; i++){
neiborhoods.add(new ArrayList<>());
}
for(int i = 1; i < n; i++){
int u = sc.nextInt();
int v = sc.nextInt();
neiborhoods.get(u).add(v);
neiborhoods.get(v).add(u);
}
dfs(1, -1);
System.out.println(res);
}
public static void dfs(int current, int last){
for(int neiborhood : neiborhoods.get(current)){
if(neiborhood == last) continue;
dfs(neiborhood, current);
if(!isRed[current] && !isRed[neiborhood] && redValid(current, neiborhood)){
isRed[current] = true;
isRed[neiborhood] = true;
res += 2;
}
}
}
public static boolean redValid(int current, int neiborhood){
long Mutiple = weights[current] * weights[neiborhood];
long square = (long) Math.sqrt(Mutiple);
return square * square == Mutiple;
}
}