leetcode之DP总结

303. Range Sum Query - Immutable

解题思路:给定一个数组,计算给定区间的数字的和。利用DP算出从开始处到i的和,dp[i]=sum[i],代码如下:

class NumArray {
public:
    NumArray(vector<int> nums) 
    {
        sum.push_back(0);
        for(int i=0;i<nums.size();i++)
        {
            sum.push_back(nums[i]+sum.back());
        }
        
    }
    
    int sumRange(int i, int j) 
    {
        return sum[j+1]-sum[i];
        
    }
private:
    vector<int> sum;
};

/**
 * Your NumArray object will be instantiated and called as such:
 * NumArray obj = new NumArray(nums);
 * int param_1 = obj.sumRange(i,j);
 */
53. Maximum Subarray

题目描述:求给定数组的和最大的连续子数组。

思路一:DP,表示到该元素的时候的和最大的连续子数组,代码如下:

class Solution {
public:
    int maxSubArray(vector<int>& nums) 
    {
        int ret=nums[0];
        vector<int> dp(nums.size()+1);
        dp[0]=ret;
        for(int i=1;i<nums.size();i++)
        {
            dp[i]=max(dp[i-1]+nums[i],nums[i]);
            if(dp[i]>ret)
            {
                ret=dp[i];
            }
        }
        return ret;
        
        
    }
};
思路2:不用DP,不需要额外这么多内存,只用两个变量表示即可,代码如下:

class Solution {
public:
    int maxSubArray(vector<int>& nums) 
    {
        int ret=INT_MIN;
        int f=0;
        for(int i=0;i<nums.size();i++)
        {
            f=max(nums[i],f+nums[i]);
            ret=max(ret,f);
        }
        return ret;
    }
};
198. House Robber
题目描述:给很多房子,每个房子有钱,不能同时偷相邻的房子的财物,求可能获得的最多的宝贝。

解题思路:DP。递推公式,我们维护一个一位数组dp,其中dp[i]表示到i位置时不相邻数能形成的最大和,dp[i] = max(num[i] + dp[i - 2], dp[i - 1]),代码如下:

class Solution {
public:
    int rob(vector<int>& nums) 
    {
    	int n=nums.size();
    	if(n==0)
    	{
    		return 0;
    	}
    	vector<int> dp(n,0);
    	dp[0]=nums[0];
    	dp[1]=max(nums[0],nums[1]);
    	for(int i=2;i<n;i++)
    	{
    		dp[i]=max(dp[i-1],dp[i-2]+nums[i]);
    	}
        return dp[n-1];
    }
};
213. House Robber II

题目描述:跟上一个题目相比,这里的房子成一个圈,不能同时包含第一个和最后一个。代码如下:

// DP
class Solution {
public:
    int rob(vector<int>& nums) 
    {
        if (nums.size() <= 1) 
        {
            return nums.empty() ? 0 : nums[0];
        }
        return max(rob(nums, 0, nums.size() - 1), rob(nums, 1, nums.size()));
    }
    int rob(vector<int> &nums, int left, int right) 
    {
        if (right - left <= 1) 
        	return nums[left];
        vector<int> dp(right, 0);
        dp[left] = nums[left];
        dp[left + 1] = max(nums[left], nums[left + 1]);
        for (int i = left + 2; i < right; ++i) 
        {
            dp[i] = max(nums[i] + dp[i - 2], dp[i - 1]);
        }
        return dp.back();
    }
};

337. House Robber III

题目描述:这个题目扩展为二叉树,即不能同时偷直接相邻的节点。

Solution1:二叉树的题目:递归,深度优先遍历,宽度优先遍历,第一种,递归算法

/**
 * Definition for a binary tree node.
 * struct TreeNode {
 *     int val;
 *     TreeNode *left;
 *     TreeNode *right;
 *     TreeNode(int x) : val(x), left(NULL), right(NULL) {}
 * };
 */
class Solution {
public:
    int rob(TreeNode* root) 
    {
    	if(root==NULL)
    	{
    		return 0;
    	}
    	int val=0;
    	if(root->left)
    	{
    		val=val+rob(root->left->left)+rob(root->left->right);

    	}
    	if(root->right)
    	{
    		val=val+rob(root->right->left)+rob(root->right->right);
    	}
    	return max(root->val+val,rob(root->left)+rob(root->right));
        
    }
};
Solution 2:用hash来存储每一个节点对应的最大值。代码如下:

