首页 > 荣耀8.14通用软件笔试
头像
sick白牧
发布于 2021-08-15 10:03
+ 关注

荣耀8.14通用软件笔试

0. 序言

第一题花了10分钟A掉了,第二题30分钟A掉了,还有80分钟呢,以为第三题稳了。结果到最后才憋出来30%,目前牛客网上没看到思路,求大佬指点。

1. 将字母分为3个等级输出

输入一个字符串,高级为"bdfhkl",中级为"aceimnorstuvwxz",低级为"gjqpy",请将字符串按字母等级分割为3个字符串,每个字符串内按字典序排序输出。如果字符串为空输出null。
三个按字典序排序的优先队列就OK了,水题。

import java.util.PriorityQueue;
import java.util.Scanner;

public class Main1 {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        String s = scanner.next();
        PriorityQueue<Character> q1 = new PriorityQueue<>();
        PriorityQueue<Character> q2 = new PriorityQueue<>();
        PriorityQueue<Character> q3 = new PriorityQueue<>();

        for(int i=0;i<s.length();i++){
            switch (fun(s.charAt(i))){
                case 1:q1.add(s.charAt(i));break;
                case 2:q2.add(s.charAt(i));break;
                case 3:q3.add(s.charAt(i));break;
                default:break;
            }
        }
        if(q1.size()!=0){
            while(q1.size()!=0)
                System.out.print(q1.poll());
            System.out.println();
        }else
            System.out.println("null");
        if(q2.size()!=0){
            while(q2.size()!=0)
                System.out.print(q2.poll());
            System.out.println();
        }else
            System.out.println("null");
        if(q3.size()!=0){
            while(q3.size()!=0)
                System.out.print(q3.poll());
            System.out.println();
        }else
            System.out.println("null");
    }
    public static int fun(char c){
        switch (c){
            case 'b':
            case 'h':
            case 'f':
            case 'k':
            case 'l':
            case 'd':
                return 1;
            case 'g':
            case 'j':
            case 'p':
            case 'q':
            case 'y':
                return 3;
            default:
                return 2;
        }
    }
}

2. 推荐歌曲

每首歌属于一个流派,如pop/jazz等,不清楚流派的为UnKnown Style。
输入有三种情况:

  • I songName songStyle : 表示将流派为songStyle的、歌名为songName的歌加载到曲库。
  • P songName : 表示用户完整听完了名为songName的歌。
  • B songName : 表示用户切歌了名为songName的歌。

如若用户完整听完一首歌,则对这首歌的喜好度+3,如若这首歌与上次完整听完的歌是一个流派,则该流派内除了这首歌的喜好度+1。
如若用户切了一首歌,则对这首歌的喜好度-2,如若这首歌与上次切掉的歌是一个流派,则该流派内除了这首歌的喜好度-1。
按喜好度顺序输出歌名和它的流派,若喜好度相同,按字典序排序。

看起来复杂,起始就是根据题意模拟即可,关键在于设计双向映射的数据结构。一共用到了3个map,根据需要相互转换。
Map<String,List<string>> map;//表示一个流派下有哪些歌
Map<String,String> map2;//表示一首歌属于哪个流派
Map<String,Integer> map3;//表示歌的分数</string>

import java.util.*;

public class Main2 {

    static class Song{
        String name;
        String lib;
        int point;

        public Song(String name, String lib,int point) {
            this.name = name;
            this.lib = lib;
            this.point = point;
        }
    }

    static Map<String,List<String>> map;//lib - songs
    static Map<String,String> map2;//song - lib
    static Map<String,Integer> map3;//song - points

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        map = new HashMap<>();
        map2 = new HashMap<>();
        map3 = new HashMap<>();
        String lastP ="";
        String lastB = "";
        while(scanner.hasNextLine()){
            String s = scanner.nextLine();
            if(s.equals(""))
                break;
            String type = s.split(" ")[0];
            if(type.equals("I")){
                List<String> list =  map.getOrDefault(s.split(" ")[2], new ArrayList<>());
                list.add(s.split(" ")[1]);
                map.put(s.split(" ")[2],list);
                map2.put(s.split(" ")[1],s.split(" ")[2]);
                map3.put(s.split(" ")[1],0);
            }else if(type.equals("P")){
                String name = s.split(" ")[1];
                map3.put(name,map3.get(name)+3);
                if(map2.get(name).equals(lastP)){
                    String lib = map2.get(name);
                    for(String songNames:map.get(lib)){
                        if(!songNames.equals(name))
                            map3.put(songNames,map3.get(songNames)+1);
                    }
                }
                lastP = map2.get(name);

            }else{
                String name = s.split(" ")[1];
                map3.put(name,map3.get(name)-2);
                if(map2.get(name).equals(lastB)){
                    String lib = map2.get(name);
                    for(String songNames:map.get(lib)){
                        if(!songNames.equals(name))
                            map3.put(songNames,map3.get(songNames)-1);
                    }
                }
                lastB = map2.get(name);
            }
        }
        Queue<Song> q = new PriorityQueue<>(new Comparator<Song>() {
            @Override
            public int compare(Song o1, Song o2) {
                if(o1.point==o2.point)
                    return o1.name.compareTo(o2.name);
                return -o1.point + o2.point;
            }
        });
        for(String key:map3.keySet())
            q.add(new Song(key,map2.get(key),map3.get(key)));
        while(q.size()!=0){
            Song song = q.poll();
            System.out.println(song.name+" "+song.lib);
        }
    }
}

