动态数组的重要性---例Longest Palindromic Substring

创建动态数组

刷题时,很多时候需要创建一个长度为n的数组。
比如我们可能想采用这种方式:

//C++代码
int n = str1.size()
bool dp[n];

但这么做是错误的,因为在编译阶段,编译器并不知道 n 的值是多少。(网上的有的leetcode教程就是这么写的,可能是之前编译器能通过?反正我用VS2010是编译不了的)
所以,这个时候我们就应该采用创建动态数组。

应该改成:(一维动态数组的创建)

int n = str1.size();
bool *dp=new int[n];

值得注意的是,动态数组创建后,要记得手动释放:

delete[] dp;

那么,如果我要创建二维动态数组,怎么做呢?请看下面代码:

//我们创建n*n的二维数组
int n = s.size();
bool **dp = new bool*[n]; //有n行
for(int i=0;i<n;i++){
   dp[i] = new bool[n]; //有n列
}

同样的,使用完后需要释放内存:

for(int i=0;i<n;i++){
    delete[] dp[i]; //释放第二维(列)内存
}
delete[] dp; //释放第一维(行)内存

注意,释放内存的时候一定要在最后,我们不在使用它时再释放。
写的好的文章有:
https://blog.csdn.net/singebogo/article/details/70477737
https://www.cnblogs.com/wft1990/p/5962898.html

vector方法创建数组

上面是用动态数组的方式创建n*n二维数组,效率比较高,但用起来也麻烦,代码比较多。
如果不考虑时间复杂度的话(有的题目用vector创建数组,提交会发现超时,下面有例子),其实可以用vector直接创建。比较方便省事,还不用手动释放内存。

创建长度为n的一维数组:

#include<vector>
using namespace std;
int n = s.size();
vector<bool> dp(n);

创建n*n的二维数组:

#include<vector>
using namespace std;
int n = s.size();
vector<vector<bool> > dp(n,vector<bool>(n));

以Longest Palindromic Substring为例

为什么是以这道题为例呢,因为它能说明动态数组的重要性。如果你用vector创建数组,自己调试的时候结果都对,就是提交显示超时。只能用动态数组的方式,才accept,这也体现了动态数组的重要性,和它效率要远高于vector。

下面顺便简单介绍一下这个题目:
https://leetcode.com/problems/longest-palindromic-substring/description/

Longest Palindromic Substring 最长回文串
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.
Example 1:
Input: “babad”
Output: “bab”
Note: “aba” is also a valid answer.
Example 2:
Input: “cbbd”
Output: “bb”
我觉得比较好理解的解法是用动态规划。
可以参考 https://www.cnblogs.com/grandyang/p/4464476.html 的解法二。

我们维护一个二维数组dp,其中dp[i][j]表示字符串区间[i, j]是否为回文串,当i = j时,只有一个字符,肯定是回文串,如果i = j + 1,说明是相邻字符,此时需要判断s[i]是否等于s[j],如果i和j不相邻,即i - j >= 2时,除了判断s[i]和s[j]相等之外,dp[j + 1][i - 1]若为真,就是回文串,通过以上分析,可以写出递推式如下:

dp[i, j] = 1                                         if i == j

	   = s[i] == s[j]                                if j = i + 1

       = s[i] == s[j] && dp[i + 1][j - 1]            if j > i + 1      

这三句话可以合并起来,得到一句就是:dp[j][i] = (s[i]==s[j]&&(i-j<2||dp[j+1][i-1]));
最后的代码和测试为:

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

using namespace std;

class Solution {
public:
    string longestPalindrome(string s) {
        int n = s.size();
        int start=0,end=0;
        bool **dp = new bool*[n];
        for(int i=0;i<n;i++){
            dp[i] = new bool[n];
        }
        //vector<vector<bool> > dp(n,vector<bool>(n));
        for(int i=0;i<n;i++)
            for(int j=0;j<n;j++){
                dp[i][j] = false;
            }
        for(int i=0;i<n;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]&&i-j+1>end-start+1){
                    start = j;
                    end = i;
                }
            }
        }
        for(int i=0;i<n;i++){
            delete[] dp[i];
        }
        delete[] dp;
        return s.substr(start,end-start+1);
    }
};

int main()
{
    string s = "anonblevel";
    Solution solve;
    string res = solve.longestPalindrome(s);
    printf("%s\n",res.c_str());
	return 0;
}

提交的话,只需要提交class Solution{...}这部分内容就行。

以上~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值