Java筆試經驗

布瑋發表於2018-09-18


低下頭解決不了任何問題 –RuiDer


本篇文章來自筆者刷題過程的一些經驗,總結自己容易犯錯的一些地方,以及還不會的知識點,以備後期複習使用。題目一般來自牛客,leetCode或者oj等等

總結

1. 二維陣列的初始化

int[][] array={{1,2},{3,4},{5,6}};

2. 二維陣列的長度問題

像下面一個3x2的二維陣列,執行array.length的結果為3,執行array[i].length(i可以等於0或者1)結果是2

1,2
3,4
5,6

3.for迴圈

下面程式碼:

int i;
for(i=0;i<5;i++){
	...code...
}
System.out.println(i);

//結果輸出為:5而不是4!!!

這點很重要,可以看看劍指offer中的順時針列印矩陣這道題,我剛開始做出現Exception:陣列越界問題,問題來源就是這個。參考程式碼:

import java.util.ArrayList;
public class Solution {
    public ArrayList<Integer> printMatrix(int [][] matrix) {
        ArrayList<Integer> list=new ArrayList<Integer>();
        fun(matrix,list);
        return list;
    }
    public void fun(int [][] matrix,ArrayList<Integer> list){
        if(matrix==null){
            return;
        }
        int xlen=matrix.length;
        int ylen=matrix[0].length;
        if(matrix.length==1){
            for(int i=0;i<matrix[0].length;i++){
                list.add(matrix[0][i]);
            }
            return;
        }
        if(matrix[0].length==1){
            for(int i=0;i<matrix.length;i++){
                list.add(matrix[i][0]);
            }
            return;
        }
        int i=0,j;
        for(j=0;j<matrix[i].length;j++){
            list.add(matrix[i][j]);
        }
        j=j-1;
        for(i=1;i<matrix.length;i++){
            list.add(matrix[i][j]);
        }
        i=i-1;
        for(j=j-1;j>=0;j--){
            list.add(matrix[i][j]);
        }
        j=j+1;
        for(i=i-1;i>0;i--){
            list.add(matrix[i][j]);
        }
        
        if(xlen-2<=0||ylen-2<=0){
            return;
        }
        xlen=xlen-2;
        ylen=ylen-2;
        int[][] newMatrix=new int[xlen][ylen];
        for(int x=0;x<xlen;x++){
            for(int y=0;y<ylen;y++){
                newMatrix[x][y]=matrix[x+1][y+1];
            }
        }
        fun(newMatrix,list);
    }
}

4.矩陣的逆時針旋轉

思路:比如有下面2x3的矩陣:

1,2,3
4,5,6

順時針旋轉之後:

3,6
2,5
1,4

發現了一個規律:原來矩陣的行資料在旋轉180度的資料在旋轉之後變成新矩陣的列資料,比如上邊的矩陣 行資料:1,2,3旋轉180度是:3,2,1逆時針旋轉後變為
列資料: 3 2 1
發現規律之後就簡單了,我的程式碼:、

import java.util.ArrayList;
public class Main {
    public static int [][] printMatrix(int [][] array) {
        if(array==null){
            return null;
        }
        int xlen=array.length;
        int ylen=array[0].length;
        int[][] newArray=new int[ylen][xlen];
        int nxlen=newArray.length;
        int nylen=newArray[0].length;
        for(int j=0;j<nylen;j++){
            for(int i=0;i<nxlen;i++){
                newArray[i][j]=array[j][ylen-1-i];
            }
        }
        return newArray;
    }
    public static void main(String[] args){
        int[][] array={{1,2},{3,4},{5,6},{7,8},{9,10}};
        array=printMatrix(array);
        for(int i=0;i<array.length;i++){
            for(int j=0;j<array[0].length;j++){
                System.out.println(array[i][j]);
            }
        }
    }
}

幾種遍歷方式的區別

每個遍歷方法的實現原理是什麼?

(1)、傳統的for迴圈遍歷,基於計數器的:
遍歷者自己在集合外部維護一個計數器,然後依次讀取每一個位置的元素,當讀取到最後一個元素後,停止。主要就是需要按元素的位置來讀取元素。
(2)、迭代器遍歷,Iterator:
每一個具體實現的資料集合,一般都需要提供相應的Iterator。相比於傳統for迴圈,Iterator取締了顯式的遍歷計數器。所以基於順序儲存集合的Iterator可以直接按位置訪問資料。而基於鏈式儲存集合的Iterator,正常的實現,都是需要儲存當前遍歷的位置。然後根據當前位置來向前或者向後移動指標。
(3)、foreach迴圈遍歷:
根據反編譯的位元組碼可以發現,foreach內部也是採用了Iterator的方式實現,只不過Java編譯器幫我們生成了這些程式碼。

各遍歷方式的適用於什麼場合?

(1)、傳統的for迴圈遍歷,基於計數器的:
順序儲存:讀取效能比較高。適用於遍歷順序儲存集合。
鏈式儲存:時間複雜度太大,不適用於遍歷鏈式儲存的集合。
(2)、迭代器遍歷,Iterator:
順序儲存:如果不是太在意時間,推薦選擇此方式,畢竟程式碼更加簡潔,也防止了Off-By-One的問題。
鏈式儲存:意義就重大了,平均時間複雜度降為O(n),還是挺誘人的,所以推薦此種遍歷方式。
(3)、foreach迴圈遍歷:
foreach只是讓程式碼更加簡潔了,但是他有一些缺點,就是遍歷過程中不能運算元據集合(刪除等),所以有些場合不使用。而且它本身就是基於Iterator實現的,但是由於型別轉換的問題,所以會比直接使用Iterator慢一點,但是還好,時間複雜度都是一樣的。所以怎麼選擇,參考上面兩種方式,做一個折中的選擇。

包含min函式的棧這個問題

劍指offer中包含min函式的棧,借鑑他人優秀的方法

class Solution {
public:
     
    stack<int> stack1,stack2;
     
    void push(int value) {
        stack1.push(value);
        if(stack2.empty())
            stack2.push(value);
        else if(value<=stack2.top())
        {
            stack2.push(value);
        }
    }
     
    void pop() {
        if(stack1.top()==stack2.top())
            stack2.pop();
        stack1.pop();
         
    }
     
    int top() {
        return stack1.top();       
    }
     
    int min() {
        return stack2.top();
    }
     
};

應用一個輔助棧,壓的時候,如果A棧的壓入比B棧壓入大,B棧不壓,,,,小於等於,AB棧同時壓入,出棧,如果,AB棧頂元素不等,A出,B不出。

相關文章