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);
    }
}


#网易##网易笔试##网易互联网##2023一起秋招吧##面经笔经##做完网易2023秋招笔试题,我裂开了#
全部评论
第三题偶数长度找一个分割点 按两个奇数串处理 注意一下长度为1的情况 第四题离散化之后把每个数的位置按数的大小放入vector 再倒着枚举计算区间内贡献 用树状数组维护
2 回复 分享
发布于 2022-08-20 17:36 广东
咱俩思路挺像的
1 回复 分享
发布于 2022-08-20 18:48 湖北
第四题可以维护一个first点和一个前缀结点
3 回复 分享
发布于 2022-08-20 17:42 湖北
第三题 让所有偶数更新成偶数的最大值,所有奇数更新成奇数的最大值,如果两个最大值不等,直接返回,否则+数组的长度/2
1 回复 分享
发布于 2022-08-20 18:44 上海
第二题思路一样 可惜忘了用long结果没过去
1 回复 分享
发布于 2022-08-20 18:48 陕西
太强了
点赞 回复 分享
发布于 2022-08-20 17:30 河北
tql
点赞 回复 分享
发布于 2022-08-20 18:49 河南

相关推荐

不愿透露姓名的神秘牛友
09-23 18:00
点赞 评论 收藏
分享
18 43 评论
分享
牛客网
牛客企业服务