zoukankan      html  css  js  c++  java
  • leetcode-494 目标和,cache的选择

      题目如上。

      我们假定,求从 nums 数组第 flag 位置开始目标和为 S 的组合数的函数为:G(nums, S, flag) 。

      那么状态转移方程的表示为:G(nums, S, flag) = G(nums,S-nums[flag],flag+1) + G(nums,S+nums[flag],flag+1) 。一个背包类问题。

      递归表示很好实现:

        public int recursion(int[] nums, int S, int flag){
            if (flag == nums.length) {
                if (S == 0) {
                    return 1;
                }
                return 0;
            }
            return recursion(nums,S-nums[flag],flag+1)+recursion(nums,S+nums[flag],flag+1);
        }

      相应的,指数级时间复杂度,回归过程中存在非常多的重复计算。需要用缓存优化掉这些重复计算。

      问题就在于,如果要建立缓存,缓存需要有两个维度:S 和 flag 。我们需要沿着这两个维度前进推演最终结果,但不能用简单的二维数组建立缓存。

      因为 S 的取值范围是不固定的,最大值为 S 与 nums 中所有元素的和,最小值为 nums 中所有元素的差,且可能存在负值。

      官方题解中,将 S 加 1000,使 S 全部映射到正数空间中。

      但我认为,无论问题规模的大小,直接申请长度为 1000 的连续数组空间比较浪费,更倾向于一维数组结合哈希表的方式构建缓存。

      nums 由一维数组存储,存储的元素为一张哈希表,哈希表中存储 nums 对应的 S 的解:

        public int findTargetSumWays(int[] nums, int S) {
            if (nums == null) {
                return 0;
            }
            Map<Integer, Integer>[] dpCache = new Map[nums.length];
            return dp(nums, S, 0, dpCache);
        }
    
        /**
         * @Author Nxy
         * @Date 2020/4/28
         * @Description G(nums, S, flag)
         * G(nums,S-nums[flag],flag+1)+G(nums,S+nums[flag],flag+1)
         */
        public int dp(int[] nums, int S, int flag, Map<Integer, Integer>[] dpCache) {
            if (flag == nums.length) {
                if (S == 0) {
                    return 1;
                }
                return 0;
            }
            if (dpCache[flag] != null) {
                Map<Integer, Integer> map = dpCache[flag];
                if (map.keySet().contains(S)) {
                    return map.get(S);
                }
                int tempRe = dp(nums, S - nums[flag], flag + 1, dpCache) + dp(nums, S + nums[flag], flag + 1, dpCache);
                map.put(S, tempRe);
                return tempRe;
            }
            dpCache[flag] = new HashMap<Integer, Integer>();
            int tempRe = dp(nums, S - nums[flag], flag + 1, dpCache) + dp(nums, S + nums[flag], flag + 1, dpCache);
            dpCache[flag].put(S, tempRe);
            return tempRe;
        }

      

      

  • 相关阅读:
    你欠我的幸福,怎么弥补
    爱,请你走开
    一生为你
    爱你到底
    粒子滤波简介(转载)
    关于小波变换和Gabor变换的一些知识!
    基于Opencv的MeanShift跟踪算法实现
    opencv学习网页
    基于OpenCV库的Gabor滤波器的实现
    Mean Shift算法(CamShift)
  • 原文地址:https://www.cnblogs.com/niuyourou/p/12803090.html
Copyright © 2011-2022 走看看