LeetCode水题之路-3月记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33248299/article/details/88643959

547.朋友圈

题解:典型的并查集模板题 初始化每个人都有一个朋友圈 所以初始化朋友圈为人数个数 当给出i和j是朋友时 分别先搜i和j最头上的人 不一样则让一方指向另一方 同时朋友圈数目减1

不废话了,直接上代码了

class Solution {
    int [] p = new int[201];
    int result;
    public int findCircleNum(int[][] M) {
          result = M.length;
          init(M.length);
          for(int i=0;i<M.length;i++){
              for(int j=0;j<M.length;j++){
                  if(M[i][j]==1){
                      unionset(i,j);
                  }
              }
          }
          return result;
    }

    private void unionset(int x, int y) {
        int xx = Find(x);
        int yy = Find(y);
        if(xx!=yy){
            p[yy]=xx;
            result--;
        }
    }

    private int Find(int x) {
        if(x!=p[x]){
            p[x]=Find(p[x]);//状态压缩
        }
        return p[x];
    }

    private void init(int length) {
        for(int i=0;i<length;i++){
            p[i]=i;
        }
    }
}

448.找到所有数组中消失的数字

题解:标记法 先循环遍历一遍把出现的数字进行标记 再循环遍历没有出现的数字添加到集合中

不废话了,直接上代码了

class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {
        List<Integer> list = new ArrayList<Integer>();
            boolean [] flags = new boolean[nums.length+1];
            for(int i=0;i<nums.length;i++){
                 flags[nums[i]]=true;
            }
             for(int i=1;i<=nums.length;i++){
                if(flags[i]==false){
                    list.add(i);
                }
            }
            return list;
    }
}

682.棒球比赛

题解:因为C是去掉分数 所以你不能简单的用几个变量来保存 所以要用到数组 因为是动态的 所以我就直接上集合了

  public int calPoints(String[] ops) {
           int finalscore=0;
           List<Integer> list = new ArrayList<Integer>();
           for(int i=0;i<ops.length;i++){

                 if(ops[i].charAt(0)=='C'){
                      int score = list.get(list.size()-1);
                      finalscore-=score;
                      list.remove(list.size()-1);

                 }
                else if(ops[i].charAt(0)=='D'){
                     int score = list.get(list.size()-1)*2;
                     list.add(score);
                     finalscore+=score;

                }
                else if(ops[i].charAt(0)=='+'){
                    int score = list.get(list.size()-1)+list.get(list.size()-2);
                    list.add(score);
                    finalscore+=score;

                }
                else{//第一次我还智障的写了下判断数字。。。后边看了那些排名前边的代码发现压根不需要
                     int score = Integer.valueOf(ops[i]);
                     finalscore+=score;
                     list.add(score);
                 }

           }
           return finalscore;
    }

557.反转字符串中的单词 III

题解:用空格分割,之后循环对每个单词进行反转

 class Solution {
    public String reverseWords(String s) {
         String [] strs = s.split(" ");
        StringBuilder sb = new StringBuilder();
        for(int i=0;i<strs.length;i++){
            sb.append(new StringBuilder(strs[i]).reverse().toString()+(i==strs.length-1?"":" "));
        }
        return sb.toString();
    }
}

942.增减字符串匹配

题解:因为I是增 D是减 范围是从0-length 所以增可以从0开始 减则从length开始 要从中知道并了解到分治的思想

class Solution {
    public int[] diStringMatch(String S) {
         int [] results = new int[S.length()+1];
        int min = 0;
        int max = S.length();
        for(int i=0;i<S.length();i++){
            if(S.charAt(i)=='I'){
                results[i]=min++;
            }else{
                results[i]=max--;
            }
        }
        results[S.length()]=max;//最后无论添加max还是min都是一样的 因为两个值相同了
        return results;
    }
}

852.山脉数组的峰顶索引

题解:注意题目 不要想太多了 直接找第一个该数大于后边的数 记录下其索引就OK了

