阿里Java實習生筆試題2020-03-27場

阿里的筆試題只有兩個編程題,讓我很意外。。。本以爲會有計算機網絡,數據庫,操作系統等類的基礎題。等筆試的時候發現就有兩道編程題。

第一題是一個給定一個序列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 + "]";
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章