LeetCode专题

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 
        //     for(int nh = 0;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的结果比较快。。。LeetCode专题_第1张图片
增加并查集部分,考虑到本体情况,无需对划分几个部分做记录,访问到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最快
LeetCode专题_第2张图片
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
        //     //  遍历上下列
        //     dfs(board,i,0);
        //     dfs(board,i,c-1);
        
        //  }
        //  for(int i =0;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);
    // }
}

LeetCode专题_第3张图片
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);
 */

LeetCode专题_第4张图片
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 param_3 = obj.getInheritanceOrder();
 */

LeetCode专题_第5张图片
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);
 */

LeetCode专题_第6张图片
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>();
        // for (int i =0;i
        //     edges.add(new ArrayList());
        // }
        // visited = new int[numCourses];
        // for (int[]info:prerequisites){
        //     edges.get(info[1]).add(info[0]);
        // }
        // for(int i=0;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;
    // }
}

LeetCode专题_第7张图片
8. 720. 词典中最长的单词

class Solution {
    public String longestWord(String[] words) {
        // String ans ="";
        // Set 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
        //             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];




    }
}

LeetCode专题_第8张图片
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();
 */

LeetCode专题_第9张图片
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;


    }
}

LeetCode专题_第10张图片
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
        //     ans = ans*x/y;
        // }
        // return (int)ans;
        
       //动态规划1
        // int dp[][]=new int[m][n];
        // for(int i =0;i
        //     dp[i][0]=1;
        // }
        // for(int j=0;j
        //     dp[0][j]=1;
        // }
        // for(int i =1;i
        //     for(int j=1;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];

    }
}

LeetCode专题_第11张图片
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;

    }
}

LeetCode专题_第12张图片
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;
    }
   

}

LeetCode专题_第13张图片
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;
     
    }
}

LeetCode专题_第14张图片
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);
    }
}

LeetCode专题_第15张图片
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;

    }
}

LeetCode专题_第16张图片
这么下去博客太长了,还是直接放表格链接。

题目 解题链接 说明
题目-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,劫舍2 21.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动规,找到每个字母的前面可以是什么

你可能感兴趣的:(LeetCode,leetcode,1024程序员节)