3.切水果

40*50的方格上,有若干个水果,可以横向/纵向/斜向(斜率为±1)4个角度消去一条直线上的水果,问至少需要几刀可以全部切除。
用了贪心,bfs,dfs,分别过了10% 30% 20%。贪心明显是不对的,但是也不至于过那么少吧。。。

方法一:贪心(10%)

每次取最大收益的一刀。当然贪心理论是不对的,我可以找出反例,但应该能覆盖不少用例啊~

import java.util.*;

public class Main30 {

    static Map<String,List<Integer>> map;
    static class D{
        String type;
        List<Integer> list;

        public D(String type, List<Integer> list) {
            this.type = type;
            this.list = list;
        }
    }
    static int[] temp;

    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        map = new HashMap<>();
        temp = new int[n];
        for(int i = 0;i<n;i++){
            int x = scanner.nextInt();
            int y = scanner.nextInt();
            add(x,y,i);
        }
        Queue<D> q = new PriorityQueue<>(new Comparator<D>() {
            @Override
            public int compare(D o1, D o2) {
                int cnt1 = 0;
                int cnt2 = 0;
                for(int a:o1.list)
                    if(temp[a]==0)
                        cnt1++;
                for(int a:o2.list)
                    if(temp[a]==0)
                        cnt2++;
                return -cnt1+cnt2;
            }
        });
        for(String key:map.keySet())
            q.add(new D(key,map.get(key)));

        int all = 0;
        int res = 0;
        while(q.size()!=0){
            D d = q.poll();
            res++;
            for(int i:d.list){
                if(temp[i]==0){
                    temp[i] = 1;
                    all++;
                }
            }
            if(all==n)
                break;
        }
        System.out.println(res);
    }
    public static void add(int x,int y,int i){
        //纵向
        List<Integer> list1 = map.getOrDefault("0-"+y, new ArrayList<>());
        list1.add(i);
        map.put("0-"+y,list1);
        //横向
        list1 = map.getOrDefault("1-"+x, new ArrayList<>());
        list1.add(i);
        map.put("1-"+x,list1);
        //从左上到右下
        list1 = map.getOrDefault("2-"+(y-x), new ArrayList<>());
        list1.add(i);
        map.put("2-"+(y-x),list1);
        //从右上到左下
        list1 = map.getOrDefault("3-"+(x+y), new ArrayList<>());
        list1.add(i);
        map.put("3-"+(x+y),list1);
    }
}

方法二:BFS(30%,TLE)

将剩余水果列表作为节点,每次拓展时,将列表里每个节点的四刀作为可能性,消去列表x||y||x+y||x-y相同的,作为子节点继续加入队列,直到某个列表为空,则当前次数为最少次数。不知道还能怎么优化...

import java.util.*;

public class Main31 {

    static Map<String,Set<List<Integer>>> map;

    static int[][] a;
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        map = new HashMap<>();
        a = new int[n][2];
        for(int i = 0;i<n;i++){
            a[i][0] = scanner.nextInt();
            a[i][1] = scanner.nextInt();
        }
        Queue<List<Integer> > q = new LinkedList<>();
        List<Integer> root =  new ArrayList<>();
        for(int i=0;i<n;i++)
            root.add(i);
        q.add(root);
        int res = 0;
        while(q.size()!=0){
            res++;
            Queue<List<Integer> > q2 = new LinkedList<>();
            while(q.size()!=0){
                List<Integer> list = q.poll();
                Set<List<Integer>> lists = expand(list);
                for(List<Integer> t:lists){
                    if(t.size()==0){
                        System.out.println(res);
                        return;
                    }
                }
                q2.addAll(lists);
            }
            q = q2;
        }

    }


    public static Set<List<Integer>> expand(List<Integer> list){
        if(map.containsKey(list.toString()))
            return map.get(list.toString());
        Set<List<Integer>> res = new HashSet<>();
        List<Integer> list1;
        for(int e:list){
            int x = a[e][0];
            list1 = new ArrayList<>();
            for(int ee:list)
                if(a[ee][0]!=x)
                    list1.add(ee);
            res.add(list1);

            int y = a[e][1];
            list1 = new ArrayList<>();
            for(int ee:list)
                if(a[ee][1]!=y)
                    list1.add(ee);
            res.add(list1);

            int xy = a[e][0]-a[e][1];
            list1 = new ArrayList<>();
            for(int ee:list)
                if(a[ee][0]-a[ee][1]!=xy)
                    list1.add(ee);
            res.add(list1);

            int yx = a[e][0]+a[e][1];
            list1 = new ArrayList<>();
            for(int ee:list)
                if(a[ee][0]+a[ee][1]!=yx)
                    list1.add(ee);
            res.add(list1);
        }
        map.put(list.toString(),res);
        return res;
    }
}

