力扣热题100,力扣49.字母异位词分组力扣128.最长连续序列力扣.盛水最多的容器力扣42.接雨水(单调栈)

目录

力扣49.字母异位词分组

力扣128.最长连续序列

力扣.盛水最多的容器

力扣42.接雨水(单调栈)


 

1.包的命名规范:

java的命名规范

全部采用小写

结尾不能加负数

声明包:

位置必须在首行

类:

字母数字下划线,美元符号

不能数字开头

不能有中文

不能以关键字命名

区分英文大小写

导包:说明当前所使用的类所在的包

*通配符,倒入包下所有内容

类名:大驼峰命名

属性,方法名:小驼峰命名

方法中的参数叫形参,起作用的是数据类型,调用方法时候实际传递的参数叫实参。

引用类型

类,接口,枚举,注解,数组

力扣49.字母异位词分组

相当于,我们把每个字母排序之后,然后获取当前字符串是否有对应列表,假如有,给他添加进去,没有则生成一个

return new ArrayList<List<String>>(ret.values()) 这里是吧ret这个哈希表的值都给放到这个ArrayList里面,然后去返回。

class Solution {
   public List<List<String>> groupAnagrams(String[] strs) {
        //使用排好序的作为Key
        Map<String,List<String>>ret=new HashMap<>();
        int n=strs.length;
        for(int i=0;i<n;i++){
            char[] a=strs[i].toCharArray();
            Arrays.sort(a);
            String str=new String(a);
            if(ret.get(str)==null){
                ret.put(str,new ArrayList<>());
            }
            ret.get(str).add(strs[i]);
        }
        return new ArrayList <List<String>>(ret.values());
    }
}

力扣128.最长连续序列

这个吗,第一想法就是排序,第二个想法看到ON,无脑哈希表,其余的再思考细节,用Set去个重复,然后这个题解写的一句话,我觉得特别牛逼,他说

假如一个数,他是最优的开头,换句话说,从他开始就是最长的,那么他不应该有前一个数,比如 200 100 1  2  3  4,那你说1作为最优的开头,是不是不应该有比1小1的数字,0,要不0就是最优秀的开头了。

class Solution {
    public int longestConsecutive(int[] nums) {
    //排序最少是nlogn,我可以哈希表,使用数组代替下班
    //我的话肯定首先先给他去重
    if(nums.length==0)return 0;
    Set<Integer>a=new HashSet<>();
    for(int num:nums){
        a.add(num);
    }
    //看到题解说的有道理,假如这个数应该是最长的话,那他肯定不存在前一个树
    //比如[100,4,200,1,3,2],从1开始是最优秀的选择,那么假如存在0的话,那么1肯定不是最优秀的选择;
    //所以跳过就是需要看看是否存在前一个数,存在则跳过,再去检查后一个数字呗,更新长度
    int max=0;
    
    for(int number:a){
        int ret=0;
        if(a.contains(number-1)==true){
            continue;
        }else{
            while(a.contains(number)==true){
                ret++;
                number++;
                max=Math.max(ret,max);
            }
        }
    }
    return max;
}
}

力扣.盛水最多的容器

开始先全部找能盛多少,然后他的公式吗,长✖️宽,然后不断便利,看看左右哪个小,假如左边小就去移动左边,右边小移动右边,肯定不能移动大的边,不然只会更小

class Solution {
    public int maxArea(int[] height) {
    int n=height.length;
    int max=0;
    int cur=0;
    int end=n-1; 
    //dp[n]:表示n位置上的可容纳的最多的水
    while(cur<end){
      max=Math.max(max,Math.min(height[cur],height[end])*(end-cur));
      if(height[end]>height[cur]){
        cur++;
      }else {
        end--;
      }
    }
    return max;
    }
}

力扣42.接雨水(单调栈)

这个题,之前写过,再次写又有不同感受,发现有一行代码是冗余的,所以我删了之后,发现好理解了很多

单调栈的作用是啥呢?

其实你不用在乎什么单调栈,你只需要存的下标,每个下标都比当前位置大,这样方便求他的长度,就好。其余倒是很简单没啥操作

相当于还是,我是找两个最近的水槽,然后出一个中间位置。相当于找到左右边界和水槽位置,就可以开始搞

class Solution {
    public int trap(int[] height) {
        Stack<Integer>stack=new Stack<>();
        int n=height.length;
        int sum=0;
        for(int i=0;i<n;i++){
            //什么样子会有雨水呢,两个水槽,并且中间有一个比两个水槽的一个要小
         while(!stack.isEmpty()&&height[stack.peek()]<height[i]){
            int mid=stack.pop();
//这里我们计算那个中间值
         if(!stack.isEmpty()){
            //两个边界值
          sum+=(Math.min(height[stack.peek()],height[i])-height[mid])*(i-stack.peek()-1);
          }
        }
         stack.add(i);
     }
        return sum;
  }
}

力扣31.下一个排列

相当于脑筋急转弯,我也是看题解的那个大哥写的,非常好

class Solution {
   public static void nextPermutation(int[] nums) {
    // 123456
    int n=nums.length;
    int i=n-2;
    //1  2  3

    while(i>=0&&nums[i]>=nums[i+1]){
        i--;
    }
    int ret=n-1;
    if(i>=0){
        while(ret>=0&&nums[ret]<=nums[i]){
            ret--;
        }
    }
    if(i>=0){
    swap(nums,ret,i);
        reverse(nums, i + 1, n - 1);}
    else if(i<0) {
         reverse(nums,0,n-1);
    }
}
    public static void swap(int[]nums,int a,int b){
        int t=nums[a];
        nums[a]=nums[b];
        nums[b]=t;
    }
    public static void reverse(int []nums,int x,int y){
        int left=x;
        int right=y;
        while(left<right){
            int t=nums[left];
            nums[left]=nums[right];
            nums[right]=t;
            left++;
            right--;
        }
    }
}

