leetcode刷题(九)

给定一个没有重复数字的序列,返回其所有可能的全排列。【46】

#include<stdio.h>
#include<iostream>
#include<vector>

using namespace std;

/* 保存所有组合的结果 */
std::vector<vector<int>> m_output;

void backtrack(int n, std::vector<int>& curr, int first)
{
	if(first == n)
		m_output.push_back(curr);

	for (int i = first; i < n; i++)
	{
		std::swap(curr[i], curr[first]);
		backtrack(n, curr, first + 1);
		std::swap(curr[i], curr[first]);
	}
}

void arrage(int n)
{
	std::vector<int> m_curr;
	for (int i = 1; i < n + 1; i++)
		m_curr.push_back(i);

	backtrack(n, m_curr, 0);
}

int main(int argc, char *argv[])
{
	arrage(4);

	/* 打印输出结果 */
	for (int i = 0; i < m_output.size(); i++)
	{
		for (int j = 0; j < m_output[i].size(); j++)
		{
			cout << m_output[i][j] << " ";
		}
		cout << endl;
	}
    system("pause");
    return 0;
}

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

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

方法一:枚举解法

  void caculate(vector<int>& nums, int i, int sum, int S, int &_count)
    {
        if(i == nums.size() - 1)
        {
            if(sum == S)
                _count++;
        } 
        else
        {
            caculate(nums, i + 1, sum + nums[i + 1], S, _count);
            caculate(nums, i + 1, sum - nums[i + 1], S, _count);
        }
    }

    int findTargetSumWays(vector<int>& nums, int S) 
    {
        int _count = 0;
        caculate(nums, -1, 0, S, _count);
        return _count;
    }

 复杂度:

  • 时间复杂度:O(2^N),其中 N 是数组 nums 的长度。

  • 空间复杂度:O(N)O(N),为递归使用的栈空间大小。

方法二:动态规划解法

#define LENGTH  2001
int findTargetSumWays(vector<int>& nums, int S)
{
        int _count = 0;
        /* 采用动态规划的基本思想(背包问题) */
        /* dp[i][j] = dp[i - 1][j - nums[i]] + dp[i - 1][j + nums[i]] */
        /* dp[0][j if j == + or - nums[0]] = dp[0][] */
        /* dp[nums.size() - 1][S] */
        /* 另外一点就是考虑将此状态方程写为迭代式 */
        /*  */
        int _dp[20][2001] = { 0 };

        /* 具体实现状态方程 */
        for (int i = 0; i < nums.size(); i++)
        {
                int next_sum1 = 0;
                int next_sum2 = 0;

                for (int j = -1000; j < 1001; j++)
                {
                        /* 排除和过滤操作 */
                        if (i == 0) {
                                if (j == nums[0] || -j == nums[0])
                                        _dp[0][j + 1000] += 1;
                                else
                                        _dp[0][j + 1000] = 0;
                                continue;
                        }

                        if (j - nums[i] + 1000 < 0)
                                next_sum1 = 0;
                        else
                                next_sum1 = _dp[i - 1][j - nums[i] + 1000];
                        if (j + nums[i] + 1000 < 0)
                                next_sum2 = 0;
                        else
                                next_sum2 = _dp[i - 1][j + nums[i] + 1000];        
                        _dp[i][j + 1000] = next_sum1 + next_sum2;
                }
        }
        _count = _dp[nums.size() - 1][S + 1000];
         return _count;
}

复杂度:

  • 时间复杂度,O(N * sum)
  • 空间复杂度,O(N * sum)
发布了140 篇原创文章 · 获赞 65 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/paradox_1_0/article/details/103862820