LeetCode专题

前言

前段时间因为考试等懈怠了,重新开始做题。决定专门开一篇博客迭代记录了,不然文章散乱。

  1. 339.除法求值
    这题是并查集专题,暂时不会用并查集,使用了广度搜索。明天再看看并查集的方法。
    首先讲字符串先映射成数字,在构建图。图的节点为变量,边的权值为两连接变量的比值。
    对于queries的查询,从起点出发,广搜得到结果。
    源码
class Solution {
    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
        int nvars = 0;
        Map<String,Integer> variables = new HashMap<>();//讲字符串映射成数字

        //遍历映射
        int n = equations.size();
        for (int i=0;i<n;i++){
            if(!variables.containsKey(equations.get(i).get(0))){
                variables.put(equations.get(i).get(0),nvars++);
            }
            if(!variables.containsKey(equations.get(i).get(1))){
                variables.put(equations.get(i).get(1),nvars++);
            }

        }
        List<Pair>[]edges=new List[nvars];
        for(int i = 0; i<nvars; i++){
            edges[i] = new ArrayList<Pair>();
        }
        for(int i = 0;i<n;i++){
            int va = variables.get(equations.get(i).get(0));
            int vb = variables.get(equations.get(i).get(1));
            edges[va].add(new Pair(vb,values[i]));
            edges[vb].add(new Pair(va,1.0/values[i]));
        }
        int queriesConnt = queries.size();
        double[]ret =  new double[queriesConnt];
        for (int i=0;i<queriesConnt;i++){
            List<String> query = queries.get(i);
            double result = -1.0;
            if(variables.containsKey(query.get(0)) && variables.containsKey(query.get(1))){
                int ia = variables.get(query.get(0));
                int ib = variables.get(query.get(1));
                if(ia==ib){
                    result= 1.0;
                }else{
                    Queue<Integer>points = new LinkedList<Integer>();
                    points.offer(ia);
                    double[]ratios = new double[nvars];
                    Arrays.fill(ratios,-1.0);
                    ratios[ia]=1.0;
                    
                    while(!points.isEmpty()&& ratios[ib]<0){
                        int x= points.poll();
                        for(Pair pair :edges[x]){
                            int y =pair.index;
                            double val = pair.value;
                            if(ratios[y]<0){
                                ratios[y] =ratios[x]*val;
                                points.offer(y);
                            }
                        }
                    }
                    result=ratios[ib];
                }
            }
            ret[i]=result;
        }
        return ret;

    }
}
class Pair{
    int index;
    double value;
    Pair(int index,double value){
        this.index=index;
        this.value=value;
    }
}

2.200.岛屿数量
懒人终于来更新了。今天题目用深搜和广搜做,其实还可以用并查集(太晚了,下次研究),将网格堪称图,竖直/水平的1相连,扫描,为1时,进行深搜,标记为0。深搜次数为岛屿数量。深搜广搜意义差不多。

class Solution {
    // void dfs(char[][]grid,int nv,int nh){
    //     int v = grid.length;
    //     int h = grid[0].length;
    //     if(nv < 0 || nh < 0 || nv >= v || nh >= h || grid[nv][nh] == '0'){
    //         return;
    //     }
    //     grid[nv][nh] = '0';
    //     dfs(grid,nv-1,nh);
    //     dfs(grid,nv+1,nh);
    //     dfs(grid,nv,nh-1);
    //     dfs(grid,nv,nh+1);
    // }
    public int numIslands(char[][] grid) {
        // int v = grid.length;
        // int h = grid[0].length;
        // int ans = 0;
        // for (int nv =0 ;nv <v;++nv){
        //     for(int nh = 0;nh<h;++nh){
        //         if(grid[nv][nh]=='1'){
        //             ans++;
        //             dfs(grid,nv,nh);
        //         }
        //     }
        // }
        // return ans;

        // bfs
        if(grid==null || grid.length ==0){
            return 0;
        }
        int r,c,ans=0;
        int x = grid.length,y=grid[0].length;
        
        for(int i = 0;i<x;++i){
            for(int j=0;j<y;++j){
                if(grid[i][j]=='1'){
                    ++ans;
                    grid[i][j]='0';
                    Queue<Integer> queue =new LinkedList();
                    queue.add(i * y + j);
                    while(!queue.isEmpty()){
                        int index = queue.remove();
                        r = index / y;
                        c = index % y;
                      
                        if(r-1>=0 && grid[r-1][c]=='1'){
                            queue.add((r-1)*y+c);
                            grid[r-1][c]='0';

                        }
                        if(c-1>=0 && grid[r][c-1]=='1'){
                            queue.add(r*y+c-1);
                            grid[r][c-1]='0';

                        }
                        if(r+1<x && grid[r+1][c]=='1'){
                            queue.add((r+1)*y+c);
                            grid[r+1][c]='0';

                        }
                        if(c+1<y && grid[r][c+1]=='1'){
                            queue.add(r*y+c+1);
                            grid[r][c+1]='0';

                        }
                        
                    }

                }
            }
        }
        return ans;
    }
}