方法三:DFS(20%,TLE)

扩展方法和bfs一样,不过每个dfs方法里记载当前的次数,如果次数已经大于了目前最少次数,则剪枝。另外用一个map做缓存。
对于某个节点扩展出的四条dfs路径,优先执行收益更高的,即局部贪心,但好像也没什么用...

import java.util.*;

public class MainF {

    static Map<String,Integer> map;
    static int[][] a;
    static int step;
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        map = new HashMap<>();
        a = new int[n][2];
        step = Integer.MAX_VALUE;
        for(int i = 0;i<n;i++){
            a[i][0] = scanner.nextInt();
            a[i][1] = scanner.nextInt();
        }
        Queue<List<Integer> > q = new LinkedList<>();
        List<Integer> root =  new ArrayList<>();
        for(int i=0;i<n;i++)
            root.add(i);
        dfs(0,root);
        System.out.println(step);
    }

    public static void dfs(int cnt, List<Integer> list){
        if(cnt>step)
            return;
        if(map.containsKey(list.toString())){
            if(map.get(list.toString())<cnt)
                return;
        }

        if(list.size()==0)
            step = Math.min(step,cnt);
        List<Integer> list1,list2,list3,list4;
        for(int e:list){
            int x = a[e][0];
            list1 = new ArrayList<>();
            for(int ee:list)
                if(a[ee][0]!=x)
                    list1.add(ee);
            int y = a[e][1];
            list2 = new ArrayList<>();
            for(int ee:list)
                if(a[ee][1]!=y)
                    list2.add(ee);
            int xy = a[e][0]-a[e][1];
            list3 = new ArrayList<>();
            for(int ee:list)
                if(a[ee][0]-a[ee][1]!=xy)
                    list3.add(ee);
            int yx = a[e][0]+a[e][1];
            list4 = new ArrayList<>();
            for(int ee:list)
                if(a[ee][0]+a[ee][1]!=yx)
                    list4.add(ee);
                Queue<List<Integer>> q= new PriorityQueue<>(new Comparator<List<Integer>>() {
                    @Override
                    public int compare(List<Integer> o1, List<Integer> o2) {
                        return o1.size()-o2.size();
                    }
                });
            q.add(list1);
            q.add(list2);
            q.add(list3);
            q.add(list4);
            while(q.size()!=0){
                List<Integer> list5 = q.poll();
                dfs(cnt+1,list5);
            }
            map.put(list.toString(),cnt);
        }
    }
}

改进:我为什么要对于每个节点的四种方式排序效率最优啊?明明可以所有节点的四种方式一起排效率最优,相当于贪心了。事后诸葛亮

import java.util.*;

public class MainF {

    static Map<String,Integer> map;
    static int[][] a;
    static int step;
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        map = new HashMap<>();
        a = new int[n][2];
        step = Integer.MAX_VALUE;
        for(int i = 0;i<n;i++){
            a[i][0] = scanner.nextInt();
            a[i][1] = scanner.nextInt();
        }
        Queue<List<Integer> > q = new LinkedList<>();
        List<Integer> root =  new ArrayList<>();
        for(int i=0;i<n;i++)
            root.add(i);
        dfs(0,root);
        System.out.println(step);
    }

    public static void dfs(int cnt, List<Integer> list){
        if(cnt>step)
            return;
        if(map.containsKey(list.toString())){
            if(map.get(list.toString())<cnt)
                return;
        }

        if(list.size()==0)
            step = Math.min(step,cnt);
        List<Integer> list1,list2,list3,list4;
        Queue<List<Integer>> q= new PriorityQueue<>(new Comparator<List<Integer>>() {
                    @Override
                    public int compare(List<Integer> o1, List<Integer> o2) {
                        return o1.size()-o2.size();
                    }
                });
        for(int e:list){
            int x = a[e][0];
            list1 = new ArrayList<>();
            for(int ee:list)
                if(a[ee][0]!=x)
                    list1.add(ee);
            int y = a[e][1];
            list2 = new ArrayList<>();
            for(int ee:list)
                if(a[ee][1]!=y)
                    list2.add(ee);
            int xy = a[e][0]-a[e][1];
            list3 = new ArrayList<>();
            for(int ee:list)
                if(a[ee][0]-a[ee][1]!=xy)
                    list3.add(ee);
            int yx = a[e][0]+a[e][1];
            list4 = new ArrayList<>();
            for(int ee:list)
                if(a[ee][0]+a[ee][1]!=yx)
                    list4.add(ee);

            q.add(list1);
            q.add(list2);
            q.add(list3);
            q.add(list4);
        }
        while(q.size()!=0){
            List<Integer> list5 = q.poll();
            dfs(cnt+1,list5);
        }
        map.put(list.toString(),cnt);
    }
}

全部评论

(3) 回帖
加载中...
话题 回帖