力扣287.寻找重复数

首先要保证不会越界,然后我们可以把它想象成一个链表,然后经典快慢指针确定是否有环,假如没环会一直不相遇,有环则会相遇,

然后让快或者慢回去,注意哈回去也是一个一个走,不能再是那个快走了

class Solution {
 public static int findDuplicate(int[] nums) {
        int n=nums.length;
        //不去越界的情况下,n+1个整数的数组,数字范围在[1,n]之内,这个是关键,否则可能会越界
        //那么我首先找他们相遇的地方
        int fast=nums[nums[0]];
        int slow=nums[0];
        //1  3  4  2 2   5 6
        while(slow!=fast){
            //走一步,vs走两步
            fast=nums[nums[fast]];
            slow=nums[slow];
        }
        fast=0;
        while(slow!=fast){
            //走一步,vs走两步
            fast=nums[fast];
            slow=nums[slow];
        }
        return slow;
    }
}

力扣239.滑动窗口最大值

这道题也是很有意思的反正,难度倒是不难,但是蛮考验代码,主要是针对情况,你是否能够井井有条的梳理出来,还要想一下,我平时用的Queue本质是LinkedList(这个本质可以支持头插,尾插,头删啥的)

我们需要面对一个情况,就是他如何更新最大值,当最大值迭代的时候,我们怎么处理,你假如开始不一条一条分析,而是直接想这两个问题,是不是很好去解决的,要是想要去解决这个题,我们需要一条一条的分析,首先就是用什么存储,肯定是一个队列,我们要维持什么呢,就是里面可以理解为一个

然后就是,维持一个递减的顺序,假如当前队列里面,所有人都是尾插,假如由于你的进入,导致顺序出现问题,不是递减的,那么就需要进行一个清空操作,然后就是因为开始没到3个,所以前三个是一个处理,后面那些就可以统一处理了,然后如何处理我们移动的时候

然后弹出的条件也很有意思,我们需要细思考一下,当前位置两种可能,要吗我移动是当前队列里面的队列首部,要吗是后面的某个值,假如是队首,那么你弹出,那么假如队列里面 3,2,1 然后你过去啦这个1(但是他并不是队列的队首,那么你又想一下,这种情况不存在的其实,只有第一种情况,因为,队首肯定是当前最大的元素,你弹出的元素,不可能是队列中的中间值甚至末尾值,因为队首登录的时候,假如1,2,3,4 这个4会把前面的1,2,3给清空,这样就好理解啦,所以只会出现一种情况

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if(nums == null || nums.length < 2) return nums;
        // 双端队列 保存当前窗口最大值的数组位置 保证队列中数组位置的数值按从大到小排序
        LinkedList<Integer> queue = new LinkedList();
        // 结果数组
        int[] result = new int[nums.length-k+1];
        for(int i = 0;i < nums.length;i++){
            // 保证从大到小 如果前面数小则需要依次弹出,直至满足要求,我看尾巴和当前值
            while(!queue.isEmpty() && nums[queue.peekLast()] <= nums[i]){
                //弹出末端元素
                queue.pollLast();
            }
            // 添加当前值对应的数组下标,尾插,细想一下,他肯定要吗是当前最大,要吗是当前最小
            queue.addLast(i);//插入的是下标
        //当最大的位置(队列头),滑动窗口到了,我们的处理,i-k表示的就是,窗口的最左边。我们下标是到了[i,j]j+1   就是到达这个j+1时候的变化
            if(queue.peek() == i-k){     
 
                queue.poll();   
            } 
            // 当窗口长度为k时(是窗口长度,不是队列长度,换句话队列只要有一个就行 保存当前窗口中最大值)
            if(i+1 >= k){
                //当i>2之后,后面就可以长度都是k了,所以对应定期的给他添加到结果里面
                result[i+1-k] = nums[queue.peek()];
            }
        }
        return result;
    }
}

力扣54.螺旋矩阵

没思路,看的题解,恍然大悟,这个题,复杂的地方是模拟想的很乱,导致不好去解题,

注意,边界值,可以相等,因为边界值相等的时候,他就是最后一行了。 

class Solution {
    public List<Integer> spiralOrder(int[][] matrix) {
        if (matrix.length == 0)
            return new ArrayList<Integer>();
            //找到上下左右四个边界
        int l = 0, r = matrix[0].length - 1, t = 0, b = matrix.length - 1, x = 0;
        //就是矩阵的乘法来去做一个总数
        Integer[] res = new Integer[(r + 1) * (b + 1)];
        while (true) {
            //向右行走
            for (int i = l; i <= r; i++) res[x++] = matrix[t][i]; // left to right
            //这个++就相当于缩圈了,并且他这个t++之后,直接到的是下一个区域,就是6这个位置
            if (++t > b) break;
            //想下走
            for (int i = t; i <= b; i++) res[x++] = matrix[i][r]; // top to bottom
            //缩圈
            if (l > --r) break;
            //向左走
            for (int i = r; i >= l; i--) res[x++] = matrix[b][i]; // right to left
            if (t > --b) break;
            //向上走
            for (int i = b; i >= t; i--) res[x++] = matrix[i][l]; // bottom to top
            if (++l > r) break;
        }
        return Arrays.asList(res);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

狗哥不是甜妹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值