dfs的结果比较快。。。在这里插入图片描述
增加并查集部分,考虑到本体情况,无需对划分几个部分做记录,访问到0时无需置为0,并查集已经记录。只要对往右往下进行连通计算

class Solution {
  // 并查集-学习下并查集
   
    class UnionFind {
        private int[] parent;
        private int count;
        public UnionFind(char[][]grid){
            int m =grid.length;
            int n = grid[0].length;
            count = 0;
            parent = new int[m * n];
            for(int i=0;i<m;i++){
                for(int j =0;j<n;j++){
                    if(grid[i][j]=='1'){
                        parent[i * n + j] = i * n + j;
                        count++;
                    }
                }
            }
        }

        public int find(int x){
            if (parent[x]!=x){
                parent[x]=find(parent[x]);
            }
            return parent[x];
        }
        public void union(int x,int y){
            int rootx = find(x);
            int rooty = find(y);
            if(rootx != rooty){
                parent[rootx]=rooty;
                --count;
            }
        }
        public int getCount(){
            return count;
        }
        
    }
    public int numIslands(char[][] grid) {
        if(grid == null || grid.length==0){
            return 0;
        }
        int row=grid.length,col=grid[0].length;
        UnionFind uf =new UnionFind(grid);
        for(int i =0;i<row;++i){
            for(int j=0;j<col;++j){
                if(grid[i][j]=='1'){
                    // grid[i][j]='0';无需置为0,联通信息已有
                    int old = i *col +j;
                    if(i+1<row && grid[i+1][j]=='1'){
                        uf.union(old,(i+1)*col+j);
                    }
                    if(j+1<col && grid[i][j+1]=='1'){
                        uf.union(old,i*col+j+1);
                    }
                }
            }
        }
      return uf.getCount();

       
    }
}

竟然还是dfs最快
在这里插入图片描述
3.130. 被围绕的区域
今天题目和上一题太像了,从题目可以知道,我们只要找到边界的O,再通过深搜或者广搜,将与之相连的标记,最后在遍历一遍地图,将标记的改回O,其余改为X就可以得到答案

class Solution {
    int r,c;
    int []dx={1,-1,0,0};
    int []dy={0,0,1,-1};
    public void solve(char[][] board) {
         r = board.length;
         c = board[0].length;
         if(r ==0){
             return;
         }
         Queue<int[]>queue =new LinkedList<>();
         for(int i=0;i<r;i++){
             if(board[i][0]=='O'){
                 queue.add(new int[]{i,0});
             }
             if(board[i][c-1]=='O'){
                 queue.add(new int[]{i,c-1});
             }
         }
          for(int i=1;i<c-1;i++){
             if(board[0][i]=='O'){
                 queue.add(new int[]{0,i});
             }
             if(board[r-1][i]=='O'){
                 queue.add(new int[]{r-1,i});
             }
         }
         while(!queue.isEmpty()){
             int[] tmp =queue.poll();
             int x=tmp[0],y=tmp[1];
             board[x][y]='a';
             for(int i=0;i<4;i++){
                 int mx =x+dx[i],my=y+dy[i];
                 if(mx<0 ||mx>=r||my<0||my>=c||board[mx][my]!='O'){
                     continue;
                 }
                 queue.add(new int[]{mx,my});
             }
         }
        //  for(int i =0;i<r;i++){
        //     //  遍历上下列
        //     dfs(board,i,0);
        //     dfs(board,i,c-1);
        
        //  }
        //  for(int i =0;i<c;i++){
        //     //  遍历上下行
        //     dfs(board,0,i);
        //     dfs(board,r-1,i);
        //  }
         for(int i=0;i<r;i++){
             for(int j=0;j<c;j++){
                 if(board[i][j]=='a'){
                     board[i][j]='O';
                 }else if(board[i][j]=='O') {
                     board[i][j]='X';
                 }
             }
         }
        

    }
    // public void dfs(char[][]board,int x,int y){
    //     if(x<0 || x >= r || y<0 || y >=c || board[x][y] !='O'){
    //         return;
    //     }
    //     board[x][y]='a';
    //     dfs(board,x-1,y);
    //     dfs(board,x,y-1);
    //     dfs(board,x+1,y);
    //     dfs(board,x,y+1);
    // }
}

在这里插入图片描述
4. 1472. 设计浏览器历史记录
今日一个栈,算简单题

class BrowserHistory {
    private int pos =-1,top=-1;
    private List<String>his;
    public BrowserHistory(String homepage) {
        his =new ArrayList<>();
        visit(homepage);

    }
    
    public void visit(String url) {
        pos++;
        if(his.size()<=pos){
            his.add(url);
        }else{
            his.set(pos,url);
        }
        top = pos;
    }
    
    public String back(int steps) {
        if(steps>pos){
            steps = pos;
        }
        pos -= steps;
        return his.get(pos);

    }
    
