LeetCode 热题 HOT 100 -------31. 下一个排列(数组,数学问题)128. 最长连续序列(数组) 11. 盛最多水的容器(数组) 621. 任务调度器 (数组)

dsadas在这里插入图片描述

/**

思路:找下一个排列,并且尽可能小,所以我们应该找一序列中从左边开始的“较小值”与“较大值”交换,但是为了尽可能小应该满足:
1、“较小值”:应该尽可能靠右,并且“较小值”的右边子序列升序
2、“较大值”:这个较大值应该是“较小值”右边所有比他大的序列中的最小值
3、调换后,然后保证"较小值i处"右边是升序的 (此时i右边的数组是递减的)
4、注意:如果整个数组是递减的,则为该数组的最大值

123456 123465 123546 ... 654321
 */
class Solution {
    public void nextPermutation(int[] nums) {
        if(nums.length == 1) return ; 
        //首先找"较小值,该值是从右向左遍历的"较小值" 
        int i = nums.length-2 ;
        while(i>=0  && nums[i] >= nums[i+1]){ 
            i--;
        }  
        //此时i+1开始的数组是递减的,若i为-1,说明数组是最大排序,则只有在i>=0的时候我们才能进行判断
        int j = nums.length-1;
        if(i>=0){
            //找尽可能靠右边的大于"较小值"的最小的"较大值" (其实就是数组最后一个值)
            while(j>=0 && nums[i]>= nums[j]){
                j--;
            }
            //到此,"较小值" 和 "较大值" 就已经找到位置了,然后需要调换顺序
            int temp = nums[i];
            nums[i] = nums[j];
            nums[j] = temp;
            //这时候我们就要保证“较小值”右边是生效的,在这之前,[i+1,nums.length-1]是递减的,应该变换反转方向
            //Arrays.sort(nums , i+1 , nums.length);
            //当i=-1,说明此时数组是最大值,返回的是最小的数组排序,也可以表达为Arrays.sort(nums , i+1 , nums.length);
            //因此放到外面
        }
        Arrays.sort(nums , i+1 , nums.length);
    }   
}

//换一种写法
class Solution {
    public void nextPermutation(int[] nums) {
       int len = nums.length;
       for(int i=len-1 ; i>0 ; i--){
           if(nums[i]>nums[i-1]){
               Arrays.sort(nums,i,len);  //"i-1"为较小值,此时我们先将"i-1"右边的数组排序
               for(int j=i ; j<len ; j++){
                   if(nums[j] > nums[i-1]){
                       int temp = nums[j];
                       nums[j] = nums[i-1];
                       nums[i-1] = temp;
                       return;
                   }
               }
           }
       }
       Arrays.sort(nums);  //为了对应数组的最大序返回的数组
       return ;
    }   
}
//解法3:(和解法1差不多)
class Solution {
    public void nextPermutation(int[] nums) {
        //首先我们去找“较小值”
        int i = nums.length-2;
        while(i>=0 && nums[i]>=nums[i+1]){
            i--;
        }
        //此时找到了“最靠右边”的“较小值”,然后我们去找"尽可能小的"“较大值”,也就是在“较小值”的
        //右边序列中仅大于“较小值”的最大值
        int j = nums.length-1;

        //如果i<0,也就是-1,则说明这个数组正好是降序的,也就是这个数组可以表示的最大值
        //所以我们在i>=0,的时候我们才进行交换
        if(i>=0){
            while(j>=0 && nums[i]>=nums[j]){
                j--;
            }
            //此时就找到了我们想要的“较大值”的位置,然后让两个值交换
            // 为了低耦合,我们用方法进行“交换”
            swap(nums,i,j);
        }

        //这时候我们就要保证“较小值”右边是生效的,在这之前,[i+1,nums.length-1]是递减的,应该变换反转方向
        reverse(nums,i+1);
    }
    public void swap(int[] nums , int i , int j){
        int temp = nums[i];
        nums[i] = nums[j];
        nums[j] = temp;
    }
    public void reverse(int[] nums , int start){
        int l = start , r = nums.length-1;
        while(l < r){
            swap(nums,l,r);
            l++;
            r--;
        }
    }
}