class Solution {
    public int peakIndexInMountainArray(int[] A) {
      int result=-1;
        for(int i=1;i<A.length-1;i++){
            if(A[i]>A[i+1]){
                result = i;
                break;//注意要跳出
            }
        }
        return result;
    }
}

496.下一个更大元素I

题解:因为元素是唯一的 所以我们开个Map来记录num2中每个数字的位置 之后来个嵌套for就OK了

class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
           int [] results = new int[nums1.length];
             Map<Integer,Integer> position  = new HashMap<Integer, Integer>();
             for(int i=0;i<nums2.length;i++){
                 position.put(nums2[i],i);//因为元素是唯一的 所以开个Map来记录nums2每个数的位置
             }
             for(int i=0;i<nums1.length;i++){
                 int w = position.get(nums1[i]);
                 results[i]=-1;
                 for(int j=w;j<nums2.length;j++){
                     if(nums2[j]>nums1[i]){
                         results[i]=nums2[j];
                         break;
                     }
                 }
             }
             return results;
    }
}

884.两句话中的不常见单词

题解:其中一个句子出现一次 另一个句子没有出现可以理解为只出现了一次 所以我们用一个Map来记录次数

class Solution {
   Map<String,Integer> map = new HashMap<String, Integer>();
    Set<String> set = new HashSet<String>();

    public String[] uncommonFromSentences(String A, String B) {
        List<String> results = new ArrayList<String>();
        init(A,map);
        init(B,map);
        for(String str:set){
           if(map.containsKey(str)&&(map.get(str)==1)){
                 results.add(str);
           }
        }
        return results.toArray(new String[results.size()]);
    }

    private void init(String strs, Map<String, Integer> map) {
          for(String str:strs.split(" ")){
               set.add(str);
               if(map.get(str)==null){
                   map.put(str,1);
               }else{
                   int num = map.get(str);
                   map.put(str,++num);
               }
          }
    }
}

824.山羊拉丁文

题解:就是先用空格分开,之后判断首字符是否是元音 进行对应的操作

class Solution {  
    StringBuilder sb = new StringBuilder();
    public String toGoatLatin(String S) {
           String [] strs = S.split(" ");
           for(int i=0;i<strs.length;i++){
               if(isyuanyin(strs[i].charAt(0))){
                     add(strs[i],i+1);
               }else{
                   char a=strs[i].charAt(0);
                   String s = strs[i].substring(1);
                   add(new StringBuilder(s).append(a).toString(),i+1);
               }
                if(i!=strs.length-1){
                   sb.append(" ");
               }
           }
           return sb.toString();
    }

    public boolean isyuanyin(char a){
         if(a=='a'||a=='e'||a=='i'||a=='o'||a=='u'||a=='A'||a=='E'||a=='I'||a=='O'||a=='U'){
             return true;
         }
         return false;
    }

    public void add(String str,int length){
        sb.append(str);
         sb.append("ma");
         for(int i=0;i<length;i++){
             sb.append("a");
         }
    }
}

13.罗马数字转整数

题解:就一个Map来存储对应的数字 因为前面罗马数字小于后面罗马数字只有6种情况而且对应长度只可能是2 所以就简单了

class Solution {
     Map<String,Integer> map = new HashMap<String, Integer>();
    public int romanToInt(String s) {
          int result = 0;
          init();
          int i=0;
          for(i=0;i<s.length();i++){
               if((i<=s.length()-2)&&(map.get(String.valueOf(s.charAt(i)))<map.get(String.valueOf(s.charAt(i+1))))){
                   String key = Character.toString(s.charAt(i))+Character.toString(s.charAt(i+1));
                   System.out.println(key);
                   result+=map.get(key);
                   i++;
               }
               else{
                   result+=map.get(Character.toString(s.charAt(i)));
               }
          }
          return result;
    }