    public String forward(int steps) {
        
        steps = Math.min(steps,top-pos);
        pos+=steps;
        return his.get(pos);

    }
}

/**
 * Your BrowserHistory object will be instantiated and called as such:
 * BrowserHistory obj = new BrowserHistory(homepage);
 * obj.visit(url);
 * String param_2 = obj.back(steps);
 * String param_3 = obj.forward(steps);
 */

在这里插入图片描述
5. 1600. 皇位继承顺序
和昨天一样设计题,费脑子

class ThroneInheritance {
    Map<String,ArrayList<String>> map =new HashMap<>();
    Set<String> set_dead = new HashSet<>();
    String kingName;

    public ThroneInheritance(String kingName) {
        this.kingName = kingName;
        map.put(kingName,new ArrayList<>());

    }
    
    public void birth(String parentName, String childName) {
        if(map.containsKey(parentName)){
            map.get(parentName).add(childName);
        }else{
            ArrayList tmp = new ArrayList<>();
            tmp.add(childName);
            map.put(parentName,tmp);
        }

    }
    
    public void death(String name) {
        set_dead.add(name);

    }
    
    public List<String> getInheritanceOrder() {
        ArrayList<String> ans = new ArrayList<>();
        if(!set_dead.contains(kingName)){
            ans.add(kingName);
        }
        dfs(kingName,ans);
        return ans;


    }

    private void dfs(String name,ArrayList<String> res){
        if(!map.containsKey(name)){
            return;
        }
        ArrayList<String> childs =map.get(name);
        for(String c :childs){
            if(!set_dead.contains(c)){
                res.add(c);
            }
            dfs(c,res);
        }
    }
}

/**
 * Your ThroneInheritance object will be instantiated and called as such:
 * ThroneInheritance obj = new ThroneInheritance(kingName);
 * obj.birth(parentName,childName);
 * obj.death(name);
 * List<String> param_3 = obj.getInheritanceOrder();
 */

在这里插入图片描述
6. 1603. 设计停车系统
今日eas题目,明天不做设计题了

class ParkingSystem {
    private int[] content = new int[3];

    public ParkingSystem(int big, int medium, int small) {
        content[0]=big;
        content[1]=medium;
        content[2]=small;

    }
    
    public boolean addCar(int carType) {
       if(content[carType-1]>0){
           content[carType-1]--;
           return true;
       }
       return false;

        

    }
}

/**
 * Your ParkingSystem object will be instantiated and called as such:
 * ParkingSystem obj = new ParkingSystem(big, medium, small);
 * boolean param_1 = obj.addCar(carType);
 */

在这里插入图片描述
7.207. 课程表
今日拓扑排序题,使用深搜和广搜,新的专题,还挺难。

class Solution {
    List<List<Integer>> edges;
    int []visited;//0为未访问,1为正在访问,2为完成
    boolean valid= true;
    int[]indeg;//入度
    public boolean canFinish(int numCourses, int[][] prerequisites) {

        edges = new ArrayList<List<Integer>>();
        for (int i =0;i<numCourses;++i){
            edges.add(new ArrayList<Integer>());
        }
        indeg = new int[numCourses];
        for (int[]info:prerequisites){
            edges.get(info[1]).add(info[0]);
            ++indeg[info[0]];
        }
        Queue<Integer> queue =new LinkedList<Integer>();
        for(int i=0;i<numCourses;++i){
            if(indeg[i]==0){
                queue.offer(i);
            }
        }
        int visit = 0;
        while(!queue.isEmpty()){
            ++visit;
            int u = queue.poll();
            for(int v:edges.get(u)){
                --indeg[v];
                if(indeg[v]==0){
                    queue.offer(v);
                }
            }
        }
        return visit==numCourses;
        // edges = new ArrayList<List<Integer>>();
        // for (int i =0;i<numCourses;++i){
        //     edges.add(new ArrayList<Integer>());
        // }
        // visited = new int[numCourses];
        // for (int[]info:prerequisites){
        //     edges.get(info[1]).add(info[0]);
        // }
        // for(int i=0;i<numCourses && valid;++i){
        //     if(visited[i]==0){
        //         dfs(i);
        //     }
        // }
        // return valid;
    }
    // public void dfs(int i){
    //     visited[i] = 1;
    //     for(int v:edges.get(i)){
    //         if(visited[v]==0){
    //             dfs(v);
    //             if(!valid){
    //                 return;
    //             }
    //         }else if(visited[v]==1){
    //             valid =false;
    //             return;
    //         }
    //     }
    //     visited[i]=2;
    // }
}

在这里插入图片描述
8. 720. 词典中最长的单词

