拼多多笔试

考试时间:2h

题型:4道编程题

很变态的是,考试的时候需要始终开着手机端微信中的一个小程序来防止作弊。

本人很菜,这些思路都是借鉴了广大网友的。

直接上题吧

几乎严格升序

  • 定给两个数组A状语从句:B,数组其中A的英文几乎严格升序个结果排列的,几乎的定义是只需改变其中一个数,即可满足完全升序排列。的你的英文任务从A中找到这个数组,并数组从B中选取一个数将其代替,使得A的英文严格升序个结果排列的,请找出乙中满足要求的最大数字,并输出有序数组,如不存在则输出NO。
input
1 3 8 7 10
2 1 7 5 9 8
output
1 3 8 9 10
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Scanner;

/**
 * 给定两个数组A和B,其中数组A是几乎严格升序排列的,几乎的定义是只需改变其中一个数,即可满足完全升序排列。你的任务是从A中找到这个数组,并从数组B中选取一个数将其代替,
 * 使得A是严格升序排列的,请找出B中满足要求的最大数字,并输出有序数组,如不存在则输出NO。
 */
public class Q1 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while (in.hasNext()) {
            // 输入
            String[] aa = in.nextLine().split(" ");
            String[] bb = in.nextLine().split(" ");
            int[] a = new int[aa.length];
            int[] b = new int[bb.length];
            for (int i = 0; i < a.length; i++) {
                a[i] = Integer.parseInt(aa[i]);
            }
            for (int i = 0; i < b.length; i++) {
                b[i] = Integer.parseInt(bb[i]);
            }

            printSorted(a, b);
        }
    }

    public static void printSorted(int[] a, int[] b){
        int i = 0;
        for (;i<a.length;i++){
            if(a[i]>=a[i+1]){
                break;
            }
        }
        Arrays.sort(b);
        i = i+1;
        int maxVal = Integer.MAX_VALUE;
        if(i+1<a.length){
            maxVal = a[i+1];
        }
        int v = binarySearch(b,0,b.length-1,a[i-1],maxVal);
        if(v==-1){
            i = i-1;
            int minVal = Integer.MIN_VALUE;
            if(i > 0){
                minVal = a[i-1];
            }
            v = binarySearch(b,0,b.length-1,minVal,a[i+1]);
        }
        if(v==-1){
            System.out.println("NO");
            return;
        }
        a[i] = v;
        for(int j=0;j<a.length;j++){
            System.out.print(a[j]);
            System.out.print(" ");
        }

    }

    private static int binarySearch(int[] arr, int l, int r, int v1, int v2){
        int mid = (l+r)/2;
        int midValue = arr[mid];
        if(l>r)
            return -1;
        if(midValue<=v1){
            return binarySearch(arr, mid+1,r,v1,v2);
        }else if(midValue>=v2){
            return binarySearch(arr,l,mid-1,v1,v2);
        }else{
            int tmp = mid+1;
            while (tmp<=r && arr[tmp]<v2){
                tmp ++;
            }
            return arr[tmp-1];
        }
    }
}

首尾相连的一组字符串

  • 给定一个字符串数组(字符串长度和数组长度均大于1且小于1024),所有字符均为大写字母。请问,给定的字符串数组是否能通过更换数组中元素的顺序,从而首尾相连,形成一个环。
input
CAT TEAM MAC
output
true

牛客上有人说,只要首,尾的字母是偶数就可以通过。可能是测试数据太弱了。但实际上AB AB这一类是不能成环的。

public class E2 {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        while(in.hasNext()) {
            String[] words = in.nextLine().split(" ");
            if(null == words || words.length < 2) System.out.println("false");
            boolean[] isUsed = new boolean[words.length];
            boolean flag = backtrack(words, new ArrayList<String>(), isUsed);
            if(flag) System.out.println("true");
            else System.out.println("false");
        }
    }

    private static boolean backtrack(String[] words, ArrayList<String> curList, boolean[] isUsed) {
        boolean flag = false;
        if(words.length == curList.size()) {
            String first = curList.get(0);
            String last = curList.get(curList.size()-1);
            return last.charAt(last.length()-1) == first.charAt(0);
        }
        for(int i = 0; i < words.length; ++i) {
            if(isUsed[i]) continue;
            if(curList.size() == 0) {
                curList.add(words[i]);
            } else {
                String prev = curList.get(curList.size()-1);
                if(prev.charAt(prev.length()-1) != words[i].charAt(0)) continue;
                curList.add(words[i]);
            }
            isUsed[i] = true;
            flag = backtrack(words, curList, isUsed);
            isUsed[i] = false;
            curList.remove(curList.size()-1);
            if(flag) break;
        }
        return flag;
    }
}

这题值AC了95,不知道问题出在哪里。

