貝殼找房 2020校招 研發工程師試卷題解
第一題
編程題|30.0分1/4
計算絕對值
**時間限制:**C/C++語言 1000MS;其他語言 3000MS
**內存限制:**C/C++語言 131072KB;其他語言 655360KB
題目描述:
給出n個正整數,要求找出相鄰兩個數字中差的絕對值最小的一對數字,如果有差的絕對值相同的,則輸出最前面的一對數。
2<n<=100,正整數都在10^16範圍內
輸入
輸入包含2行,第一行爲n,第二行是n個用空格分隔的正整數。
輸出
輸出包含一行兩個正整數,要求按照原來的順序輸出
樣例輸入
9
1 3 4 7 2 6 5 12 32
樣例輸出
3 4
AC 100% 代碼,簽到題,注意用long類型:
import java.util.Scanner;
/**
* @author HGS
* @date 2019/08/10
*/
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
long[] num = new long[n];
for (int i = 0; i < n; i++) {
num[i] = sc.nextLong();
}
long res = Long.MAX_VALUE;
int idx = 0;
for (int i = 1; i < n; i++) {
if(Math.abs(num[i] - num[i-1]) < res){
res = Math.abs(num[i] - num[i-1]);
idx = i;
}
}
System.out.println(num[idx-1] +" "+num[idx]);
}
}
第二題
編程題|30.0分2/4
月光寶盒的密碼
**時間限制:**C/C++語言 1000MS;其他語言 3000MS
**內存限制:**C/C++語言 131072KB;其他語言 655360KB
題目描述:
小希偶然得到了傳說中的月光寶盒,然而打開月光寶盒需要一串密碼。雖然小希並不知道密碼具體是什麼,但是月光寶盒的說明書上有着一個長度爲 n (2 <= N <= 50000)的序列 a (-10^9 <= a[i] <= 10^9)的範圍內。下面寫着一段話:密碼是這個序列的最長的嚴格上升子序列的長度(嚴格上升子序列是指,子序列的元素是嚴格遞增的,例如: [5,1,6,2,4]的最長嚴格上升子序列爲[1,2,4]),請你幫小希找到這個密碼。
輸入
第1行:1個數N,N爲序列的長度(2<=N<=50000)
第2到 N+1行:每行1個數,對應序列的元素(-10^9 <= a[i] <= 10^9)
輸出
一個正整數表示嚴格最長上升子序列的長度
樣例輸入
8
5
1
6
8
2
4
5
10
樣例輸出
5
AC 54 % 的數據 代碼
import java.util.Scanner;
/**
* @author HGS
* @date 2019/08/10
*/
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] nums = new int[n];
int[] dp = new int[n];
for (int i = 0; i < n; i++) {
nums[i] = sc.nextInt();
}
int res = 0;
for (int i = 1; i < n; i++) {
int max = 1;
for (int j = 0; j < i; j++) {
if (nums[i] > nums[j]) {
max = Math.max(max, dp[j] + 1);
}
}
dp[i] = max;
if(max > res){
res = max;
}
}
System.out.println(res);
}
}
以上解法的時間複雜度爲 O(N2),可以使用二分查找將時間複雜度降低爲 O(NlogN)。
定義一個 tails 數組,其中 tails[i] 存儲長度爲 i + 1 的最長遞增子序列的最後一個元素。對於一個元素 x,
- 如果它大於 tails 數組所有的值,那麼把它添加到 tails 後面,表示最長遞增子序列長度加 1;
- 如果 tails[i-1] < x <= tails[i],那麼更新 tails[i] = x。
例如對於數組 [4,3,6,5],有:
tails len num
[] 0 4
[4] 1 3
[3] 1 6
[3,6] 2 5
[3,5] 2 nullCopy to clipboardErrorCopied
可以看出 tails 數組保持有序,因此在查找 Si 位於 tails 數組的位置時就可以使用二分查找。
public int lengthOfLIS(int[] nums) {
int n = nums.length;
int[] tails = new int[n];
int len = 0;
for (int num : nums) {
int index = binarySearch(tails, len, num);
tails[index] = num;
if (index == len) {
len++;
}
}
return len;
}
private int binarySearch(int[] tails, int len, int key) {
int l = 0, h = len;
while (l < h) {
int mid = l + (h - l) / 2;
if (tails[mid] == key) {
return mid;
} else if (tails[mid] > key) {
h = mid;
} else {
l = mid + 1;
}
}
return l;
}
第三題
編程題|30.0分3/4
舉重大賽
**時間限制:**C/C++語言 1000MS;其他語言 3000MS
**內存限制:**C/C++語言 131072KB;其他語言 655360KB
題目描述:
舉重大賽開始了,爲了保證公平,要求比賽的雙方體重較小值要大於等於較大值的90%,那麼對於這N個人最多能進行多少場比賽呢,任意兩人之間最多進行一場比賽。
輸入
第一行N,表示參賽人數(2<=N<=10^5)
第二行N個正整數表示體重(0<體重<=10^8)
輸出
一個數,表示最多能進行的比賽場數
樣例輸入
5
1 1 1 1 1
樣例輸出
10
AC 100 % 代碼,排序優化一下就可過掉:
import java.util.Arrays;
import java.util.Scanner;
/**
* @author HGS
* @date 2019/08/10
*/
public class Main {
public static boolean canPlay(int a, int b) {
if (a == b) {
return true;
}
if (a < b) {
return a * 10 >= b * 9;
} else {
return b * 10 >= a * 9;
}
}
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] nums = new int[n];
for (int i = 0; i < n; i++) {
nums[i] = sc.nextInt();
}
Arrays.sort(nums);
int cnt = 0;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (canPlay(nums[i], nums[j])) {
cnt++;
}else {
break;
}
}
}
System.out.println(cnt);
}
}
第四題
特殊的測試
**時間限制:**C/C++語言 1000MS;其他語言 3000MS
**內存限制:**C/C++語言 131072KB;其他語言 655360KB
題目描述:
小C在做一種特殊的服務器負載測試,對於一個請求隊列中的請求,每一個請求都有一個負荷值,爲了保證服務器穩定,請求隊列中的請求負荷必須按照先遞增後遞減的規律(僅遞增,僅遞減也可以),比如[ 1,2,8,4,3 ],[ 1,3,5 ]和[ 10 ]這些是滿足規律的,還有一些不滿足的,比如[ 1,2,2,1 ],[ 2,1,2 ]和[ 10,10 ]。現在給你一個請求隊列,你可以對請求的負荷值進行增加,要求你調整隊列中請求的負荷值,使數組滿足條件。最後輸出使隊列滿足條件最小的增加總和。
輸入
輸入有兩行,第一行是N (1≤n≤5000) ,代表請求隊列中的請求數量。
第二行有N個數字 a1,a2…an (1≤ai≤10^9)。Ai是第i個請求的負荷值。
輸出
輸出這個最小增加總和
樣例輸入
5
1 4 3 2 5
樣例輸出
6
AC 100% 代碼,暴力過掉,注意結果用long類型
import java.util.Arrays;
import java.util.Scanner;
/**
* @author HGS
* @date 2019/08/10
*/
public class Main {
public static void main(String args[]) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
int[] nums = new int[n];
int[] temp = new int[n];
for (int i = 0; i < n; i++) {
nums[i] = sc.nextInt();
}
long res = Long.MAX_VALUE;
long cnt;
for (int i = 0; i < n; i++) {
temp = Arrays.copyOf(nums, n);
// 以 nums[i] 爲峯值中心,前面遞增,後面遞減
cnt = 0;
for (int j = 1; j <= i; j++) {
if (temp[j - 1] >= temp[j]) {
int num = temp[j];
temp[j] = temp[j - 1] + 1;
cnt = cnt + temp[j] - num;
}
}
for (int j = n - 2; j >= i; j--) {
if (temp[j] <= temp[j + 1]) {
int num = temp[j];
temp[j] = temp[j + 1] + 1;
cnt = cnt + temp[j] - num;
}
}
if (cnt < res) {
res = cnt;
}
}
System.out.println(res);
}
}