Leetcode刷题 2021.02.11

Leetcode306 累加数

累加数是一个字符串,组成它的数字可以形成累加序列。

一个有效的累加序列必须至少包含 3 个数。除了最开始的两个数以外,字符串中的其他数都等于它之前两个数相加的和。

给定一个只包含数字 ‘0’-‘9’ 的字符串,编写一个算法来判断给定输入是否是累加数。

说明: 累加序列里的数不会以 0 开头,所以不会出现 1, 2, 03 或者 1, 02, 3 的情况。

大年三十的晚上还在写博客,/(ㄒoㄒ)/~~,马上十二点了,还是赶紧写吧, 新年愿望就是拿一个大厂的offer。
题目本身是比较基础的回溯做法,但是有各种边界情况要考虑,提交了好多次才通过。

class Solution {
    
    
    public boolean isAdditiveNumber(String num) {
    
    
        if(num.length() < 3) return false;
        //前两位是一定成立的,所以可以初始化前两位是负数
        return helper(num, 0, -1, -1, 0);
    }
    
    private boolean helper(String num, int index, long prev1, long prev2, int count){
    
    
    	//如果超过边界,并且数目大于等于三就返回true
        if (index >= num.length() && count >= 3){
    
    
            return true;
        }
        //long防止数字过大
        long now = 0;
        for(int i = index; i < num.length(); i++){
    
    
        	//获取当前的数字
            now = now * 10 + num.charAt(i) - '0';
            if (num.charAt(index) == '0' && now != 0) return false;
            //如果数目小于二,或者相等就继续递归
            if ((count < 2 || prev1 + prev2 == now) && helper(num, i + 1, prev2, now, count + 1)){
    
    
                return true;
            }
        }
        return false;
    }
}

LeetcodeLCP12 小张刷题计划

为了提高自己的代码能力,小张制定了 LeetCode 刷题计划,他选中了 LeetCode 题库中的 n 道题,编号从 0 到 n-1,并计划在 m 天内按照题目编号顺序刷完所有的题目(注意,小张不能用多天完成同一题)。

在小张刷题计划中,小张需要用 time[i] 的时间完成编号 i 的题目。此外,小张还可以使用场外求助功能,通过询问他的好朋友小杨题目的解法,可以省去该题的做题时间。为了防止“小张刷题计划”变成“小杨刷题计划”,小张每天最多使用一次求助。

我们定义 m 天中做题时间最多的一天耗时为 T(小杨完成的题目不计入做题总时间)。请你帮小张求出最小的 T是多少。

又是二分查找基础题,不断地尝试缩小边界即可。

class Solution {
    
    
    public int minTime(int[] time, int m) {
    
    
        if (time.length <= m) return 0;
        int i = 0, j = 1_000_000_000;
        //二分模板
        while (i < j){
    
    
            int mid = i + (j - i) / 2;
            if (helper(time, m, mid)){
    
    
                j = mid;
            }else{
    
    
                i = mid + 1;
            }
        }
        return i;
    }
	
	//这个可以转换为,求一段连续数组的最大值小于等于给定值,数组的一个元素可以忽略,所以肯定是忽略最大值,在遍历过程中记录即可。
    private boolean helper(int[] time, int m, int target){
    
    
        int n = time.length, sum = 0, max = 0, count = 0, i = 0;
        while (i < n){
    
    
            sum += max + time[i];
            max = Math.max(max, time[i]);
            sum -= max;
           if (sum > target){
    
    
               count++;
               sum = max = 0;
            }else{
    
    
                i++;
            }
            if (count == m) break;
        }
        return i >= n ? true : false;
    }
}

Leetcode673 最长递增子序列的个数

给定一个未排序的整数数组,找到最长递增子序列的个数。

O(n^2)的做法和最长递增子序列长度基本一致,只是需要另一个维度记录子序列的个数就行。

class Solution {
    
    
    public int findNumberOfLIS(int[] nums) {
    
    
        if (nums.length == 0) return 0;
        int n = nums.length;
        int[][] dp = new int[n][2];
        //初始化为1
        for(int i = 0; i < n; i++){
    
    
            dp[i][0] = 1;
            dp[i][1] = 1;
        }
        int max = 0;
        for(int i = 0; i < n; i++){
    
    
            for(int j = 0; j < i; j++){
    
    
            //如果当前元素大于之前的元素
                if (nums[i] > nums[j]){
    
    
                	//如果之前元素子序列的长度加1大于当前最长子序列,就更新一下子序列长度和个数
                    if (dp[j][0] + 1 > dp[i][0]){
    
    
                        dp[i][0] = dp[j][0] + 1;
                        dp[i][1] = dp[j][1];
                     //如果相等,就再加上子序列个数   
                    }else if (dp[j][0] + 1 == dp[i][0]){
    
    
                        dp[i][1] += dp[j][1];
                    }
                }
            }
            //记录一下最长子序列的长度
            max = Math.max(max, dp[i][0]);
        }
        int res = 0;
        //再遍历一次,把等于最长子序列长度的子序列数都加起来
        for(int i = 0; i < n; i++){
    
    
            if (dp[i][0] == max) res += dp[i][1];
        }
        return res;
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_43447128/article/details/113792514