    private void init() {
        String [] keys={"I","V","X","L","C","D","M","IV","IX","XL","XC","CD","CM"};
        int [] values={1,5,10,50,100,500,1000,4,9,40,90,400,900};
        for(int i=0;i<keys.length;i++){
            map.put(keys[i],values[i]);
        }

    }
}

796.旋转字符串

题解:因为是串A经过N次旋转后能形成串B,所以我们不妨串A+串A,这样如果串B包含在这个新字符串中,那么意味着串B能够经过串A旋转形成 如果不包含则说明不行

class Solution { 
    public boolean rotateString(String A, String B) {
           if(A.length()==0&&B.length()==0){
                return true;
            }
            if(A.length()!=B.length()){
                return false;
            }
            if((A+A).contains(B)){
                return true;
            }else{
                return false;
            }
    }
}

896.单调数列

题解:这题运用到了数学中的知识,先作差然后在相乘判断符号来判断是否是单调数列

class Solution { 
    public boolean isMonotonic(int[] A) {
         if(A.length<=2) //长度小于等于2 肯定是单调数列
            return true;
        boolean result = true;
        int cha1 = A[1]-A[0];
        for(int i=2;i<A.length;i++){
            int cha2=A[i]-A[i-1];
            if(cha2==0){//差为0会影响判断 继续下一个
                continue;
            }
            if(cha1*cha2<0){
                result = false;
                break;
            }
               cha1=cha2;
        }
        return result;
    }
}

747.至少是其他数字两倍的最大数

题解:用一个for循环就可以了 找最大数 和 仅次于最大数的数 比较最大数是否是该数的两倍就行了

class Solution { 
    public int dominantIndex(int[] nums) {
        if(nums.length==1){
            return 0;
        }
        int max=-1;//最大的数
        int p=-1; //位置
        int secondmax = -1;
        for(int i=0;i<nums.length;i++){
               if(max<nums[i]){//最大数小于当前数
                   secondmax=max;
                   max=nums[i];
                   p=i;
               }
               else if(nums[i]>secondmax){当前数大于第二大的数
                   secondmax=nums[i];
               }
        }

        return max<secondmax*2?-1:p;
    }
}

200.岛屿的个数

题解:标准的dfs模板题 虽然可以用并查集做 不过有点不清楚咋用并查集解决这题 for循环遇到1就往它的四周搜索 遇到1就把它坐标变为2(意思就是走过了)

class Solution {
     int count;
    int []x={0,0,-1,1};
    int []y={1,-1,0,0};
    public int numIslands(char[][] grid) {
        if(grid.length==0){
            return 0;
        }
          count = 0;
          for(int i=0;i<grid.length;i++){
              for(int j=0;j<grid[i].length;j++){
                  if(grid[i][j]=='1'){
                      count++;
                      dfs(i,j,grid);
                  }
              }
          }
          return count;
    }

    private void dfs(int i, int j,char [][]grid) {
        for(int k=0;k<4;k++){
                int xx=i+x[k];
                int yy=j+y[k];
                if(xx<0||yy<0||xx>=grid.length||yy>=grid[0].length){
                    continue;
                }
                if(grid[xx][yy]=='1'){
                    grid[xx][yy]='2';
                    dfs(xx,yy,grid);
                }
            }
        }
}

695.岛屿的最大面积

题解:还是标准的dfs题 找结束条件 上下左右搜

class Solution {
     int max_length;
    int []xs={0,0,-1,1};
    int []ys={1,-1,0,0};
    public int maxAreaOfIsland(int[][] grid) {
           max_length=0;
           for(int i=0;i<grid.length;i++){
               for(int j=0;j<grid[i].length;j++){
                   if(grid[i][j]==1){
                       int length = dfs(i,j,grid);
                       max_length=length>max_length?length:max_length;
                   }
               }
           }
           return max_length;
    }

      private int dfs(int x, int y,int[][] grid) {
          if(x<0||y<0||x>=grid.length||y>=grid[0].length||grid[x][y]!=1)//结束条件
            return 0;
          int length = 1;
          grid[x][y]=0;//标记走过
          for(int i=0;i<4;i++){
              length+=dfs(x+xs[i],y+ys[i],grid);//上下左右搜
          }
          return length;
    }
}

