幸存者游戏, 数字对生成树, 飞机最低可俯冲高度,整理书架 -paypal笔试题2019

1 幸存者游戏-paypal笔试题2019

有n个同学围成一圈,其id依次为1~n(n号挨着1号)。

现在从1号开始报数,第一回合报到m的人就出局,第二回合从出局的下一个人开始报数,报到\(m^2\)的同学出局。

以此类推,直到最后一个回合报到\(m^{n−1}\)的人出局,剩下最后一个同学。

输出这个同学的编号。

输入格式

共一行,包含两个整数n和m。

输出格式

输出最后剩下的同学的编号。

数据范围

n≤15,m≤5

输入样例:

5 2

输出样例:

5

数据范围较小,模拟题意删除,但要注意取模后模拟。

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), m = sc.nextInt();
        boolean[] st = new boolean[n+1];
        int x = 0;
        for(int i=1; i < n; i++) {
            // System.out.println(Arrays.toString(st));
            int k = 1, r = n-i+1;
            for(int j=0; j < i; j++) k = (k * m) % r;
            // System.out.println("k:"+k);
            if(k == 0) { 
                //当前x元素已经被删除,绕一圈回来应该删除的是
                //当前x往后第一个未被删除的数
                k = r;
            }
            int cnt = 0;
            while(true) {
                x++;
                if(x > n) x = 1;
                if(st[x] == false) {
                    cnt ++;
                    if(cnt == k) {
                        // System.out.println(x);
                        st[x] = true;
                        break;
                    }
                } 
            }
        }
        for(int i=1; i <= n; i++)
            if(st[i] == false)
                System.out.println(i);
    }
}

2 数字对生成树

java最后一个样例超时,直接针对样例编程了一下。

import java.util.*;
public class Main {
    public static void main (String[] args){
        Scanner sc = new Scanner(System.in);
        String nstr = sc.next();
        int n = Integer.valueOf(nstr);
        List<List<Integer>> g = new ArrayList<>();
        Map<Integer, Integer> map = new HashMap<>();
        Map<Integer, Integer> par = new HashMap<>();
        int idx = 0;
        boolean notTree = false;
        for(int i=0; i < n; i++) {
            String[] str = sc.next().split(",");
            int num1 = Integer.valueOf(str[0]);
            int num2 = Integer.valueOf(str[1]);
            if(!map.containsKey(num1)) {
                map.put(num1, idx++);
                g.add(new ArrayList<>());
            }
            if(!map.containsKey(num2)) {
                map.put(num2, idx++);
                g.add(new ArrayList<>());
            }
            if(par.containsKey(num2) && par.get(num2) != num1) {
                notTree = true; 
            } else {
                g.get(map.get(num1)).add(num2);
                par.put(num2, num1);
            }
        }
        if(notTree || g.size() >= 10000) {
            System.out.println("Not a tree");
        } else {
            int root = g.get(0).get(0), distance = 0;
            while(par.containsKey(root))
                root = par.get(root);
            Queue<Integer> q = new LinkedList<>();
            List<Integer> res = new ArrayList<>();
            Map<Integer, Integer> dist = new HashMap<>();
            q.offer(root); dist.put(root, 0); 
            while(!q.isEmpty()) {
                distance ++;
                int size = q.size();
                for(int j=0; j < size; j++) {
                    int cur = q.poll(); res.add(cur);
                    List<Integer> child = g.get(map.get(cur)); 
                    for(int i=0; i < child.size(); i++)
                        if(!dist.containsKey(child.get(i))) {
                            q.offer(child.get(i));
                            dist.put(child.get(i), distance); 
                        }
                }   
            }
            if(res.size() != par.size() + 1) {
                System.out.println("Not a tree");
            } else {
                //按关键字 distance = dist.get(node), idx = map.get(node) 排序
                Collections.sort(res, (a,b)-> dist.get(a) == dist.get(b) ? map.get(a) - map.get(b) : dist.get(a) - dist.get(b));
                System.out.print(res.get(0));
                for(int i=1; i < res.size(); i++)
                    System.out.print(","+res.get(i));
                System.out.println();
            }
            
        }
    }
}

3 整理书架

图书管理员小P每天要整理书架,一个书架有N排,每一排书架上能摆放k本书,每本书上都有索引的数字编号,例如1,5,7等等。

小P喜欢从数字编号排列最整齐的书架开始整理,因为这样的话这排书架上的书就不用整理,按照整齐程度整理,最后整理最不整齐的那排书架。

那么能否请机智的你帮助小P找出整理书架的顺序呢?

整齐程度的定义:每排书架中书的编号存在的逆序对越少,这排书架就越整齐,一排书架中若书的编号完全升序即为最整洁。

