文章目录
- 面试经典150题【101-110】
- 9.回文数
- 61.加一
- 172.阶乘后的0
- 69.x的平方根
- 50.Pow(x,n)
- 149.直线上最多的点数
- 52.N皇后II
- 120.三角形最小路径和
- 64.最小路径和
- 63.不同路径II
 
面试经典150题【101-110】
6道偏数学的题和4道二维dp
9.回文数
一开始想转为字符串再判断。后来发现可以直接取后一半数字再判断。
class Solution {
    public boolean isPalindrome(int x) {
        //因为如果x后面出现0,后面算法会出错
        if(x<0 || x%10==0 && x!=0){
            return false;
        }
        int temp=0;
        while(temp<x){
            temp = temp*10 + x%10;
            x = x/10;
        }
        // x从1221 -> 12;  x: 12321 -> 12 <123
        return x==temp || x==temp/10;
    }
}
61.加一

class Solution {
    public int[] plusOne(int[] digits) {
        for(int i=digits.length-1;i>=0;i--){
            digits[i]++;
            digits[i] = digits[i]%10;
            if(digits[i] != 0) return digits;
        }
        //都加完了还不返回,说明是999这种
        int[] ans=new int[digits.length+1];
        ans[0]=1;
        return ans;
    }
}
直接加,最后遇到999这种则扩容。
172.阶乘后的0

 25 = 25 *。。。 *5。。。
 答案是3,看有几个5.其中25这个数字代表两个5
class Solution {
    public int trailingZeroes(int n) {
        int count=0;
        for(int i=0;i<n+1;i++){
            int temp=i;
            //最后temp会被干到0
            while(temp %5==0 && temp!=0){
                count++;
                temp =temp/5;
            }
        }
        return count;
    }
}
69.x的平方根
直接二分去搜,牛顿的数学太复杂。
50.Pow(x,n)
要将n进行二进制的拆分
 
class Solution {
    public double myPow(double x, int n) {
        if(x ==0.0f) return 0;
        long b=n;
        double res=1;
        if(b<0){
            x = 1/x;
            b = -b;
        }
        while(b>0){
            if((b&1)==1){
                res = res*x;
            }
            x =x*x;
            b = b>>1;
        }
        return res;
    }
}
149.直线上最多的点数

 三个点,ABC,AB和BC的斜率应该一样。
 暴力的话就是先确定两个点,再依次遍历其他的点,看斜率是否等于AB的斜率。
 用哈希表就是,先确定一个点(N),计算与其他所有点(N)的斜率,将斜率k存储到哈希表中。取哈希表中value的最大值即可。
public class LC149 {
    public static int maxPoints(int[][] points) {
        int ans=0;
        for(int i=0;i<points.length;i++){
            HashMap<String,Integer>map =new HashMap<>();
            int[] x=points[i];
            for(int j=i+1;j<points.length;j++){
                int[] y=points[j];
                int x1=x[0],x2=y[0],y1=x[1],y2=y[1];
                int deltax = x1-x2,deltay=y1-y2;
                int gcdxy=gcd(deltax,deltay);
                String key=deltax/gcdxy +"_"+deltay/gcdxy;
                map.put(key,map.getOrDefault(key,0)+1);
                //[1,1]-[2,2],  [1,1]-[3,3]   [2,2]-[3,3]   [7,9] - [9,11]
                int value = map.get(key);
                ans =  ans=Math.max(ans,value+1);
            }
        }
        return ans;
    }
    public static int gcd(int x,int y){
        return y==0? x:gcd(y,x%y);
    }
    public static void main(String[] args) {
        int[][]points= {{1,1},{2,2},{3,3}};
        System.out.println(maxPoints(points));
    }
}
一个要注意最小公约数gcd的写法。
 HashMap应该是针对于每一个 i 点的,则每一个 j 点都要统计。
52.N皇后II

 老解法,回溯。先在每一行下棋,然后下一行,然后回溯到这一行没下。去下这一行的下一列。