class Solution {
    public String longestWord(String[] words) {
        // String ans ="";
        // Set<String> set = new HashSet<>();
        // for(String word:words){
        //     set.add(word);
        // }
        // for(String word:words){
        //     if(word.length()>ans.length() || word.length()==ans.length()&& word.compareTo(ans)<0){
        //         boolean flag =true;
        //         for(int i=1;i<word.length();++i){
        //             if(!set.contains(word.substring(0,i))){
        //                 flag=false;
        //                 break;
        //             }
        //         }
        //         if(flag)ans=word;
        //     }
        // }
        // return ans;
        if(words==null || words.length==0) return "";
        Arrays.sort(words);
        String curr="",prev=" ";//注意次数pre有个空字符,用于curr.charAt(0)==prev.charAt(0)
        int index=0;
        for (int i=0;i<words.length;++i){
            curr=words[i];
            if((curr.startsWith(prev) && curr.length()==prev.length()+1)){
                if(curr.length()>words[index].length()){
                    index=i;
                }
                 prev =curr;
            }else{
               if(curr.length()==1) prev = curr;
                else if(curr.charAt(0)==prev.charAt(0) && prev.length()>=curr.length() && curr.substring(0,curr.length()-1).equals(prev.substring(0,curr.length()-1))) prev = curr;
                else prev = prev;


            }
           

        }
        return words[index];




    }
}

在这里插入图片描述
9. 设计循环队列
使用单链表,其实数组就行,数组注意使用mod操作就好

class Node{
    public int value;
    public Node next;
    public Node(int value){
        this.value=value;
        this.next=null;
    }
}
class MyCircularQueue {
    private Node head,tail;
    private int capacity;
    private int count;

    public MyCircularQueue(int k) {
        this.capacity=k;

    }
    
    public boolean enQueue(int value) {
        if(this.count==this.capacity){
            return false;
        }
        Node node = new Node(value);
        if(this.count==0){
            head=tail=node;
        }else{
            tail.next=node;
            tail = node;
        }
        this.count++;
        return true;

    }
    
    public boolean deQueue() {
        if(this.count==0){
            return false;
        }
        this.head =this.head.next;
        this.count--;
        return true;
    }
    
    public int Front() {
        if(this.count==0){
            return -1;
        }else{
            return this.head.value;
        }

    }
    
    public int Rear() {
        if(this.count==0){
            return -1;
        }else{
            return this.tail.value;
        }

    }
    
    public boolean isEmpty() {
        return this.count==0;

    }
    
    public boolean isFull() {
        return this.count==this.capacity;

    }
}

/**
 * Your MyCircularQueue object will be instantiated and called as such:
 * MyCircularQueue obj = new MyCircularQueue(k);
 * boolean param_1 = obj.enQueue(value);
 * boolean param_2 = obj.deQueue();
 * int param_3 = obj.Front();
 * int param_4 = obj.Rear();
 * boolean param_5 = obj.isEmpty();
 * boolean param_6 = obj.isFull();
 */

在这里插入图片描述
10. l螺旋矩阵
通过模拟螺旋

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        List<Integer> ans = new ArrayList<>();
        int rows=matrix.length,cols=matrix[0].length;
        if(matrix==null || rows==0||cols==0){
            return ans;
        }
        boolean [][]visited =new boolean[rows][cols];
        int row=0,col=0;
        int[][] directions = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}};
        int index=0;
        for(int i=0;i<rows*cols;++i){
            ans.add(matrix[row][col]);
            visited[row][col]=true;
            int newRow =row+directions[index][0];
            int newCol = col+directions[index][1];
            if(newRow<0 || newRow>=rows ||newCol<0 ||newCol>=cols || visited[newRow][newCol]){
                index = (index+1)%4;
            }
         
            row += directions[index][0];
            col += directions[index][1];
        } 
        return ans;


    }
}

在这里插入图片描述
11.62. 不同路径

class Solution {
    public int uniquePaths(int m, int n) {
        //排列组合
        // int tmp =0;
        // if(m>n){
        //     tmp=m;
        //     m=n;
        //     n=tmp;
        // }
        // long ans=1;
        // for(int x =n, y=1;y<m;x++,y++){
        //     ans = ans*x/y;
        // }
        // return (int)ans;
        
       //动态规划1
        // int dp[][]=new int[m][n];
        // for(int i =0;i<m;i++){
        //     dp[i][0]=1;
        // }
        // for(int j=0;j<n;j++){
        //     dp[0][j]=1;
        // }
        // for(int i =1;i<m;i++){
        //     for(int j=1;j<n;j++){
        //         dp[i][j]=dp[i-1][j]+dp[i][j-1];
        //     }
        // }
        // return dp[m-1][n-1];
        
        // 动规3

        int dp[]=new int [m];
        for (int i=0;i<n;i++){
             dp[0]=1;
            for(int j = 1;j<m;j++){
                    dp[j]=dp[j-1]+dp[j];

                
            }
        }
        return dp[m-1];

    }
}

在这里插入图片描述
12.57. 插入区间
模拟过程,三种情况,两种直接插入,一种需要合并,为了避免数组移动,使用List