733.图像渲染

题解:依然是典型的dfs模板题 搜过的不能再搜了 所以开个boolean变量来记录

class Solution {
  
    int [] [] results;
    boolean [] [] flags;
    int color;
    int []x={0,0,-1,1};
    int []y={1,-1,0,0};
    public int[][] floodFill(int[][] image, int sr, int sc, int newColor) {
        results=image;
        flags = new boolean[image.length][image[0].length];
        color = image[sr][sc];//原始点的颜色
         results[sr][sc]=newColor;  //把开始点换上新颜色
        flags[sr][sc]=true;  //把开始点标记为走过
        dfs(sr,sc,newColor);
        return results;
    }

      private void dfs(int sr, int sc,int newcolor) {
            for(int i=0;i<4;i++){
            int xx=sr+x[i];
            int yy=sc+y[i];
            if(xx<0||yy<0||xx>=results.length||yy>=results[0].length||results[xx][yy]!=color||flags[xx][yy]){
                continue;
            }
            results[xx][yy]=newcolor;//把这点换上新颜色
            flags[xx][yy]=true;//把这点标记为走过
            dfs(xx,yy,newcolor);
        }
    }
}

980. 不同路径 III

题解:最近一直在做dfs的题 还是一如既往的办法

class Solution {
     int length;//记录多少次
    int count;//记录0出现次数 因为要求每一个无障碍方格都要通过一次
    int xs[]={0,0,-1,1};
    int ys[]={1,-1,0,0};
    boolean [][] flags;//标记走过没
    public int uniquePathsIII(int[][] grid) {
        length=0;
        int sx=0,sy=0;
        count=0;
        flags = new boolean[grid.length][grid[0].length];
        for(int i=0;i<grid.length;i++){
            for(int j=0;j<grid[i].length;j++){
                if(grid[i][j]==0){
                    count++;
                }
                if(grid[i][j]==1){
                   sx=i;
                   sy=j;
                }
            }
        }
        flags[sx][sy]=true;
        dfs(sx,sy,grid);
        return length;
    }

    private void dfs(int x, int y,int [][]grid) {
        if(grid[x][y]==2&&count==-1){//注意为什么是-1 因为你走到2把2的也减掉了
            length++;
            return;
        }
        for(int i=0;i<4;i++){
            int xx=x+xs[i];
            int yy=y+ys[i];
            if(xx<0||yy<0||xx>=grid.length||yy>=grid[0].length||flags[xx][yy]){
                continue;
            }
            if(grid[xx][yy]!=-1){
                count--;
                flags[xx][yy] = true;
                dfs(xx, yy, grid);
                flags[xx][yy] = false;
                count++;
            }
        }

    }
}

542.01矩阵

题解:找出每个元素到最近的 0 的距离 根据题目提示的输入输出当原数为0时 直接是0 不是0的点则用bfs就搜距离当前最近的0的距离

class Solution {
       	int[][] lengths;
 	int[] dx = {0, 0, -1, 1};
	int[] dy = {1, -1, 0, 0};
    public int[][] updateMatrix(int[][] matrix) {
        lengths = new int[matrix.length][matrix[0].length];
        for (int i = 0; i < matrix.length; i++) {
            for (int j = 0; j < matrix[i].length; j++) {
                if (matrix[i][j] != 0) {
                    lengths[i][j] = bfs(i, j, matrix);
                }
            }
        }
        return lengths;
    }

