21年9月第五周 力扣每日一题记录

题目

lc639. 解码方法 II
lc437. 路径总和III
lc517. 超级洗衣机
lc223. 矩形面积

09-27 lc639. 解码方法 II

  • 一道hard题,难点在于思考的全面性,容易漏case

  • 我做了挺长时间,因为我把 1 e 9 + 7 1e9+7 1e9+7写成了 10 e 9 + 7 10e9+7 10e9+7,真的服了,大哭,我是伞兵

  • 首先这是个dp问题,dp的比较简单

  • 按位读,每次进行判断

    • 如果是*,则本身能够表示9个数字,然后再看前面的字符是否有
      • 如果前面的字符是1 or 2,那么就多一种可能
      • 如果前面的字符是*,则就是连续两个*,因为*只能表示1-9,所以有15个可能
    • 如果当前是0,
      • 那么要看前一位是不是1 or 2 or *,那就是错误case
    • 如果当前是普通数字
      • 首先自己就是一种可能
      • 然后看前一位,分别进行判断,主要要检验合法性
  • 这一题其实和ip地址那题很像,但是难点在于多了个*,就让问题更麻烦了,不复杂,但麻烦,其实本题意义不大

class Solution {
    
    
    //解码,和那个ip地址很像
    //返回的是数目
    //其中还有*,有*的话,可能有多种,则需要按照前面的来看
    //是个dp问题
    //要分当前是*还是数字,两种情况要分类讨论,挺麻烦的
    //还要区分是不是0
    public int numDecodings(String s) {
    
    
        char[] ss = s.toCharArray();
        int n = ss.length;
        long[] f = new long[n];

        for(int i=0; i<n; i++){
    
    
            if(ss[i]=='*'){
    
    
                //f[i-1] * 9 
                f[i] = i>=1 ? 9*f[i-1] : 9;
                f[i] %= 10e9 +7; 
                // f[i-2] * n
                if(i>=1){
    
    
                    if(ss[i-1]=='1') f[i] += (i>=2?f[i-2]:1) * 9;
                    if(ss[i-1]=='2') f[i] += (i>=2?f[i-2]:1) * 6;
                    if(ss[i-1]=='*') f[i] += (i>=2?f[i-2]:1) * 15; // *代表1-9。所以只能有1 1-9, 2 1-6 这15个
                }
            }
            else if(ss[i]=='0'){
    
    
                //0只能和其他的一起
                if(i==0||ss[i-1]=='0') return 0;
                if(ss[i-1]=='*') f[i] += i>=2?2*f[i-2]:2;
                else if(ss[i-1]=='1'||ss[i-1]=='2') f[i] += i>=2?f[i-2]:1;
                else return 0;
            }
            else{
    
    
                f[i] = i>=1?f[i-1]:1;
                f[i] %= 10e9 +7; 
                if(i>=1){
    
    
                    if(ss[i-1]=='1') f[i] += i>=2?f[i-2]:1;
                    if(ss[i-1]=='2'&&ss[i]-'0'<7) f[i] += i>=2?f[i-2]:1;
                    if(ss[i-1]=='*'){
    
    
                        if(ss[i]-'0'<7) f[i] += i>=2?2*f[i-2]:2;
                        else f[i] += i>=2?f[i-2]:1;
                    } 
                } 
            }

            f[i] %= 1e9+7; 
        }
        return (int)f[n-1];
    }
}

09-28 lc437. 路径总和

  • 求的是二叉树上,路径总和等于k的路径的数量
  • 此处路径的约束是,只能向下,其他随便
  • 所以这里是一个多路的连续序列求和问题,可以用累加和来进行解决
  • 我这里写的方法是On2的,因为整体的数据量并不大,所以时间其实也还好
  • 其实,这里不关注前面的序列,直接用一个hashmap来存储不不同累加和对应的结尾节点个数,加上递归的回溯,这样可以o1就算出当前节点结尾的满足题意的路径个数。
  • 下面是On2的代码,懒得改了,也打败了60%多的。。

class Solution {
    
    
    //求的是所有的路径数
    //不对好像,有点难啊,在一条路径上,就是一个序列,那么就是求当前路径上的个数
    //首先,给你一个数组,让你求连续和为k的序列个数
    //然后,除此之外,每次的路径还不一样,这个倒好办,用个栈来存储当前的情况
    //用个数组来存储当前的情况
    //首先连续序列最大和,这个是On2的,然后其实可以整合成On的
    //用两个数组,一个是序列数组,存放遍历过的值,另一个是累加和数组,存放当前累加和
    private static int res;
    private static int t;
    private static int[] seq;
    private static int[] sum;
    public int pathSum(TreeNode root, int targetSum) {
    
    
        res =  0;
        t = targetSum;
        seq = new int[1001];
        sum = new int[1001];
        help(root, 1);
        return res;
    }
    //序列数组,累加和数组,当前位置数组
    private static void help(TreeNode root, int index){
    
    
        if(root==null) return;
        seq[index] = root.val;
        sum[index] = root.val + (index==0?0:sum[index-1]);
        
        res += pathNums(index);
        help(root.left,index+1);
        help(root.right,index+1);
    }  
    //计算以当前位置结尾的连续序列累加和
    private static int pathNums(int index){
    
    
        int cnt = 0;
        for(int i=0; i<index; i++){
    
    
            if(sum[index]-sum[i]==t) cnt++;
        }
        return cnt;
    }
}