class Solution {
    public int[][] insert(int[][] intervals, int[] newInterval) {
        if(intervals.length==0){
            return new int[][]{newInterval};
        }
        // int m =intervals.length,n=intervals[0].length;
        List<int[]> ansList = new ArrayList<>();
        int left = newInterval[0],right = newInterval[1];
        boolean flag =false;
        for (int[]interval:intervals){
            if(right<interval[0]){
                if(!flag){
                    ansList.add(new int[]{left,right});
                    flag=true;
                }
                ansList.add(interval);
            }else if(left>interval[1]){
                ansList.add(interval);
            }else{
                left = Math.min(left,interval[0]);
                right = Math.max(right,interval[1]);
            }
        }
        if(!flag){
            ansList.add(new int[]{left,right});
        }
        int [][]ans = new int[ansList.size()][2];
        for(int i=0;i<ansList.size();++i){
            ans[i]=ansList.get(i);
        }
        return ans;

    }
}

在这里插入图片描述
13.59. 螺旋矩阵 II
和螺旋矩阵一个方法,模拟过程

class Solution {
    public int[][] generateMatrix(int n) {
        int num = n * n;
        int [][]ans =new int [n][n];
        int [][]directions ={{0,1},{1,0},{0,-1},{-1,0}};
        int index=0;
        int cur =1;
        int row =0,col=0;
        while(cur<=num){
            ans[row][col]=cur;

            cur++;
            int newRow = row+directions[index][0], newcol =col+directions[index][1];
            if(newRow<0||newRow>=n||newcol<0||newcol>=n||ans[newRow][newcol]!=0){
                index = (index+1)%4;
            }
            row = row+directions[index][0];
            col = col+directions[index][1];

        }
        return ans;
    }
   

}

在这里插入图片描述
14.79. 单词搜索
dfs+回溯
剪枝效果明显

class Solution {
    public boolean exist(char[][] board, String word) {
        int m =board.length,n=board[0].length;
        //剪枝效果明显
        int []cnt1=new int[255];
        int []cnt2=new int[255];
        for(int i =0;i<word.length();i++){
            cnt1[word.charAt(i)]++;
        } 
        for(char[] tmp :board){
            for(char s:tmp){
                cnt2[s]++;
            }
        }
        for(int i =0;i<cnt1.length;i++){
            if(cnt1[i]>cnt2[i]){
                return false;
            }
        }
        for(int i=0;i<m;++i){
            for(int j=0;j<n;++j){
                if(board[i][j]==word.charAt(0)){
                    if(dfs(board,i,j,0,word)) return true;
                }
            }
        }
        return false;

    }
   
    boolean dfs(char[][]board,int i,int j,int k,String s){
        if(k==s.length()){
            return true;
        }
       
        if(i<0 || i>=board.length|| j<0||j>=board[0].length){
            return false;
        }
        if(board[i][j]!=s.charAt(k)){
            return false;
        }
        
        char tmp = board[i][j];
        board[i][j]='0';
        boolean flag = dfs(board,i,j+1,k+1,s) || dfs(board,i+1,j,k+1,s) || dfs(board,i-1,j,k+1,s) || dfs(board,i,j-1,k+1,s);
        board[i][j]=tmp;//回溯
        return flag;
     
    }
}

在这里插入图片描述
15.69. x 的平方根
使用二分法或者牛顿法(使用零点逼近)

class Solution {
    public int mySqrt(int x) {
        //二分法
        // int start =0,end=x,ans=-1;
        // while(start <= end){
        //     int mid = start+(end-start)/2;
        //     if((long)mid*mid <= x){
        //         ans =mid;
        //         start = mid+1;
        //     }else{
        //         end= mid-1;
        //     }
        // }
        // return ans;

        //牛顿法

        if(x==0){
            return 0;
        }

        double C=x ,x0=C;
        while(true){
            double xi =0.5 * (x0+C/x0);
            if(Math.abs(xi-x0)<1e-7){
                break;
            }
            x0=xi;
        }
        return (int)(x0);
    }
}

在这里插入图片描述
16 82. 删除排序链表中的重复元素 II
其实昨天做了去除重复元素1,由于是升序链表所以就听简单的。本题要注意头指针可能被去除,所以增加一个指向头指针的节点。

/**
 * Definition for singly-linked list.
 * public class ListNode {
 *     int val;
 *     ListNode next;
 *     ListNode() {}
 *     ListNode(int val) { this.val = val; }
 *     ListNode(int val, ListNode next) { this.val = val; this.next = next; }
 * }
 */
class Solution {
    public ListNode deleteDuplicates(ListNode head) {
        if(head==null){
            return head;
        } 
        ListNode dummy = new ListNode();
        dummy.next=head;
        ListNode cur = dummy;
        while(cur.next!=null && cur.next.next!=null){
            if(cur.next.val==cur.next.next.val){
                int x = cur.next.val;
                while(cur.next!=null && cur.next.val==x){
                    ListNode tmp = cur.next;
                    cur.next=tmp.next;
                    tmp=null;
                }
            }else{
                cur= cur.next;
            }
        }
        return dummy.next;

    }
}

