20220820网易互联网笔试代码(3.2/4)
第一题
给你两个数a,b,把数当成字符串,可以从两个字符串中删除任意字符,问最少删除几次,使得a是b的倍数,或者b是a的倍数
思路
因为数的范围小于10^9,用DFS分别生成a,b删除可以得到的所有数的集合,并记录需要删除的次数。最后遍历两个集合求最小值
package wangyi;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Q1 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int num1 = sc.nextInt();
int num2 = sc.nextInt();
String s1 = new StringBuilder(Long.toString(num1)).reverse().toString();
String s2 = new StringBuilder(Long.toString(num2)).reverse().toString();
Map<Integer,Integer> cnt1 = new HashMap<>();
Map<Integer,Integer> cnt2 = new HashMap<>();
getDDD(s1,0,0,cnt1,0);
getDDD(s2,0,0,cnt2,0);
int ans = s1.length()+s2.length()+1;
/* for (Integer val : cnt1.keySet()) {
System.out.println("key1:"+val+":"+cnt1.get(val));
}
for (Integer val : cnt2.keySet()) {
System.out.println("key1:"+val+":"+cnt2.get(val));
}*/
for (Integer key1 : cnt1.keySet()) {
for (Integer key2 : cnt2.keySet()) {
if(key1%key2 == 0 || key2%key1==0){
ans = Math.min(ans,cnt1.get(key1)+cnt2.get(key2));
}
}
}
System.out.println(ans==(s1.length()+s2.length()+1)?-1:ans);
}
public static void getDDD(String str,int p,int val,Map<Integer,Integer> map,int cnt){
if(str.length()==p){
if(val!=0){
map.put(val,str.length()-cnt);
}
return;
}
//不要当前元素
getDDD(str,p+1,val,map,cnt);
//要当前元素
val += (str.charAt(p)-'0')*(int)Math.pow(10,cnt);
getDDD(str,p+1,val,map,cnt+1);
}
}
第二题
长城,给你一个数组,你可以往任何一个位置上加一(次数不限),问最少加多少次可以让这个数组变成长城(长城的定义:任意一个数左右两个数字相等)
思路
计算奇数位置和偶数位置的最大值,确定他们的高度,如果相同得考虑是把奇数位置+1,还是偶数位置+1的问题
package wangyi;
import java.util.Scanner;
public class Q2 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
long arr[] = new long[n];
long firstMax=0,secondMax=0;
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
if(i%2==0) firstMax=Math.max(firstMax,arr[i]);
else secondMax=Math.max(secondMax,arr[i]);
}
if(firstMax == secondMax){
System.out.println(Math.min(minOps2(arr,firstMax+1,secondMax),minOps2(arr,firstMax,firstMax+1)));
}
else
System.out.println(minOps2(arr,firstMax,secondMax));
}
public static long minOps2(long arr[],long num1,long num2){
long ans = 0;
for (int i = 0; i < arr.length; i++) {
ans+=(i%2==0?num1-arr[i]:num2-arr[i]);
}
return ans;
}
}
第三题
red问题,给你一个字符串,里面只包含red三个字符,你每次可以把一个字符变成另一个字符,问你最少操作几次,可以使得字符串中好e最多。“好e的定义”:左边和右边必须是r和d,比如red和der。思路
(只过了60%)要使得好e最多,字符串是有规律的,比如redered,由一个r(或d)跟着一个e,那么下一个肯定是d(或r)。生成这样的字符串,和原字符串比较。
问题:奇数长度好像满足这规律,偶数长度很恶心,如果有大佬,请指教下。
package wangyi;
import java.util.*;
public class Q3 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
int n = str.length();
String re = construct(new StringBuilder(), new char[]{'r', 'd'}, 2*n);
String de = construct(new StringBuilder(), new char[]{'d', 'r'}, 2*n);
String er = construct(new StringBuilder("e"), new char[]{'r', 'd'}, 2*n);
String ed = construct(new StringBuilder("e"), new char[]{'d', 'r'}, 2*n);
if (n % 2 == 1) {
int ans = Math.min(minChange(str, re,0,n), minChange(str, de,0,n));
ans = Math.min(ans, minChange(str, er,0,n));
ans = Math.min(ans, minChange(str, ed,0,n));
System.out.println(ans);
} else {
int ans = Math.min(minChange(str, re,0,n), minChange(str, de,0,n));
ans = Math.min(ans, minChange(str, er,0,n));
ans = Math.min(ans, minChange(str, ed,0,n));
ans = Math.min(ans, minChange(str, re,1,n));
ans = Math.min(ans, minChange(str, de,1,n));
ans = Math.min(ans, minChange(str, er,1,n));
ans = Math.min(ans, minChange(str, ed,1,n));
ans = Math.min(ans, minChange(str, re,2,n));
ans = Math.min(ans, minChange(str, de,2,n));
ans = Math.min(ans, minChange(str, er,2,n));
ans = Math.min(ans, minChange(str, ed,2,n));
System.out.println(ans);
}
}
public static int minChange(String s1, String s2,int left,int right) {
int ans = 0;
for (int i = left; i < right; i++) {
if (s1.charAt(i) != s2.charAt(i)) ans++;
}
return ans;
}
public static String construct(StringBuilder sb, char order[], int n) {
int p = 0;
while (sb.length() < n) {
sb.append(order[p]);
p = (p + 1) % 2;
if (sb.length() < n) {
sb.append('e');
}
}
return sb.toString();
}
}
第四题
给你一个数组,定义三元组(i,j,k)为arr[i]==arr[k]并且arr[j]<arr[i],问这样的三元组有多少个思路
(只过了60%)先计算每个数左边小于他的元素有多少个。然后再一次遍历,用哈希表存住每个元素的位置,这样下一个位置的相同的元素就可以计算三元组的个数了
package wangyi;
import java.util.*;
public class Q4 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int arr[] = new int[n];
for (int i = 0; i < n; i++) {
arr[i] = sc.nextInt();
}
int leftMinCnt[] = new int[n];
for (int i = 1; i < n; i++) {
for (int j = i-1; j >= 0; j--) {
if(arr[j]<arr[i]) leftMinCnt[i]++;
}
//System.out.println("i:"+i+"\tval:"+arr[i]+"\tleft:"+leftMinCnt[i]);
}
HashMap<Integer,List<Integer>> map = new HashMap();
int ans = 0;
for (int i = 0; i < n; i++) {
//应该可以优化的,map只存上一次的地址,然后加上一个元素的结果,不用每个相同元素的访问过去
List<Integer> list = map.getOrDefault(arr[i],new ArrayList<>());
for (int j = 0; j < list.size(); j++) {
ans+= (leftMinCnt[i]-leftMinCnt[list.get(j)]);
}
list.add(i);
map.put(arr[i],list);
}
System.out.println(ans);
}
}