    private int bfs(int x,int y,int [][]matrix){
        int sum=0;
        Queue<int []> q = new LinkedList<>();//创建一个队列
        q.offer(new int[]{x,y});//把当前坐标位置放到队列之中
        while(q.size()!=0){//队列为空结束循环
            int len=q.size();//取出当前队列的长度
            sum++;     //长度+1
            for(int i=0;i<len;i++){
                int[]n=q.poll();//取出队列中首位元素
                for(int j=0;j<4;j++){//上下左右搜索
                    int xx=n[0]+dx[j];
                    int yy=n[1]+dy[j];
                    if(xx<0||yy<0||xx>=matrix.length||yy>=matrix[0].length){
                        continue;
                    }
                    if(matrix[xx][yy]==0){//当等于0就走人
                        return sum;
                    }
                    else{
                        q.offer(new int[]{xx,yy});//不是0就将这个坐标加到队列中
                    }
                }
            }
        }
        return sum;
    }
}

994.腐烂的橘子

题解:首先这题并没有告诉你腐烂的橘子初始的时候有多少个,所以你只能用循环把腐烂的橘子加入队列中
用一个数来记录新鲜的橘子的个数
当新鲜橘子个数为0直接返回 如果不为0 就用bfs去搜 一旦当新鲜橘子为0就直接返回
当队列为空 但是新鲜橘子还不为0时 就返回-1 表示不可能

class Solution {
     int dx[]={1,-1,0,0};
    int dy[]={0,0,1,-1};
     Queue<int []> queue;
    int count;
    public int orangesRotting(int[][] grid) {
        queue = new LinkedList<>();
        count=0;
        for(int i=0;i<grid.length;i++){
            for(int j=0;j<grid[i].length;j++){
                if(grid[i][j]==2){
                    queue.offer(new int[]{i,j});
                }
                if(grid[i][j]==1){
                    count++;
                }
            }
        }
        if(count==0){
            return 0;
        }
        return bfs(grid);
        
    }

    private int bfs(int [][]grid) {
        int sum=0;
        while(queue.size()!=0){
            int len = queue.size();
                 sum++;
            for(int i=0;i<len;i++){
                int []n=queue.poll();
                for(int j=0;j<4;j++){
                    int xx=n[0]+dx[j];
                    int yy=n[1]+dy[j];
                    if(xx<0||xx>=grid.length||yy<0||yy>=grid[0].length||grid[xx][yy]!=1){
                        continue;
                    }
                    count--;
                    if(count==0){
                        return sum;
                    }
                    System.out.println(count);
                    grid[xx][yy]=2;
                    queue.offer(new int[]{xx,yy});

                }
            }
        }
        return -1;
        }
}


118.杨辉三角

题解:这个就应该没啥可以说的吧。。。编程中的入门题了

class Solution {
   public List<List<Integer>> generate(int numRows) {
          List<List<Integer>>  list = new ArrayList<>();
          int [][]dp = new int[numRows][numRows];
          for(int i=0;i<numRows;i++){
              List<Integer> li = new ArrayList<>();
              for(int j=0;j<=i;j++){
                  if(j==0||i==j){
                      dp[i][j]=1;
                  }else{
                      dp[i][j]=dp[i-1][j-1]+dp[i-1][j];
                  }
                  li.add(dp[i][j]);
              }
              list.add(li);
          }

          return list;
    }
}

566.重塑矩阵

题解:首先找出无法重塑新矩阵的条件 之后就开个数组双层for来重新给另外一个数组赋值 返回这个数组就OK了

class Solution {
    public int[][] matrixReshape(int[][] nums, int r, int c) {
        if(r*c!=nums.length*nums[0].length){
            return nums;
        }
          int  [][] result = new int[r][c];
               int l1=0,l2=0;
               for(int i=0;i<nums.length;i++){
                   for(int j=0;j<nums[i].length;j++){
                        result[l1][l2]=nums[i][j];
     
                        l2++;
                        if(l2==c){
                            l2=0;
                           l1++;
                        }
                   }
               }
               return result;
    }
}

171.Excel表列序号

题解:这题没其他办法 你只有用笔来算算 模拟出对应的公式

