Guess Number Higher or Lower II

解题思想

任取一个点做第一个点,计算被该点分开的两边的loss。这个点的loss加上两边loss中的最大值,就可以完全猜出两边的所有值。所以,遍历一遍所有点,得出以每个点为起点的时候,想要猜出两边所有的值的loss,然后找出最小值就可以了。 而最小问题有两个,一个是只有一个值的时候,那就返回0;另外一个是,有两个值的时候,返回左一值。

实现

#include <iostream>
#include <string>
#include <vector>

using namespace std;

int return_max(vector<int> nums, int left, int right)
{
    int res = INT_MAX;
    if (left >= right) {
        return 0;
    }

    if(left == right - 1) return nums[left];

    if(left == right - 2) return nums[left + 1];

    for(int i = left; i <= right; i++)
    {
        int left_val = return_max(nums, left, i - 1);
        int right_val = return_max(nums, i + 1, right);

        int cur =nums[i] + (left_val > right_val ? left_val : right_val);
        res = res < cur ? res : cur;
    }

    return res;
}


int main()
{
    int n = 33;
    vector<int> nums;
    nums.push_back(0);

    for(int i = 1; i <= n; i++)
    {
        nums.push_back(i);
    }
    cout<<return_max(nums, 1, n)<<endl;

    return 0;
}

下面这种解法非常耗时。每次计算一个left与right之间的值,它的子问题都要计算一遍。而这些子问题其实只需要计算一遍就可以了。下面加一个数组。把相同left与right之间的计算记录下来。

改进版

class Solution {
public:
    int getMoneyAmount(int n) {
        vector<vector<int>> record(n + 1, vector<int>(n + 1, -1));
        return return_max_dy(1, n, record);
    }
    int return_max_dy(int left, int right, vector<vector<int>>& record)
    {
        int res = INT_MAX;
        if (left >= right) {
            return 0;
        }



        //if(left == right - 4) return left + 1 + left + 3;

        //if(left == right - 3) return left + left + 2;

        //if(left == right - 2) return left + 1;

        if(left == right - 1) return left;

        if(record[left][right] != -1) return record[left][right];

        for(int i = left; i <= right; i++)
        {
            int left_val = return_max_dy(left, i - 1, record);
            int right_val = return_max_dy(i + 1, right, record);

            if(i - 1 >= left)
            record[left][i - 1] = left_val;
            if(i + 1 <= right)
            record[i + 1][right] = right_val;

            int cur = i + (left_val > right_val ? left_val : right_val);

            res = res < cur ? res : cur;
        }

        return res;
    }

};

个人感受

这类问题,首先要想清楚它要求的值有哪些,哪些是最优的。然后就是,如何将问题分解成子问题。最后再想清楚最小子问题有哪些。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值