LeetCode-第三个星期

除法求值

LeetCode339题,已知一些等式,根据这些等式换算出各个字母的联系,并求出题目给出的等式值。
在这里插入图片描述
思路分析:问题的方程式中会出现未知的方程式解,比如没有出现过的字母,这类方程式的解通常是不存在的,另外一些方程式会存在两个字母没有明显的交叉点,但是可以通过已知方程式的解,进行代换得到答案。这时我们可以把代换的过程,看作是从A点如何到B点的一个无向图求路径的问题,比如a/b=2.0,可以看作是A点到B点的路长为2.0,所以寻找没有明面的方程式的解,其实就是找两点之间的距离。

class Edge {
    String from;
    String to;
    double val;

    public Edge(String from, String to, double val) {
        this.from = from;
        this.to = to;
        this.val = val;
    }
}

public class Solution3 {
    HashMap<String, List<Edge>> mEdges = new HashMap<>();
    double[] mRes;

    public double[] calcEquation(List<List<String>> equations, double[] values, List<List<String>> queries) {
        for (int i = 0; i < equations.size(); i++) {
            String s1 = equations.get(i).get(0);
            String s2 = equations.get(i).get(1);
            double v1 = values[i];
            //将s1通向s2的边关联
            List<Edge> edges1 = mEdges.get(s1);
            if (edges1 == null) {
                edges1 = new ArrayList<>();
                mEdges.put(s1, edges1);
            }
            edges1.add(new Edge(s1, s2, v1));
            //s2也需要关联s1
            List<Edge> edges2 = mEdges.get(s2);
            if (edges2 == null) {
                edges2 = new ArrayList<>();
                mEdges.put(s2, edges2);
            }
            edges2.add(new Edge(s2, s1, 1 / v1));
        }
        List<String> visited = new ArrayList<>();
        for (int i = 0; i < queries.size(); i++) {
            mRes[i] = dfs(queries.get(i).get(0), queries.get(i).get(1), visited);
            visited.clear();
        }
        return mRes;
    }

    private double dfs(String start, String dest, List<String> visited) {
        if (!mEdges.containsKey(start) || !mEdges.containsKey(dest)) {
            return -1.0;
        }
        //将访问过的顶点加入
        visited.add(start);
        if (start.equals(dest)) {
            return 1.0;
        }
        //获取start顶点的边
        List<Edge> edges = mEdges.get(start);
        if (edges == null || edges.isEmpty()) {
            return -1.0;
        }
        for (Edge edge : edges) {
            if (visited.contains(edge.to)) {
                continue;
            }
            //循环遍历查找,直到找到目标点
            double res = dfs(edge.to, dest, visited);
            if (res != -1.0) {
                return res * edge.val;
            }
        }
        return -1.0;
    }
}

和至少为 K 的最短子数组

LeetCode862题,求一个数组里的连续的子数组的和,大于或等于指定的值,返回该数组的最短长度。在这里插入图片描述
思路分析:
1.让数组A不断的进行一个叠加sum,当发现sum小于1的时候,可以认为前面这段叠加是无效的,将sum置为0记录重新开始叠加的下标
2.另外这里还需对原数组做处理,将后一个小于0的数置为0,并且将该数和前一个数相加,循环判断,直到遇见一个不为0的数,该操作为下一步做铺垫
3.当sum>=K的时候,就要计算最小子数组的长度了,这里实际得出的长度并不就是最终的一个长度,需要判断sum-A[begin]是否大于K,如果条件为真,将begin向后移一位并且从sum中减去,直到条件为假,最终求出连续子数组的最小长度。

        int sum = 0, begin = 0, res = -1;
        for (int i = 0; i < A.length; i++) {
            //不断进行一个叠加
            sum += A[i];
            //当sum小于1时,前面这段叠加可以认为是无效的
            if (sum < 1) {
                sum = 0;
                //记录新开始的叠加下标的子数组
                begin = i + 1;
                continue;
            }
            //这里需要将小于0的数不断往前处理,为后续计算res做处理
            for (int j = i; A[j] < 0; j--) {
                A[j - 1] = A[j] + A[j - 1];
                A[j] = 0;
            }
            if (sum >= K) {
                //对begin做处理,如果A[begin]是大于0的,则后面的数也一定是大于0的
                while (sum - A[begin] >= K)
                    sum -= A[begin++];
                int length = i - begin + 1;
                if (res < 0 || res > length)
                    res = length;
            }
        }

        return res;

删除一次得到子数组最大和

LeetCode1186题,同样是求子数组的最大和,并且允许删除子数组中的一个元素,返回得出的最大和。
在这里插入图片描述
思路分析:
动态规划的思想,要保存之前数组计算的值,并且尝试性删除当前数组中最小的负数,来让子数组的和最大,当程序继续进行后,遇见了更小的值,导致了删除后的元素大于当前数组和的话,就按照这样的规则运行下去。

		int len = arr.length;
        int[] f = new int[len];
        int[] g = new int[len];
        f[0] = arr[0];
        g[0] = -200001;
        int res = arr[0];
        for (int i = 1; i < len; i++) {
            //f记录所有值的叠加情况,没有删除的问题
            f[i] = Math.max(f[i - 1] + arr[i], arr[i]);//其实就是f(i-1)是否<0
            //如果arr[i]是一个负数,那么前者就会比后者小,这时g[i]就需要等于f[i-1]假设此时删除的是arr[i],如果下一次遇到更小的值,就回把这个值给加上
            g[i] = Math.max(g[i - 1] + arr[i], f[i - 1]);
            res = Math.max(res, Math.max(f[i], g[i]));
        }
        return res;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值