A  1  
AB   1*26+2
AAB 1*26*26+1*26+2
BBZ 2*26*26+ 2*26+26
class Solution {
    public int titleToNumber(String s) {
        int result = 0;
        int count = 1;
        for(int i=s.length()-1;i>=0;i--){
              int c  = s.charAt(i)-64;
              if(i!=s.length()-1){
                  count*=26;//这样做就懒得每次for浪费时间了
              }
             result=result+(c*count);
            
        }
        return result;
    }
}

520.检测大写字母

题解:判断首个字母和第二个字母 分别进行校验

class Solution {
  public boolean detectCapitalUse(String word) {
        if(word.length()==1){
            return true;
        }
        boolean flag = true;
        char first = word.charAt(0);
        char second = word.charAt(1);
        if(first>='a'&&first<='z'){//首字母小写
             flag = isDanCi(word,'A',1);
        }else{
            if(second>='a'&&first<='z'){
                flag = isDanCi(word,'A',1);
            }else{
                flag = isDanCi(word,'a',1);
            }
        }

        return flag;
    }

    private boolean isDanCi(String word, char a, int m) {
        for(int i=m;i<word.length();i++){
            if(word.charAt(i)>=a&&word.charAt(i)<=(a+25)){
                return false;
            }
        }
        return true;
    }
}

811.子域名访问计数

题解:就是计算出域名访问次数,最后把访问次数+" "+域名放到List集合去 先用map来存储 增加for遍历给出的次数+域名,放到map中 然后对域名进行处理 截取.之后为新的域名在用map来存储 最后把map转list

class Solution {
    Map<String,Integer> map = new HashMap<>();
    public List<String> subdomainVisits(String[] cpdomains) {
          for(String cpdomain:cpdomains){
              int count = Integer.valueOf(cpdomain.split(" ")[0]);
              String ip = cpdomain.split(" ")[1];
             addmap(ip,count);
              for(int i=0;i<ip.length();i++){
                  if(ip.charAt(i)=='.'){
                      String newip = ip.substring(i+1,ip.length());
                      addmap(newip,count);
                  }
              }
                    
          }
           List<String> list = new ArrayList<>();
         for(String key:map.keySet()){
             list.add(map.get(key)+" "+key);
         }
          return list;
    }
    
    public void addmap(String ip,int count){
        if(map.containsKey(ip)){
            int num = map.get(ip)+count;
            map.put(ip,num);
        }else{
            map.put(ip,count);
        }
    }
}

509.斐波那契数列(递归、动态规划)

题解:斐波那契数列是在编程中比较出名的例子,我用两种方法来说下如何解决这道题 第一种是最常见的就是递归了

class Solution {
    public int fib(int N) {
         if(N==0)
        return 0;
        if(N==1)
        return 1;
        return fib(N-1)+fib(N-2);
    }
}

另一种就是dp(动态规划)

class Solution {//动态规划来做用时大大降低
    public int fib(int N) {
         int []a=new int[31];
        a[0]=0;
        a[1]=1;
        for(int i=2;i<=30;i++){
            a[i]=a[i-1]+a[i-2];
        }
        return a[N];
    }
}

771.宝石与石头

题解:就是从S中找有几个是J中的 双重for就ok

class Solution {
    	public int numJewelsInStones(String J, String S) {
		int result = 0;
		for(int i=0;i<J.length();i++)
		{
			for(int j=0;j<S.length();j++)
			{
                 			 if(J.charAt(i)==S.charAt(j)){
					  result++;
				  }
			}
		}
		return result;
    }
}

709.转换成小写字母

题解:从题意中我们就知道这题怎么做了…

class Solution {
    public String toLowerCase(String str) {
		StringBuilder sb=new StringBuilder(str);
		for(int i=0;i<sb.length();i++){
			if(sb.charAt(i)>='A'&&sb.charAt(i)<='Z'){
				char temp = (char)(sb.charAt(i)+32);
				sb.setCharAt(i, temp);
			}
		}
        return sb.toString();
    }
}

猜你喜欢

转载自blog.csdn.net/qq_33248299/article/details/88643959