2018贝壳找房研发校招笔试题

题目会做但是做不全对

一、多米诺骨牌

在一维平面上,存放着N个多米诺骨牌,每个骨牌有两个属性:位置,高度。
输入M个查询,每个查询为一个整数x,问推一下第x个骨牌,会有多少个骨牌倒下去

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class Main {
class Node {
    int x, h, index;
    int can;

    Node(int x, int h, int index) {
        this.x = x;
        this.h = h;
        this.index = index;
    }
}

Main() {
    Scanner cin = new Scanner(System.in);
    int n = cin.nextInt();
    Node[] a = new Node[n];
    for (int i = 0; i < n; i++) {
        a[i] = new Node(cin.nextInt(), cin.nextInt(), i);
    }
    Arrays.sort(a, Comparator.comparingInt(x -> x.x));
    for (int i = a.length - 1; i >= 0; i--) {
        a[i].can = 1;
        for (int j = i + 1; j < a.length; j++) {
            if (a[i].x + a[i].h <= a[j].x) break;
            a[i].can = Math.max(a[i].can, a[j].can + j - i);
        }
    }
    Arrays.sort(a, Comparator.comparingInt(x -> x.index));
    System.out.print(a[0].can);
    for (int i = 1; i < a.length; i++) {
        System.out.print(" " + a[i].can);

    }
}

public static void main(String[] args) {
    new Main();
}
}

二、最近公共祖先

在族谱上,存储着父子对,输入n对父子关系,如
子1 父1
子2 父2
.....

输入M个查询,每个查询包含A和B两个数字。如果A是B的祖先,输出1;如果B是A的祖先,输出2;否则,输出0。

这个问题很显然是经典的最近公共祖先问题LCA。以空间换时间,倍增算法。

import java.util.Scanner;

public class Main {

int[][] father;
int[] level;

int lca(int A, int B) {
    if (A == B) return A;
    if (level[A] == level[B]) {
        if (father[A][0] == father[B][0]) return father[A][0];
        for (int i = father[0].length - 1; i >= 0; i--) {
            if (father[A][i] == father[B][i]) continue;
            return lca(father[A][i], father[B][i]);
        }
    }
    if (level[A] > level[B]) {
        int tem = A;
        A = B;
        B = tem;
    }
    int i = father[0].length - 1;
    while ((1 << i) > level[B] - level[A]) {
        i--;
    }
    B = father[B][i];
    return lca(A, B);
}

int getLevel(int x) {
    if (father[x][0] == -1) return 1;
    if (level[x] != -1) return level[x];
    int i = father[0].length - 1;
    while (father[x][i] == -1) i--;
    level[x] = (1 << i) + getLevel(father[x][i]);
    return level[x];
}

Main() {
    Scanner cin = new Scanner(System.in);
    int n = cin.nextInt();
    int layer = 17;
    father = new int[n + 1][layer];
    level = new int[n + 1];
    for (int i = 0; i < father.length; i++) {
        for (int j = 0; j < father[i].length; j++) {
            father[i][j] = -1;
        }
    }
    for (int i = 0; i < n; i++) {
        father[cin.nextInt()][0] = cin.nextInt();
    }
    for (int i = 1; i < layer; i++) {
        for (int j = 1; j <= n; j++) {
            if (father[j][i - 1] == -1) {
                father[j][i] = -1;
            } else {
                father[j][i] = father[father[j][i - 1]][i - 1];
            }
        }
    }

    for (int i = 0; i < level.length; i++) {
        level[i] = -1;
    }
    for (int i = 1; i <= n; i++) {
        level[i] = getLevel(i);
    }
    int m = cin.nextInt();
    for (int i = 0; i < m; i++) {
        int A = cin.nextInt(), B = cin.nextInt();
        int anc = lca(A, B);
        if (anc == A) {
            System.out.println(1);
        } else if (anc == B) {
            System.out.println(2);
        } else {
            System.out.println(0);
        }
    }
}

public static void main(String[] args) {
    new Main();
}
}

三、按几次键才能变换数字

给定一个int,你只能对它执行两种操作:乘以2,减一。
输入两个int值N和M,问需要多少次操作才能从N变成M?

如果N>M,那么需要N-M次操作无疑。
如果N<M,那么至少需要ceil(log2(N/M))次,然后开始做减法。与其需要做这么多次减法,就不如把这些减法在乘2之前进行。

import java.util.PriorityQueue;
import java.util.Random;

public class Main {
int maxn = 1 << 7;
int[][] a = new int[maxn][maxn];

void init() {
    for (int i = 0; i < a.length; i++) {
        for (int j = 0; j < a.length; j++) {
            a[i][j] = maxn * 2;
        }
        a[i][i] = 0;
    }
    for (int i = 1; i < maxn; i++) {
        PriorityQueue<Integer> q = new PriorityQueue<>();
        q.add(i);
        while (!q.isEmpty()) {
            int j = q.poll();
            if (j >= maxn) continue;
            if (j * 2 < maxn) {
                if (a[i][j * 2] > a[i][j] + 1) {
                    q.add(j * 2);
                    a[i][j * 2] = a[i][j] + 1;
                }
            }
            if (j - 1 > 0) {
                if (a[i][j - 1] > a[i][j] + 1) {
                    q.add(j - 1);
                    a[i][j - 1] = a[i][j] + 1;
                }
            }
        }
    }
}

int solve(int n, int m) {
    if (n == m) return 0;
    if (n > m) {
        return n - m;
    }
    int miCount = (int) Math.ceil(Math.log(m * 1.0 / n) / Math.log(2));
    int p = n * (1 << miCount);
    if (p == m) return miCount;
    int sub = (p - m) / (1 << miCount);
    if (sub == 0) return solve(n * 2, m) + 1;
    return solve(n - sub, m) + sub;
}

Main() {
    Random r = new Random();
    init();
    for (int i = 0; i < 100; i++) {
        int n = r.nextInt(maxn - 1) + 1, m = r.nextInt(maxn - 1) + 1;
        System.out.println(n + " " + m + " " + solve(n, m) + " " + a[n][m]);
    }
}

public static void main(String[] args) {
    new Main();
}
}

猜你喜欢

转载自www.cnblogs.com/weiyinfu/p/9581707.html
今日推荐