在这里插入图片描述
这么下去博客太长了,还是直接放表格链接。

题目解题链接说明
题目-82. 删除排序链表中的重复元素 II题解-82. 删除排序链表中的重复元素 II注意头节点可能删除
61. 旋转链表源码(自己写的有点蠢,绕半天,应该直接接上头才好)
173. 二叉搜索树迭代器题解(中序遍历)
190. 颠倒二进制位题解颠倒就是数字的循环颠倒,灵活采用与运算符和移位操作
74. 搜索二维矩阵题解升序。然后二分,看了提交发现自己好蠢,不用新开辟一个数组,直接用matrix[mid/n][mid%n]取值更节省空间。这个BST解法太秀了
78. 子集,90. 子集 II子集子集2两题相似,使用回溯做,这个明天开始做专题,感觉不是很会,在子集2中注意连续重复时,就排除当个子集,回溯得记住要回。。。
88. 合并两个有序数组题解应该是个简单题,第一种方法用两个头指针和一个额外完成。第二种方法用两个尾指针完成。(好菜
7. 整数反转题解判断是否溢出
141. 环形链表题解判断有环,一种使用hashset直接判断有没有访问,另外一种采用龟兔赛跑,如果有环兔子会追上龟
1252. 奇数值单元格的数目题解最简单的方式是二维数组模拟遍历,第二种方法两个数组统计1的个数
1309. 解码字母到整数映射题解欸,暴力遍历,char转string竟然还错了半天
153. 寻找旋转排序数组中的最小值题解今天题目就很奇怪,怎么感觉是简单题,二分或者直接遍历就好(遇到转折就返回)
179. 最大数题解重写比较器,直接转换为字符串之间比大小。
208. 实现 Trie (前缀树)题解21.4.12。使用一个26长度数组和字母一一对应即可
198. 打家劫舍,213. 打家劫舍 II劫舍1劫舍221.4.15,两题思路相同,动态规划,取dp[i-2]+nums[i]和dp[i-1]大者,劫舍2种情况,一个是0-n-1,另一种是1-n
661. 图片平滑器题解暴力法,遍历了每个元素的周边八个元素
217. 存在重复元素题解排序或者用hashmap,其实用set最好
220. 存在重复元素 III题解暴力超时,要用滑动窗口
26. 删除有序数组中的重复项题解 4.17 双指针,已排序数组,所以元素相同就是连续的,所以用双指针记录,慢指针获得非重复数字
1323. 6 和 9 组成的最大数字题解4.19就很蠢,转成字符串,高位碰到6就转9,然后跳出
1822. 数组元素积的符号题解4.19判断负数个数
27. 移除元素题解4.19双指针
28. 实现 strStr()题解4.20暴力,使用charAt和substring还是有区别
91. 解码方法题解4.20动规,关键还是找到转移方程,明天开始做动规
303. 区域和检索 - 数组不可变题解用一个数组处理前缀和,申请n+1的数组。便于求解,不用考虑0
1025. 除数博弈题解我i感觉简单题的动规也好难-
剑指 Offer 42. 连续子数组的最大和题解4.23继续动规
面试题 17.16. 按摩师题解4.23明天继续动规
392. 判断子序列题解4.24明天继续动规,这题easy肯定是因为暴力能做!动规的递推还是难找==
面试题 08.01. 三步问题题解4.26简单dp,母函数不好求,不然更快
938. 二叉搜索树的范围和题解4.27简单dfs
338. 比特位计数题解用了最简单的方法,这个动规的逻辑使用了最高有效位还是很难可以想到
1734. 解码异或后的排列题解5.11这题还很考异或操作,首先是n个正整数排列,其次是n是奇数,还需要研究研究
877. 石子游戏题解5.12动规,转移方程dp[i][j]表示i到j之间两者的最大差值
131. 分割回文串题解5.13动规加回溯,可以在研究研究
12. 整数转罗马数字题解硬编码模拟,效率低
1442. 形成两个异或相等数组的三元组数目题解异或编码,注意公式计算
1738. 找出第 K 大的异或坐标值题解异或牛逼
692. 前K个高频单词题解hashmap+排序,发现自己java语法还是很不熟,知道思路写不出来
525. 连续数组题解6.3前缀和的思想
203. 移除链表元素题解6.5简单题,遍历链表
剑指 Offer 58 - II. 左旋转字符串题解6.9切片操作 ,简单题
1869. 哪种连续子字符串更长题解6.9用了四个变量分别记录长度和最长的,简单题
1863. 找出所有子集的异或总和再求和题解6.12本题竟然是简单题哈哈哈,暴力用dfs比较好理解,遍历 2 n 2^n 2n次方,使用二进制代表较为晦涩,最后数学方法难懂
278. 第一个错误的版本题解6.13二分,简答题
374. 猜数字大小题解6.14和昨天一样的题型,简单题
852. 山脉数组的峰顶索引题解6.15简单题,直接遍历简单,可用二分

复习

题目解题链接说明
877. 石子游戏题解6.16动规,没明白上次的写法竟然过了==

一个月没做题,感觉这个时间把控不对,从专题开始做

题目解题链接说明
96. 不同的二叉搜索树题解7.20动规,这题有点巧妙
95. 不同的二叉搜索树 II题解7.21和昨天那题方法完全不同,使用回溯
98.验证二叉搜索树题解7.22递归验证,可以用中序
99. 恢复二叉搜索树题解7.23中序遍历,存在逆序就记录交换
101. 对称二叉树题解7.26递归和迭代
102. 二叉树的层序遍历题解7.27BFS
104. 二叉树的最大深度题解7.28昨天问题的简化版本
103. 二叉树的锯齿形层序遍历题解7.29层序遍历,加一个层级判断,奇数逆序
108. 将有序数组转换为二叉搜索树题解7.30递归,找到中间值作为根
105. 从前序与中序遍历序列构造二叉树题解7.31前序中序构建树,注意两个遍历特点,递归完成
106. 从中序与后序遍历序列构造二叉树题解8.4和上一题一样
107. 二叉树的层序遍历 II题解8.6中序遍历BFS,逆序
109. 有序链表转换二叉搜索树题解8.11和108一个同类型
110. 平衡二叉树题解8.12简单题
113. 路径总和 II题解8.13树的遍历,采用bfs,利用两个队列分别存储节点和值,利用map回溯路径,可以使用dfs更简单
114. 二叉树展开为链表题解8.14最简单是采用前序遍历,细究可以思考左子树的最右节点是右子树的头节点
116. 填充每个节点的下一个右侧节点指针题解8.15第一种层序遍历,第二种用next,分同父节点,第二种不同父节点
129. 求根节点到叶节点数字之和题解8.16DFS
199. 二叉树的右视图题解8.17bfs,记录每层最后一个节点
222. 完全二叉树的节点个数题解8.18递归左右子树,直接加1,该方法可以继续优化
226. 翻转二叉树题解8.22翻转二叉树,递归,左右节点呼唤

数组专题

题目解题链接说明
11. 盛最多水的容器题解8.24使用双指针,向内逼近
35. 搜索插入位置题解8.29二分
31. 下一个排列题解8.31从后往前定位,找到前面比后面小的数字,交换并升序前面后面的序列
39. 组合总和题解9.3回溯,数组和target的题目还挺多的,做了忘=
40. 组合总和 II题解9.4昨天的小拓展,加了一个重复条件
15. 三数之和题解9.5三树之和,面试常见,先排序,双指针!
36. 有效的数独题解9.6维护行、列、方格hashmap,注意方格的索引
33. 搜索旋转排序数组题解9.7使用二分
45. 跳跃游戏 II题解9.8贪心法,前向遍历,这种题型应该挺常见的
46. 全排列题解9.9回溯,本方法已经出现很多次,需加强理解
73. 矩阵置零题解9.10使用标记数组或者标记变量
77. 组合题解9.11组合,还是回溯!
47. 全排列 II题解9.12全排列回溯,经典题目
66. 加一题解9.13末尾往上加,循环判断,及时return
48. 旋转图像题解9.14旋转矩阵,观察规律
80. 删除有序数组中的重复项 II题解9.15快慢指针
81. 搜索旋转排序数组 II题解9.16二分,注意边界
118. 杨辉三角题解9.16就数学递推
134. 加油站题解9.17两层循环带走
119. 杨辉三角 II题解9.18可以用1的方法,也可以简化递推,用一维数组
189. 旋转数组题解9.20常规使用额外数组,O(1)首先反转全部,再翻转前k个,再反转后n-k个

字符串专题

题目解题链接说明
3. 无重复字符的最长子串题解9.22滑动窗口,这个一定要学会
5. 最长回文子串题解9.23经典题目,动规,拓展中心
6. Z 字形变换题解9.24按行寻找,按行索引
8. 字符串转换整数 (atoi)题解9.26符合日常场景题,模拟过程,首先跳过空格,使用sign标记正负,在判断是否溢出
13. 罗马数字转整数题解9.27简单题遍历,使用Map编码最初的字符
22. 括号生成题解9.28递归,回溯
38. 外观数列题解9.29递归,双指针计数
43. 字符串相乘题解9.30应用题,模拟乘法竖式过程
49. 字母异位词分组题解10.1巧用map
93. 复原 IP 地址题解10.3经典回溯,减枝
151. 翻转字符串里的单词题解10.8自带api方便,也可以用一个栈,或者自定义实现api
165. 比较版本号题解10.14其实不是很难,自己绕进去了
168. Excel表列名称题解10.15相当于26进制,做一个偏移
171. Excel 表列序号题解10.16昨天的逆向

动规专题

题目解题链接说明
241. 为运算表达式设计优先级题解10.18使用分治
300. 最长递增子序列题解10.20简单判断
5. 最长回文子串题解10.21算复习把,中心拓展,马拉车不想看==
22. 括号生成题解10.22回溯,复习了
55. 跳跃游戏题解10.24贪心法,每次更新最远能到的距离
53. 最大子序和题解10.24动规,维护pre= max(pre+num[i],num[i]
45. 跳跃游戏 II题解10.25贪心,动规,维护最远距离,当能达到最远距离时才更新步数
97. 交错字符串题解10.29动规,dp[i,j]=(dp[i-1,j]&&s1[i-1]==s3[i+j-1] )||(dp[i,i-1]&& s2[j-1]==s3[i+j-1])
213. 打家劫舍 II,212. 打家劫舍题解11.1打家劫舍经典动规
37. 打家劫舍 III题解11.2树形dp,用dp记录两种状态
322. 零钱兑换题解11.2两成遍历,dp[i]=min[dp[i],dp[i-coins[j]]+1
343. 整数拆分题解11.3dp[i]=max(curMax,Math.max(ji-j,jdp[i-j))
357. 计算各个位数不同的数字个数题解11.4此题可以逆向作,dp为重复值,两种情况,1、dp[i-1]为已经重复了,所以第i位可以0-9。2、dp[i-1]未重复,所以(9pow(10,i-2)-dp[i-1])(i-1),前面为不重复的总值*任意i-1数字
1218. 最长定差子序列题解11.5 dp[v]=dp[v−d]+1.v为数组元素数字,d为difference
72. 编辑距离题解11.22分为三种情况,dp[i][j]表示单词1的前i个字母和单词2的前j个字母的编辑距离

哈希表

题目解题链接说明
142. 环形链表 II题解11.27哈希表或者快慢指针
133. 克隆图题解11.27本质需要遍历图,深搜,使用一个map记录访问过了

排序

题目解题链接说明
229. 求众数 II题解12.1排序,统计次数,最简单是用哈希。

每日一题

题目解题链接说明
299. 猜数字游戏题解11.8每日一题,一层遍历,索引内容相同+1,用俩数组表示每个数字出现个数,取小的相加
2. 两数相加题解11.9每日一题,模拟链表相加过程
495. 提莫攻击题解11.10每日一题,一次遍历,直接比较duar和两者之差最小者
169. 多数元素题解11.11直接统计个数,或者排序取一半的都行
397. 整数替换题解11.19递归,进一步可以使用map,空间换时间
559. N 叉树的最大深度题解11.21递归,和二叉树一样
384. 打乱数组题解11.22random 随机取
859. 亲密字符串题解11.23 暴力解法,首先s和goal完全相同,需要有重复字母。否则,需要s[i]=goal[j] && s[j]=goal[i]
423. 从英文中重建数字题解11.24有点傻逼,根据英文单词可以知道zwuxg只会出现在02468中,h(8.3),f(6,7),o(4,5),o(0,1,2,4),i(5,6,8,9),通过map统计词频就可以算出
700. 二叉搜索树中的搜索题解11.25根据二叉搜索树特性,如果小于节点的值就往左子树走否则往右子树走
519. 随机翻转矩阵题解11.26使用map映射
400. 第 N 位数字题解11.30重要定位,边界很容易错,么,根据位数其个数为x * 9*10 ^x-1
1446. 连续字符题解12.1一遍遍历统计
18. 四数之和题解12.1四树之和,排序双指针,剪枝
1005. K 次取反后最大化的数组和题解12.3排序,将负数变为正数,k剩余为偶数,数值不变,为基数减去最小值
383. 赎金信题解12.4统计英文词频
21. 合并两个有序链表题解12.4比大小合并
911. 在线选举题解12.11先预处理得到每个时刻的top,再二分查找t,查表
630. 课程表 III题解12.14贪心,难=
851. 喧闹和富有题解12.15 构造图和dfs
1154. 一年中的第几天题解12.21硬编码每个月天数,闰年2月+1
1791. 找出星型图的中心节点添加链接描述12.23直接对比前两个点,,有个都出现的就是中心点
1705. 吃苹果的最大数目题解12.24贪心加最小堆(优先队列),先吃最快腐烂的
1609. 奇偶树题解12.25典型bfs,需要逐层遍历,以及奇偶判断
1078. Bigram 分词题解12.26直接分割遍历
825. 适龄的朋友题解12.27分析数学公式,排序,双指针找区间
1995. 统计特殊四元组题解12.29数据较小,可以直接枚举,或者使用map,存储nums[d]出现的个数,少一层循环;或者是存储nums[d]-nums[c]变为2重循环
1576. 替换所有的问号题解1.5使用3个字符循环
71. 简化路径题解1.6使用双端队列
1614. 括号的最大嵌套深度题解1.7统计连续左括号个数
89. 格雷编码题解1.8位运算不是很会
373. 查找和最小的 K 对数字题解1.14最小堆或者二分
1220. 统计元音字母序列的数目题解1.17动规,找到每个字母的前面可以是什么
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值