class Solution {
public:
    int rob(TreeNode* root) 
    {
        unordered_map<TreeNode*, int> m;
        return dfs(root, m);
    }
    int dfs(TreeNode *root, unordered_map<TreeNode*, int> &m) 
    {
        if (!root) return 0;
        if (m.count(root)) return m[root];
        int val = 0;
        if (root->left) 
        {
            val += dfs(root->left->left, m) + dfs(root->left->right, m);
        }
        if (root->right) 
        {
            val += dfs(root->right->left, m) + dfs(root->right->right, m);
        }
        val = max(val + root->val, dfs(root->left, m) + dfs(root->right, m));
        m[root] = val;
        return val;
    }
};
338. Counting Bits
题目描述:给定一个数字N,求从0到N的每个数字二进制表示后1的个数。

解题思路:如果一个数为偶数,那么它包含的1的个数与其除2后的1的个数相同,比如8,4,2,1,如果一个数为奇数,它包含的1的个数等于除2后的数加1,找到相互关系后,代码如下:

代码:

class Solution {
public:
    vector<int> countBits(int num) 
    {
        vector<int> dp(num+1,0);
        dp[1]=1;
        for(int i=2;i<num+1;i++)
        {
            if(i%2==0)
            {
                dp[i]=dp[i/2];
            }
            else
            {
                dp[i]=dp[i/2]+1;
            }
        }
        return dp;

        
    }
};
647. Palindromic Substrings

题目描述:给定一个字符串,求该字符串的所有对称的子串。

解题思路:二维DP问题,DP[j][i]表示子串sub(j,i)是否是对称的子串,如果dp[j][i]=dp[j+1][i-1]+s[i]==s[j].然后统计所有的对称的子串的个数,代码如下:

class Solution {
public:
    int countSubstrings(string s) 
    {
        if(s.size()<=1)
        {
            return s.size();
        }
        int n=s.size();
        vector<vector<bool>> dp(n,vector<bool>(n,false));
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<i;j++)
            {
                dp[j][i]=s[j]==s[i]&&((i-j<2)||dp[j+1][i-1])
            }
            dp[i][i]=true;
        }
        int ret=0;
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(dp[i][j])
                {
                    ret++;
                }
            }
        }
        return ret;
    }
};
5. Longest Palindromic Substring
题目描述:求字符串的最长的对称的子串

解题思路:同上

代码如下:

// DP
class Solution {
public:
    string longestPalindrome(string s) 
    {
        int dp[s.size()][s.size()] = {0}, left = 0, right = 0, len = 0;
        for (int i = 0; i < s.size(); ++i) {
            for (int j = 0; j < i; ++j) 
            {
                dp[j][i] = (s[i] == s[j] && (i - j < 2 || dp[j + 1][i - 1]));
                if (dp[j][i] && len < i - j + 1) 
                {
                    len = i - j + 1;
                    left = j;
                    right = i;
                }
            }
            dp[i][i] = 1;
        }
        return s.substr(left, right - left + 1);
    }
};

516. Longest Palindromic Subsequence

题目描述:求最长的对称的子序列。

解题思路:动态规划

代码如下:

class Solution {
public:
    int longestPalindromeSubseq(string s) 
    {
        int n=s.size();
        if(n<=1)
        {
            return n;
        }
        vector<vector<int>> dp(n,vector<int>(n,0));
        for(int i=0;i<n;i++)
        {
            dp[i][i]=1;
            for(int j=i-1;j>=0;j--)
            {
                if(s[i]==s[j])
                {
                    dp[j][i]=dp[j+1][i-1]+2;
                }
                else
                {
                    dp[j][i]=max(dp[j+1][i],dp[j][i-1]);
                }
            }

        }
        return dp[0][n-1];
        
    }
};
413. Arithmetic Slices
题目描述:求一个数组的所有的等差数列的子数组

解题思路:DP

class Solution {
public:
    int numberOfArithmeticSlices(vector<int>& A) 
    {
        int res = 0, n = A.size();
        vector<int> dp(n, 0);
        for (int i = 2; i < n; ++i) 
        {
            if (A[i] - A[i - 1] == A[i - 1] - A[i - 2]) 
            {
                dp[i] = dp[i - 1] + 1;
            }
            res += dp[i];
        }
        return res;
    }
};

343. Integer Break

题目描述:给定一个数字,将该数字至少分成两个,求分开后乘积最大的结果。

解题思路:dp,试着写前几个,发现规律。

class Solution {
public:
    int integerBreak(int n) 
    {
        vector<int>dp(7);
        dp[0]=0;
        dp[1]=0;
        dp[2]=1;
        dp[3]=2;
        dp[4]=4;
        dp[5]=6;
        dp[6]=9;
        for (int i = 7; i <= n; ++i) 
        {
            dp.push_back(dp[i-3]*3);
        }
        return dp[n];
    }
};

