剑指offer47:礼物的最大价值

啊,又是一道dp的题目呢,相信这里的状态转移方程我们可以很直观地写出来:

 f(i,j)=max(f(i-1,j),f(i,j-1))+grid(i,j)

写到这里,我们能很快写出代码,但是其实边界条件也应该写进来,想想就知道了,获取题目信息之后,我们知道,在答案的矩阵的第一行和第一列都应该是对应行和列的累加和,然后进行自底向上的代码书写

代码也能很快写出来:

class Solution {
public:
    int maxValue(vector<vector<int>>& grid) {
        vector<vector<int>>ans(grid.size(),vector<int>(grid[0].size(),0));
        for(int i=0;i<grid.size();++i)
        {
            if(i==0) 
            {
                ans[i][0]=grid[i][0];
                continue;
            }
            ans[i][0]=ans[i-1][0]+grid[i][0];
        }
        for(int i=1;i<grid[0].size();++i)
        {
            ans[0][i]=ans[0][i-1]+grid[0][i];
        }
        int row=grid.size();
        int col=grid[0].size();
        for(int i=1;i<row;++i)
        {
            for(int j=1;j<col;++j)
            {
                ans[i][j]=max(ans[i-1][j],ans[i][j-1])+grid[i][j];
            }
        }
        return ans[row-1][col-1];
    }
};

结果如下所示:

 emmm,当然,我们应当想到用滑动数组来简化空间复杂度。这里我们在计算一行时其实只用了上一行以及当前行的前一个,所以我们能将O(n^2)降成O(n)代码如下所示:

class Solution {
public:
    int maxValue(vector<vector<int>>& grid) {
        vector<int>ans(grid[0].size(),0);
        ans[0]=grid[0][0];
        for(int i=1;i<grid[0].size();++i)
        {
            ans[i]=ans[i-1]+grid[0][i];
        }
        int row=grid.size();
        int col=grid[0].size();
        for(int i=1;i<row;++i)
        {
            for(int j=0;j<col;++j)
            {
                if(j==0) ans[0]=ans[0]+grid[i][0];
                else
                {
                    ans[j]=max(ans[j-1],ans[j])+grid[i][j];
                }
            }
        }
        return ans[col-1];
    }
};

结果如下所示:

 可以看到,内存消耗减少了很多噢。

不过看了下答案,好像直接在grid上面改可以把时间复杂度降为O(1),嘿嘿,不是不行嗷~

在写完自底向上的代码后,我们可以来尝试一下自顶向下(递归)的写法:

class Solution {
public:
    int maxValue(vector<vector<int>>& grid) {
        int row=grid.size(),col=grid[0].size();
        return f(grid,row-1,col-1);
    }

    int f(vector<vector<int>>& grid,int i,int j)
    {
        if(i==0&&j==0)
        {
            return grid[i][j];
        }
        else if(i==0)
        {
            grid[i][j]=f(grid,i,j-1)+grid[i][j];
            return grid[i][j];
        }
        else if(j==0)
        {
            grid[i][j]=f(grid,i-1,j)+grid[i][j];
            return grid[i][j];
        }
        grid[i][j]=max(f(grid,i-1,j),f(grid,i,j-1))+grid[i][j];
        return grid[i][j];
    }
};

结果是这样:

 呜呜呜 不知道哪里错了。。。然后试着加了个访问的数组:

class Solution {
public:
    int maxValue(vector<vector<int>>& grid) {
        int row=grid.size(),col=grid[0].size();
        vector<vector<int>> visit(row,vector<int>(col,0));
        return f(grid,visit,row-1,col-1);
    }

    int f(vector<vector<int>>& grid,vector<vector<int>>& visit,int i,int j)
    {
        if(i==0&&j==0)
        {
            visit[0][0]=1;
            return grid[i][j];
        }
        else if(visit[i][j]==1) return grid[i][j];
        else if(i==0)
        {
            grid[i][j]=f(grid,visit,i,j-1)+grid[i][j];
            visit[i][j]=1;
            return grid[i][j];
        }
        else if(j==0)
        {
            grid[i][j]=f(grid,visit,i-1,j)+grid[i][j];
            visit[i][j]=1;
            return grid[i][j];
        }
        grid[i][j]=max(f(grid,visit,i-1,j),f(grid,visit,i,j-1))+grid[i][j];
        visit[i][j]=1;
        return grid[i][j];
    }
};

结果是这样:

 啊,所以那个错了的原因我猜测是对于同一个i,j,可能重复求了多次值导致结果错误,如果猜测的不对恳请大佬们指点俺......

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值