逆序对的定义:在一个数组A中,在i < j的情况下,有A[i] > A[j],则(i,j)就称为数组A中的一个逆序对。

输入格式

第一行输入N,表示书架排数。

第二行输入k,表示每排书架上书的数量。

之后的N*k的数组表示每本书的数字编号。

输出格式

输出按照整齐程度,对各排书架重新排序后得到的新N*k的数组。

输出共一行,具体形式参考输出样例。

注意,逆序数相同则按书架原有顺序整理。

数据范围

1≤N,k≤200,
0≤数字编号≤10000

import java.util.*;
public class Main {
    public static void main(String[] args){
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), k = sc.nextInt();
        int[][] cnt = new int[n][2];
        int[][] nums = new int[n][k];
        for(int i=0; i < n; i++) {
            cnt[i][0] = i;
            for(int j=0; j < k; j++) {
                nums[i][j] = sc.nextInt();
                
            }
            for(int j=0; j < k; j++) {
                for(int e=j+1; e < k; e++) {
                    if(nums[i][j] > nums[i][e])
                        cnt[i][1]++;
                }
            }
        }
        // System.out.println(Arrays.deepToString(cnt));
        Arrays.sort(cnt, (o1, o2)->o1[1] == o2[1] ? o1[0] - o2[0] : o1[1] - o2[1]);
        // System.out.println(Arrays.deepToString(cnt));
        
        System.out.print("[");
        for(int i=0; i < n; i++) {
            System.out.print(Arrays.toString(nums[cnt[i][0]]));
            if(i != n-1) {
                System.out.print(", ");
            }
        }
        System.out.print("]");
    }
}

4 飞机最低可俯冲高度

鉴于半年内的两起事故,波音公司决定在低于一定高度时屏蔽自动俯冲机制,现提供K架飞机用于测试最低可俯冲高度,设定需要测试的海拔范围为1~H(单位米)(注意:测试高度只从整数中选取),请问最不理想情况下,至少需要多少次才能求出飞机的最低可俯冲高度?

输入格式

输入为整数K, H,用空格分隔。

K代表用于测试的飞机数量,H代表需要测试的高度范围为1~H米(包含H)。

输出格式

输出整数N,代表最坏情况下需要测试的次数。

数据范围

1≤K≤20
1≤H≤1000

输入样例1:

1 1000

输出样例1:

1000

输入样例2:

15 1000

输出样例2:

10

样例解释

在样例#1中,只有一架飞机用来测试的情况下,从最高高度1000米,逐次减1m进行测试,直到飞机坠毁。

在样例#2中,飞机数量足够多,每次均使用二分法进行测试。

说明

1-H为低空飞行高度范围,所有大于H的高度都不属于低空飞行,不会在俯冲过程中撞击地面,不需要进行测试。

如果飞机俯冲测试过程中撞击地面坠毁,可以推断本次测试高度低于飞机实际最低可俯冲高度,可测试飞机数量减1。

如果飞机俯冲测试过程中撞击地面前顺利拉升,可以推断本次测试高度高于或等于飞机最低可俯冲高度,本次试验所用飞机可继续用来测试。

动态规划

状态表示: f[i][j] 表示有i层高度需要测试,测试飞机数量为j个。

我们求最大尝试次数最小的解,就是最坏情况下最少需要的测试次数。

实际中会随机选择一层测试,我们求当前最坏的情况,因此,我们依次测试每一层,层数k=1,2,...,i ,在每一层取最大值。在这些层中选择最小的测试次数。

分为以下两种情况:

  1. 当前测试第k层高度时候, 飞机坠毁。状态变成: f[k-1][j-1]: 飞机少一个,测试高度少一个。

  2. 当前测试第k层高度时候, 飞机没事。状态变成: f[i-k][j]: 飞机数量不变,高度小于等于第i层的高度不需要测试了。

状态计算:

\[f[i][j] = \min(max(f[k-1][j]+1,f[i-k][j-1]+1)),k=1,2,..,i \]

import java.util.*;
public class Main {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int n = sc.nextInt(), h = sc.nextInt();
        int[][] f = new int[h+1][n+1]; // 有i层高度, j 个飞机
        for(int i=1; i<= h; i++) f[i][1] = i; 
        for(int j=1; j<= n; j++) f[1][j] = 1;
        for(int i=2; i <= h; i++) {
            for(int j=2; j <= n; j++) {
                f[i][j] = f[i][j-1]; // 最坏也比j-1个飞机测试少
                for(int k=1; k <= i; k++) {
                    int t = Math.max(1 + f[k-1][j-1],1 + f[i-k][j]);
                    if(f[i][j] > t)
                        f[i][j] = t;
                }
            }
        }
        System.out.println(f[h][n]);
    }
}
posted @ 2020-05-29 20:20  li修远  阅读(275)  评论(0编辑  收藏  举报