646. Maximum Length of Pair Chain

题目描述:给定一个区间数组,求满足要求的最长长度。

Input: [[1,2], [2,3], [3,4]]
Output: 2
Explanation: The longest chain is [1,2] -> [3,4]

解题思路:按照结束值进行排序,即可。

代码:

class Solution {
public:
    int findLongestChain(vector<vector<int>>& pairs) 
    {
        sort(pairs.begin(),pairs.end(),cmp);
        vector<int> pair;
        int ret=0;
        for(int i=0;i<pairs.size();i++)
        {
            if(i==0||pairs[i][0]>pair[1])
            {
                pair=pairs[i];
                ret++;
            }
        }
        return ret;
        
    }
    static bool cmp(vector<int> a,vector<int> b)
    {
        return a[1]<b[1]||a[1]==b[1]&&a[0]<b[0];
    }
 392. Is Subsequence
题目描述:给定两个字符串s和t,判断s是不是t的子串。

解题思路:依次遍历即可;

代码:

class Solution {
public:
    bool isSubsequence(string s, string t) 
    {
        int m=s.size();
        int n=t.size();
        if(m>n)
        {
            return false;
        }
        if(m==n)
        {
            return s==t;
        }
        int i=0;
        int j=0;
        while(i<m&&j<n)
        {
            if(s[i]==t[j])
            {
                i++;
                j++;
            }
            else
            {
                j++;
            }
        }
        if(i==m)
        {
            return true;
        }
        return false;
        
    }
};
494. Target Sum
题目描述:给定一个数组,求能够满足给定和的组合的个数。

Input: nums is [1, 1, 1, 1, 1], S is 3. 
Output: 5
Explanation: 

-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

There are 5 ways to assign symbols to make the sum of nums be target 3.
解题思路:深度优先遍历,求每一种组合的结果,然后统计满足要求的结果的个数。

代码如下:

class Solution {
public:
    int findTargetSumWays(vector<int>& nums, int S) 
    {
        return help(nums,0,S);
    }
    int help(vector<int>&nums,int start,int S)
    {
        if(start>=nums.size())
        {
            if(S==0)
            {
                return 1;
            }
            return 0;
        }
        return help(nums,start+1,S-nums[start])+help(nums,start+1,S+nums[start]);
    }
};



  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在信号处理领域,DOA(Direction of Arrival)估计是一项关键技术,主要用于确定多个信号源到达接收阵列的方向。本文将详细探讨三种ESPRIT(Estimation of Signal Parameters via Rotational Invariance Techniques)算法在DOA估计中的实现,以及它们在MATLAB环境中的具体应用。 ESPRIT算法是由Paul Kailath等人于1986年提出的,其核心思想是利用阵列数据的旋转不变性来估计信号源的角度。这种算法相比传统的 MUSIC(Multiple Signal Classification)算法具有较低的计算复杂度,且无需进行特征值分解,因此在实际应用中颇具优势。 1. 普通ESPRIT算法 普通ESPRIT算法分为两个主要步骤:构造等效旋转不变系统和估计角度。通过空间平移(如延时)构建两个子阵列,使得它们之间的关系具有旋转不变性。然后,通过对子阵列数据进行最小二乘拟合,可以得到信号源的角频率估计,进一步转换为DOA估计。 2. 常规ESPRIT算法实现 在描述中提到的`common_esprit_method1.m`和`common_esprit_method2.m`是两种不同的普通ESPRIT算法实现。它们可能在实现细节上略有差异,比如选择子阵列的方式、参数估计的策略等。MATLAB代码通常会包含预处理步骤(如数据归一化)、子阵列构造、旋转不变性矩阵的建立、最小二乘估计等部分。通过运行这两个文件,可以比较它们在估计精度和计算效率上的异同。 3. TLS_ESPRIT算法 TLS(Total Least Squares)ESPRIT是对普通ESPRIT的优化,它考虑了数据噪声的影响,提高了估计的稳健性。在TLS_ESPRIT算法中,不假设数据噪声是高斯白噪声,而是采用总最小二乘准则来拟合数据。这使得算法在噪声环境下表现更优。`TLS_esprit.m`文件应该包含了TLS_ESPRIT算法的完整实现,包括TLS估计的步骤和旋转不变性矩阵的改进处理。 在实际应用中,选择合适的ESPRIT变体取决于系统条件,例如噪声水平、信号质量以及计算资源。通过MATLAB实现,研究者和工程师可以方便地比较不同算法的效果,并根据需要进行调整和优化。同时,这些代码也为教学和学习DOA估计提供了一个直观的平台,有助于深入理解ESPRIT算法的工作原理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值