阿里的筆試題只有兩個編程題,讓我很意外。。。本以爲會有計算機網絡,數據庫,操作系統等類的基礎題。等筆試的時候發現就有兩道編程題。
第一題是一個給定一個序列A與一個序列B,每次只能把序列A的一個字符移動到字符尾,問能否通過這種方式把序列A變爲序列B,如果能變成,最少需要多少次,輸出最少次數N,不能變成輸出-1。
這題還是挺簡單的。代碼我也沒有保存。。。所以就不對這個進行解釋了,如果有疑問可以在下面留言。有需要我會解釋一下。
第二題是給你N個區間,對每個區間(Li,Ri)隨機取一個數,得出N個數,取到的數中最小的數的期望是多少,其中1<=N<=2000,1<=Li<=Ri<=2000。要求好像是誤差要小於 1e-6。
例子
2
1 1
2 3
這個有{1,2},{1,3},{2,2},{2,3},{3,2}{3,3},這個期望是1.8333333
對於這個肯定不能一個一個的列出來,我是使用優先隊列,每次把Li最小的拿出來,筆試中我是看它在所佔的權重,把所有的相加,除以總的數量算的,由於沒有考慮到數的大小問題,出現數太大,超出計算範圍,無法計算,導致只是過了35%的數據。這種方法相對來說精度高一些,因爲只有最後一個除法是會導致精度誤差的,之前的運算都是整數。都不存在精度的問題。在筆試後想到了修改的方法,就是看它在所有中所佔的概率,加權後相加,然後就能得出期望結果,這樣雖然會產生較大的誤差,但是這種方法是可計算的,不會出現數太大,導致無法計算的情況。總體的複雜度只有N2logN,這個。以下是我使用概率方法的代碼
import java.util.PriorityQueue;
import java.util.Scanner;
public class Main {
static double qw = 0;
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
Node arr[] = new Node[n];
for(int i = 0;i<n;i++) {
arr[i] = new Node(sc.nextInt());
}
for(int i = 0;i<n;i++) {
arr[i].b = sc.nextInt();
}
PriorityQueue<Node> pq = new PriorityQueue<Node>();
for(int i = 0;i<n;i++) {
pq.add(arr[i]);
}
double test = 1;
double ans = 0;
while(!pq.isEmpty()) {
Node te = pq.poll();
if(te.b<te.a||test<=0) {
break;
}
ans += test*te.a/(te.b-te.a+1);
test = test - test/(te.b-te.a+1);
te.a++;
pq.add(te);
}
System.out.println(ans);
}
}
class Node implements Comparable<Node>{
int a;
int b;
public Node() {
}
public Node(int a) {
this.a = a;
}
@Override
public int compareTo(Node o) {
return this.a - o.a;
}
@Override
public String toString() {
return "Node [a=" + a + ", b=" + b + "]";
}
}