網易2018校招內推Android筆試編程題一道

題目:
輸入一個數組,長度不超過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個都是正確的。
校招還是更注重基礎知識

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章