題目:
輸入一個數組,長度不超過2*10^5,數組元素爲整數,大小不超過10^9,從第一個位置依次取元素並添加到新數組末尾,每取一次就逆序操作一次,直到取完所有元素。最後輸出這個逆序操作多次後的新數組。
示例:
原數組:1 2 3 4
取1,逆序後還是1
取2後數組爲1 2,逆序後是2 1
取3後數組爲2 1 3,逆序後是3 1 2
取4後數組爲3 1 2 4,逆序後是4 2 1 3
要求:
輸入第一行爲n,表示數組長度;第二行爲數組,以空格隔開。
輸出結果數組,以空格隔開,最後不能有空格。
思路:
平時還是做這種算法題太少,3道大題拿到題後就這個稍微有點思路。一開始被題目誤導,寫了個逆序函數去操作,每取一個數就調用一次函數,結果時間複雜度太高,TimeOut,無法AC。
所以一開始我的代碼是這樣的:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
while (scan.hasNext()) {
int n = scan.nextInt();
int a[] = new int[n];
for (int i = 0; i < n; i++) {
a[i] = scan.nextInt();
// 每讀入了新元素就逆序操作一次,這樣時間複雜度基本上就是O(n^2)
reverse(a, i + 1);
}
for (int i = 0; i < n; i++) {
if (i == n - 1) {
System.out.print(a[i]);
} else {
System.out.print(a[i] + " ");
}
}
}
}
private static void reverse(int a[], int len) {
if (len > 1) {
int temp;
for (int i = 0; i < len / 2; i++) {
temp = a[i];
a[i] = a[len - i - 1];
a[len - i - 1] = temp;
}
}
}
}
其實通過觀察幾個結果可以知道,這個根本不需要遍歷地去逆序操作,而是根據規律去添加元素:
1 2 3 4 → 4 2 1 3
1 2 3 4 5 → 5 3 1 2 4
1 2 3 4 5 6 → 6 4 2 1 3 5
從數組末尾開始,取兩個數,分別放在左右兩端,再取兩個數,放在內部的兩端,依次類推,所以中間那個數當長度爲奇數時永遠都是1,爲偶數時就是2,1。
生成過程:
1 2 3 4 5
5 _ _ _ 4
5 3 _ 2 4
5 3 1 2 4
AC代碼:
import java.util.Scanner;
public class Test {
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
while (scan.hasNext()) {
int n = scan.nextInt();
int a[] = new int[n];
for (int i = 0; i < n; i++) {
a[i] = scan.nextInt();
}
int b[] = reverseBest(a, n);
for (int i = 0; i < n; i++) {
if (i == n - 1) {
System.out.print(b[i]);
} else {
System.out.print(b[i] + " ");
}
}
}
}
// 時間複雜度降低爲O(n)
private static int[] reverseBest(int a[], int len) {
int b[] = new int[len]; // 搞一個空白數組來填
if (len > 1) {
for (int i = 0, j = 0; i < len / 2; i++) {
// 如i=0時左端元素就來自原數組倒數第一個
b[i] = a[len - 1 - j];
// 右端元素來自原數組的倒數第二個
b[len - 1 - i] = a[len - 2 - j];
j += 2; // 從後往前取,每次取兩個
}
if (len % 2 != 0) { // 最後如果是奇數列,要把中間的元素補1,因爲空數組默認元素都是0
b[len / 2] = 1;
}
return b;
} else {
return a; // len=1時,直接返回原數組,無需逆序操作
}
}
}
唉,總的來說還是學藝不精,算法編程題還是要多見多刷,纔會很快就有思路。
說來是Android的筆試題,其實真正的Android知識題目只有三四個選擇題(UI、SQL語句、內存泄露等),加上兩三個Java的題(主要是線程方面的知識,wait、notify、sleep之類的),其餘選擇題都是計算機的專業知識包括網絡、操作系統(Linux的一些命令操作),而且考察的形式基本上是“下列哪個說法是錯誤的”,也就是說有3個都是正確的。
校招還是更注重基礎知識。