09-29 lc517. 超级洗衣机

  • 这个题挺难,是个贪心
  • 首先要求出平均值,对于低于平均值的,要从别处拿,对于高于的,要往别处扩散
  • 遍历整个的数组,用diff来记录当前的总的差值(diff实际就代表,左边一共需要多少件,而扩散已知,是只能从一边到另一边的,所以就直接是diff次操作才行),那么当前左边和当前洗衣机要平衡,就至少需要其中的最大值
  • 这里比较的时候,当前的是 m − a v g m-avg mavg,因为如果是低于平均值的话,已经计算到左边了,必比diff绝对值小
class Solution {
    
    
    //首先算累加和,然后求avg
    //对于高于avg的值,它需要i-avg才能到平均值,对于低于avg的值,它需要avg-i
    //所以至少他们需要这么多的次数
    //然后中间如果有东西挡着,那么也无妨,可以做到传递,只要把中间的给选取,那么就可以保持中间不变,小值加1
    //找到一个规律,就是小值,需要加,还挺麻烦,不好写这题
    public int findMinMoves(int[] machines) {
    
    
        if(machines==null||machines.length==0) return -1;
        int sum = 0;
        for(int m:machines) sum += m;
        int avg = sum/machines.length;
        if(sum%machines.length!=0) return -1;

        int diff = 0, res = 0;
        for(int m:machines){
    
    
            diff += avg -m;
            res = Math.max(res,Math.max(Math.abs(diff),m-avg));
        }

        return res;

    }
}

09-30 lc223. 矩形面积

  • 首先思路很简单,矩形的对角坐标知道,直接就可以分别求出面积
  • 然后二者相加,减去二者的交集就可以得出它们覆盖的总面积,也就是并集
  • 如何求交集是一个问题,首先判断是否有交集,我们以矩形1为基准,用矩形2来判断,当bx1大于等于ax2时,当bx2小于等于ax1时,二者必没有交集面积,同理y方向也是一样
  • 然后再确定交集坐标,也是一样的,固定矩形1,用矩形2判断,因为此时必有交集,那么要么bx1在ax1与ax2之间,要么bx1小于等于ax1,那么此时交集矩形的x1便可以有两个情况, i n t x 1 = b x 1 > = a x 1 ? b x 1 : a x 1 ; int x1 = bx1>=ax1?bx1:ax1; intx1=bx1>=ax1?bx1:ax1;,这样就可以确定x1,同理其他的三个坐标都是这样
class Solution {
    
    
    //求总面积
    //直接求两个矩形分别的面经,然后再求交集的面积,然后减一下就可以了
    public int computeArea(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2) {
    
    
        //分别求面积
        int s1 = (ax2-ax1) * (ay2-ay1);
        int s2 = (bx2-bx1) * (by2-by1);
        //相交的面积
        int s3 = computeOverlap(ax1,ay1,ax2,ay2,bx1,by1,bx2,by2);
        return s1+s2-s3;
    }
    //计算交集面积
    private int computeOverlap(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2){
    
    
        if(bx1>=ax2||bx2<=ax1||by2<=ay1||by1>=ay2) return 0;
        //有交集
        int x1 = bx1>=ax1?bx1:ax1;
        int x2 = bx2<=ax2?bx2:ax2;
        int y1 = by1>=ay1?by1:ay1;
        int y2 = by2<=ay2?by2:ay2;
        return (x2-x1) * (y2-y1);
    }

	//这个交集计算更清晰
	private int computeOverlap(int ax1, int ay1, int ax2, int ay2, int bx1, int by1, int bx2, int by2){
    
    
        if(bx1>=ax2||bx2<=ax1||by2<=ay1||by1>=ay2) return 0;
        //有交集
        int x1 = Math.max(ax1,bx1);
        int x2 = Math.min(ax2,bx2);
        int y1 = Math.max(ay1,by1);
        int y2 = Math.min(ay2,by2);
        return (x2-x1) * (y2-y1);
    }
}

猜你喜欢

转载自blog.csdn.net/qq_34687559/article/details/120503750