leetcode 整數拆分(c++)

嘻嘻作者哈哈發表於2019-03-08

思路:先用暴力遞迴,之後用記憶化搜尋,最後動態規劃.
列舉所有可能:以計算4為例

如上圖所示,2被重複計算,所以可以使用記憶化搜尋,將第一次計算得到的結果儲存下來,當以後再出現時直接使用第一次計算得到的值。
vs2019執行程式碼

#include<iostream>
#include<algorithm>    //max
#include<ctime>
#include<vector>
#include<cassert>
using namespace std;

//思路:將n的所有拆分可能全部列舉出來,對這些可能進行比較得到最大值
vector<int> mem;
class Solution {

private:
	int max_three(int a, int b, int c) {
		return max(a, max(b, c));         //max只能求2項的最大值
	}

	//n拆分為至少2項
	/*
	//暴力遞迴
	int _IntegerBreak(int n) {

		int res = -1;
		if (n == 1)
			return 1;

		//利用題目的加法條件,將n拆分為i + (n-i)
		//利用乘法條件, i * _IntegerBreak(n - i)為i*res,每遞迴呼叫一次都會有一個最優解,連續的最優解乘積就是最後的最大值
		for (int i(1); i < n; i++)
			res = max_three(res, i*(n - i), i * _IntegerBreak(n - i));   //注意:i*(n-i)也可能是最大值,也就是隻拆分為2個數 
		
		return res;
	}*/

	//記憶化搜尋
	/*
	int _IntegerBreak(int n) {

		if (n == 1)
			return 1;
		if (mem[n] != -1)
			return mem[n];
		
		int res(-1);
		for (int i = 1; i <= n - 1; i++)
			res = max_three(res, i*(n - i), i * _IntegerBreak(n - i));  //將每次計算的結果都返回給res
		mem[n] = res;        //記憶,儲存n的最優解
		return res;
	}*/

public:
	/*int integerBreak(int n) {
		return _IntegerBreak(n);
	}*/

	/*int integerBreak(int n) {
		assert(n >= 2);
		mem = vector<int>(n + 1, -1);
		return _IntegerBreak(n);
	}*/

	int integerBreak(int n) {
		assert(n >= 2);
		vector<int> res(n + 1, -1);
		
		res[1] = 1;

		//先把小的資料求出來,並將結果儲存在向量裡,在求解大的資料時直接使用小資料的結果(求解順序由2到n)
		//求res[n]
		for (int i = 2; i <= n; i++) {
			
			//求解res[i],把i拆為j + (i-j)
			//求解res[i]時,1<= j <=i-1 ,當j=1是為1+i-1,當j=i-1時為i-1 + (i-(i-1))
			for (int j = 1; j <= i - 1; j++)
				res[i] = max_three(res[i], j*(i - j), j*res[i - j]);
		}
			
		return res[n];
	}
};

int main()
{
	Solution s;
	int n;
	time_t start, end;
	
	while (cin >> n) {

		/*start = clock();
		cout << s.integerBreak(n) << endl;
		end = clock();
		cout << "求(" << n << ")拆分最優解暴力遞迴時間: " << (double)(end - start) / CLOCKS_PER_SEC << " s" << endl;
		cout << "\n";*/

		/*start = clock();
		cout << s.integerBreak(n) << endl;
		end = clock();
		cout << "求(" << n << ")拆分最優解記憶化搜尋遞迴時間: " << (double)(end - start) / CLOCKS_PER_SEC << " s" << endl;*/

		start = clock();
		cout << s.integerBreak(n) << endl;
		end = clock();
		cout << "求(" << n << ")拆分最優解動態規劃時間: " << (double)(end - start) / CLOCKS_PER_SEC << " s" << endl;
	}
	
	cin.get();
	return 0;
}

相關文章