public class LC52 {
    private static int ans=0;
    public static int totalNQueens(int n) {
        char[][] board=new char[n][n];
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                board[i][j]='.';
            }
        }
        dfs(board,0);
        return ans;
    }
    public static void dfs(char[][] board,int row){
        if(row == board.length){
            ans++;
            return;
        }
        for(int j=0;j< board.length;j++){
            if(check(board,row,j)){
                board[row][j]='Q';
                dfs(board,row+1);
                board[row][j]='.';
            }
        }
    }
    public static boolean check(char[][]board,int row,int col){
        // 这一列
        for(int i=0;i< board.length;i++){
            if(board[i][col]=='Q') return false;
        }
        // 检查 135度角是否有皇后
        for (int i = row - 1, j = col - 1; i >=0 && j >= 0; i--, j--) {
            if (board[i][j] == 'Q') {
                return false;
            }
        }
        // 检查 45度角是否有皇后
        for(int i = row - 1, j = col + 1; i >= 0 && j < board.length; i--, j++) {
            if (board[i][j] == 'Q') {
                return false;
            }
        }
        return true;
    }
    public static void main(String[] args) {
        System.out.println(totalNQueens(4));
    }
}
120.三角形最小路径和

class Solution {
    public int minimumTotal(List<List<Integer>> triangle) {
        // 最后一行全是0
        int[][] dp = new int[triangle.size() + 1][triangle.size() + 1];
        for (int i = triangle.size() - 1; i >= 0; i--) {
            for (int j = 0; j <= i; j++) {
                dp[i][j] = Math.min(dp[i + 1][j], dp[i + 1][j + 1]) + triangle.get(i).get(j);
            }
        }
        return dp[0][0];
    }
}
这个是倒序的,从三角形的下边到上面。
 迭代公式:
 dp[i][j] = Math.min(dp[i + 1][j], dp[i + 1][j + 1]) + triangle.get(i).get(j);
64.最小路径和

class Solution {
    public int minPathSum(int[][] grid) {
        for (int i = 0; i < grid.length; i++) {
            for (int j = 0; j < grid[0].length; j++) {
                if (i == 0 && j == 0)
                    continue;
                else if (i == 0)
                    grid[i][j] = grid[i][j - 1] + grid[i][j];
                else if (j == 0)
                    grid[i][j] = grid[i - 1][j] + grid[i][j];
                else
                    grid[i][j] = Math.min(grid[i - 1][j], grid[i][j - 1]) + grid[i][j];
            }
        }
        return grid[grid.length - 1][grid[0].length - 1];
    }
}
这个是从上到下迭代的,迭代公式:
 grid[i][j] = Math.min(grid[i - 1][j], grid[i][j - 1]) + grid[i][j];
63.不同路径II

    public int uniquePathsWithObstacles(int[][] obstacleGrid) {
        int m=obstacleGrid.length;
        int n=obstacleGrid[0].length;
        if(obstacleGrid[0][0]==1) return 0;
        int[][] dp=new int[m][n];
        dp[0][0]=1;
        for(int i=0;i<m;i++){
            for(int j=0;j<n;j++){
                if(i==0 && j==0) continue;
                if(i>0 && j>0 && obstacleGrid[i][j]==0){
                    dp[i][j]=dp[i-1][j]+dp[i][j-1];
                }else if(i==0 && obstacleGrid[i][j]==0){
                    dp[i][j]=dp[i][j-1];
                }else if(j==0 && obstacleGrid[i][j]==0){
                    dp[i][j]=dp[i-1][j];
                }else{
                    //有障碍物
                    dp[i][j]=0;
                }
            }
        }
        return dp[m-1][n-1];
    }
递推公式: dp[i][j]=dp[i-1][j]+dp[i][j-1];
 应该先用俩for循环初始一下第一行和第一列。然后ij都从1开始循环也蛮好的。



















