zoukankan      html  css  js  c++  java
  • leetcode 494. 目标数

    题目描述:

    给定一个非负整数数组,a1, a2, ..., an, 和一个目标数,S。现在你有两个符号 + 和 -。对于数组中的任意一个整数,你都可以从 + 或 -中选择一个符号添加在前面。

    返回可以使最终数组和为目标数 S 的所有添加符号的方法数。

    示例 1:

    输入: nums: [1, 1, 1, 1, 1], S: 3
    输出: 5
    解释:

    -1+1+1+1+1 = 3
    +1-1+1+1+1 = 3
    +1+1-1+1+1 = 3
    +1+1+1-1+1 = 3
    +1+1+1+1-1 = 3

    一共有5种方法让最终目标和为3。

    注意:

    1. 数组的长度不会超过20,并且数组中的值全为正数。
    2. 初始的数组的和不会超过1000。
    3. 保证返回的最终结果为32位整数。

    思路分析:

    思路一:用递归深搜,效率很低。存在重复计算。

    思路二:动态规划。由于题目中说明了不会超过1000,利用一个2000的数组来存正数和负数。

    代码:

    思路一:

     1 class Solution {
     2 public:
     3     long long dfs(vector<int>& nums, long long S, int start)
     4     {
     5         int n = nums.size();
     6         if(start >= n)
     7             return 0;
     8         if(start == n-1)
     9         {
    10             if(S == nums[start] || S== -nums[start])
    11             {
    12                 if(nums[start]==0)
    13                     return 2;
    14                 else
    15                     return 1;
    16             }
    17             else
    18                 return 0;
    19         }
    20         else
    21         {
    22             long long path1 = dfs(nums, S-nums[start], start+1);
    23             long long path2 = dfs(nums, S+nums[start], start+1);
    24             return path1+path2;
    25         }
    26     }
    27     int findTargetSumWays(vector<int>& nums, int S) {
    28         if(nums.size()==0)
    29             return 0;
    30         long long ans = dfs(nums, S, 0);
    31         return ans;
    32     }
    33 };

    思路二:

     1 class Solution {
     2 public:
     3     int findTargetSumWays(vector<int>& nums, int S) {
     4         if(nums.size()==0)
     5             return 0;
     6         int pre[2001], now[2001];
     7         memset(pre, 0, sizeof(pre));
     8         memset(now, 0, sizeof(now));
     9         pre[1000]=1;
    10         for(int i=0; i<nums.size(); i++)
    11         {
    12             for(int j=0; j<2001; j++)
    13             {
    14                 if(pre[j]!=0)
    15                 {
    16                     now[j+nums[i]] += pre[j];
    17                     now[j-nums[i]] += pre[j];
    18                 }
    19             }
    20             for(int j=0; j<2001; j++)
    21             {
    22                 pre[j] = now[j];
    23                 now[j] = 0;
    24             }
    25         }
    26         if(S>1000)
    27             return 0;
    28         else
    29             return pre[1000+S];
    30     }
    31 };
  • 相关阅读:
    Bitmap\Bytes\BitmapImage相互转换
    枚举值为什么使用1,2,4,8,16,32等2的幂方(转)
    获取电脑信息
    操作内存的帮助类
    C#调用DLL(整理)
    [原]java集合类TreeMap和TreeSet
    [原]《面试题精选》08.颠倒句子中单词的顺序
    [原]数据结构与对象的区别
    [原]初步了解Hadoop平台
    [原]《程序员面试题精选》06.查找最小的k个元素
  • 原文地址:https://www.cnblogs.com/LJ-LJ/p/11424387.html
Copyright © 2011-2022 走看看