dasdasd在这里插入图片描述

//思路:如果不考虑时间复杂度0(n),可以先排序,然后滑动窗口。
//因为考虑时间复杂度,所以要换一种数学思想:“核心思想”:我们只要去找一个连续的当中得最小值开始求就可以,通过num,num-1判定
//1、优化:因为我们找连续的,所以可以通过set来去掉重复的数
//2、遍历数组,我们没必要每个数都找连续,如果当前数值-1不在set中,我们再去求连续,如果在则不用了
class Solution {
    public int longestConsecutive(int[] nums) {
        //创建set
        Set<Integer> nums_set = new HashSet<Integer>();
        //将数组放入到set中
        for(int num : nums){
            nums_set.add(num);
        }
        int longestCount = 0;
        //遍历数组,看num-1是否在set中,如果在,就没必要去就最大连续,如果不在,就可以去求最大连续
        for(int num : nums){
            if(!nums_set.contains(num-1)){
                //说明不包含num-1,则num是某个连续序列得最小值
                int curNum = num;
                int curCount = 1;
                //求“num是某个连续序列得最小值”的连续序列得长度
                while(nums_set.contains(curNum+1)){
                    curNum+=1;
                    curCount += 1;
                }
                longestCount = Math.max(longestCount,curCount);
            }
        }
        return longestCount;
    }
}

dasdas在这里插入图片描述

//第一种方法,双重for循环,我记得会超时,所以不再写
/*
通过左右指针判断,通过一个变量存储水的面记 areaMax = Integer.MIN_VALUE
然后做右指针记录数值,往里面遍历,如果高变大了我们重新求面积,如果没有变大,则直接略过
时间复杂度O(n) 空间复杂度O(1)
*/
class Solution {
    public int maxArea(int[] height) {
        int l = 0 , r  = height.length-1;
        int maxArea = (r-l) * Math.min(height[l] , height[r]);
        while(l<r){
            if(height[l]<height[r]){
                l++;
            }else{
                r--;
            }
            maxArea = Math.max(maxArea , (r-l)*Math.min(height[l],height[r]));
        }
        return maxArea;
    }
}

//优化算法
class Solution {
    public int maxArea(int[] height) {
        int l = 0 , r  = height.length-1 ,  maxArea = 0;
        while(l<r){
           maxArea = height[l] > height[r] ?  Math.max(maxArea , (r-l)*height[r--]) : Math.max(maxArea , (r-l)*height[l++]);
        }
        return maxArea;
    }
}

dasdads在这里插入图片描述

//解题思路:“桶思想”:很奇妙的思想
//1、我们找几个桶子,大小是数组中最大重复字数的个数
//2、每个桶的容量是(n+1),这样可以保证每个桶都是不需要待命的,因此这种情况的全部时间就是(桶数-1)*(间隔数+1)+最后一个桶的任务个数
//3、第二种情况就是不需要待命,则总时间就是"tasks.length()""

class Solution {
    public int leastInterval(char[] tasks, int n) {
        //求一下数组的长度
        int len = tasks.length;
        //求一下最大个数的任务是什么,相同个数的任务有多少
        int maxTask = 0 , maxCountTask = 0;
        //创建放任务的数组,一共26个字母
        int[] temp = new int[26];
        //往里面存入数据
        for(char c : tasks){
            temp[c-'A']++;    //存入数据
            maxTask = Math.max(maxTask,temp[c-'A']);
        }
        for(int countTask : temp){
            if(countTask == maxTask){
                maxCountTask++;
            }
        }
        return Math.max(len,(maxTask-1)*(n+1)+maxCountTask);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值