小易有一個長度為n的整數序列,a_1,...,a_n。然后考慮在一個空序列b上進行n次以下操作:
1、將a_i放入b序列的末尾
2、逆置b序列
小易需要你計算輸出操作n次之后的b序列。輸入描述:
輸入包括兩行,第一行包括一個整數n(2 ≤ n ≤ 2*10^5),即序列的長度。
第二行包括n個整數a_i(1 ≤ a_i ≤ 10^9),即序列a中的每個整數,以空格分割。輸出描述:
在一行中輸出操作n次之后的b序列,以空格分割,行末無空格。輸入例子1:
4
1 2 3 4輸出例子1:
4 2 1 3
網易的筆試時間真是不夠,兩個小時,20道選擇,3道編程題,選擇題考的范圍極廣,我那套卷涉及到了C++,Java,數據結構,操作系統,計算機網絡,數據庫,Linux命令,Android,后端服務器,正則表達式等知識,我大概花了30多分鐘做選擇題,導致后面做編程題的時間連一個半小時都不到。
這道題是三道編程題中的第二道,解題時我犯了一個比較致命的錯誤:『讀懂題意后,就順著題目描述的過程開始敲代碼,而沒有仔細思考有沒有時間復雜度更低的解法』
按照題目的描述,整個數組的操作過程無非就是:每讀入一個整數,將其放到整數序列末尾,然后逆置整數序列。于是我按照這個過程寫出如下代碼:
public class OperateSequence {
public static void swap(int[] arr, int i, int j) {
int tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
/**
* 逆置數組
*
* @param arr
* @param n
*/
public static void reverseArr(int[] arr, int n) {
int c = n / 2;
int d = 1;
if (n % 2 == 0) {
while (c - d >= 0 && c + d - 1 < n) {
swap(arr, c - d, c + d - 1);
d++;
}
} else {
while (c - d >= 0 && c + d < n) {
swap(arr, c - d, c + d);
d++;
}
}
}
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) {
int n = in.nextInt();
int[] nums = new int[n];
for (int i = 0; i < n; i++) {
nums[i] = in.nextInt();
reverseArr(nums, i + 1);
}
for (int i = 0; i < n; i++) {
System.out.print(nums[i]);
if (i != n - 1) {
System.out.print(" ");
}
}
}
}
}
然后提交運行,結果如下圖
很明顯,上面這個O(n^2)的算法被卡了,感覺自己被套路了。。。
然后又重新在紙上列出n取不同值對應的結果,整數序列按升序輸入,便于分析,于是規律出來了:
1
2 1
3 1 2
4 2 1 3
5 3 1 2 4
6 4 2 1 3 5
換個姿勢看看,秒懂了吧
1
2 | 1
3 1 | 2
4 2 | 1 3
5 3 1 | 2 4
6 4 2 | 1 3 5
其最后輸出的序列分兩部分,前一半從最后一個數開始以2為步長遞減;后一半根據整數個數的奇偶,分別從第二個或第一個數開始以2為步長遞增。找到了這個規律,O(n)的算法就很容易寫出來了:
public class OperateSequence {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
while (in.hasNextInt()) {
int n = in.nextInt();
int[] nums = new int[n];
for (int i = 0; i < n; i++) {
nums[i] = in.nextInt();
}
for (int i = n - 1; i >= 0; i -= 2) { // 前一半從最后一個數開始以2為步長遞減
System.out.print(nums[i] + " ");
}
for (int i = n % 2; i < n - 2; i += 2) { // 后一半根據整數個數的奇偶,分別從第二個或第一個數開始以2為步長遞增
System.out.print(nums[i] + " ");
}
System.out.print(nums[n - 2]); // 最后一個數
}
}
}
提交運行上述代碼,完美AC,本題OJ傳送門在此
但遺憾的是,在考試時間內,我雖然找到了規律,但代碼沒寫完。至于第三題,我連看的時間都沒有。最后,三道編程題只AC1.5道。。。
平時自己刷題時都習慣先暴力求解,再去思考最優解,但是在真實的考試中,時間是不允許的,出題人還會刻意的去卡你的時間復雜度,吸取這次慘痛教訓吧。