多任务的执行顺序

  • 一现在教育学习语言文字N个待执行的任务,每个任务需要裨的时间完成执行。同时任务之间可能会有一些依赖关系,比如任务1可能依赖任务2和任务3,那么任务1必须等任务2和任务3执行完成后才能开始执行。为了最小化任务的平均返回时长,请安排所有任务的执行顺序。假设在零时刻,所有ñ个任务已到达系统。
  • 本题应该是考察图的拓扑序,即所有的任务根据依赖关系可以画出一张依赖图,每轮迭代执行一批入度为0的任务,为了满足平均返回时长最小的要求,入度为0的任务再根据任务时长短的优先执行的贪心策略执行,可以使用优先队列实现。
import java.util.*;
public class Q3 {
    static class Task {
        int seq;
        int weight;

        /**
         * @param n  任务的编号
         * @param w  任务的花费时间
         */
        public Task(int n, int w) {
            seq = n;
            weight = w;
        }
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        int m = in.nextInt();
        Task[] t = new Task[n+1];
        for(int i = 1; i < n+1; ++i) {
            t[i] = new Task(i, in.nextInt());
        }

        // construct dependency raph
        Map<Integer, List<Integer>> graph = new HashMap<>();
        int[] indegree = new int[n+1];
        for(int i = 0; i < m; ++i) {
            int u = in.nextInt();
            int v = in.nextInt();
            if(graph.containsKey(u)) {
                graph.get(u).add(v);
            } else {
                List<Integer> edges = new ArrayList<>();
                edges.add(v);
                graph.put(u, edges);
            }
            indegree[v]++;
        }

        //topological sort, 按照任务的时间,从小到大排序
        PriorityQueue<Task> queue = new PriorityQueue<>(new Comparator<Task>() {
            @Override
            public int compare(Task o1, Task o2) {
                return o1.weight-o2.weight;
            }
        });

        // 将入度为0,即没有依赖关系的,根据贪心策略,按时间从短到长依次执行
        for(int i = 1; i < n+1; ++i) {
            if(indegree[i] == 0) queue.offer(t[i]);
        }

        // 将入度为0的任务完成后,其后续任务可以将入度-1
        List<Integer> res = new ArrayList<>();
        while (! queue.isEmpty()) {
            Task complete = queue.poll();
            res.add(complete.seq);
            if (graph.containsKey(complete.seq)) {
                for (int i: graph.get(complete.seq)) {
                    if (--indegree[i] == 0) {
                        queue.offer(t[i]);
                    }
                }
            }
        }

        for (int i = 0; i < n; i++) {
            System.out.println(res.get(i));
            if (i != n - 1) System.out.println(" ");
        }

    }

}

搭积木

  • 有N个长方体积木,每个积木的高都是1,长宽都为Li,重量为Wi。现在想要用这些积木搭一个高高的金字塔,每一层由且仅由一块积木组成,同时每一层积木的边长都比下方的积木小,每块积木智能承受自身重量的7倍重量,请计算最高可以搭一个多高的金字塔?
  • 本题应该以前我个积木能搭成高为ħ的金字塔的最小重量为状态,那么状态转移方程为 dp[i][h]=min(dp[i][h], dp[k][h-1]+b[i].weight)
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.Scanner;
public class Q4 {
    public static class Box {
        int len;
        int weight;
    }

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        int n = in.nextInt();
        Box[] b = new Box[n+1];
        b[0] = new Box();
        for(int i = 1; i < n+1; ++i) {
            b[i] = new Box();
            b[i].len = in.nextInt();
        }
        for(int i = 1; i < n+1; ++i) {
            b[i].weight = in.nextInt();
        }

        Arrays.sort(b, new Comparator<Box>() {
            @Override
            public int compare(Box o1, Box o2) {
                return o1.len == o2.len ? o1.weight - o2.weight : o1.len - o2.len;
            }
        });

        int maxRes = 0;
        int[][] dp = new int[n+1][n+1];
        for (int i = 0; i < n+1; i++) {
            for (int j = 0; j < n+1; j++) {
                dp[i][j] = Integer.MAX_VALUE;
            }
        }
        dp[0][0] = 0;
        for (int i = 1; i < n+1; i++) {
            for (int k = 0; k < i; k++) {
                if (b[k].len < b[i].len) {  // 上层比下层要小
                    for (int j = 0; j <= k; j++) {
                        if (dp[k][j] != Integer.MAX_VALUE && dp[k][j] < b[i].weight * 7) {
                            dp[i][j+1] = Math.min(dp[i][j+1], dp[k][j] + b[i].weight);
                            maxRes = Math.max(maxRes, j + 1);
                        }
                    }
                }
            }
        }
        System.out.println(maxRes);
    }

}

参考资料:
https://www.hytheory.com/algorithm/pdd-exam/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值