Java笔试经验


低下头解决不了任何问题 –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不出。

猜你喜欢

转载自blog.csdn.net/qq_40910541/article/details/82757385