fn fibonacci_inner(dp: &mut [usize], n: usize) -> usize {
match n {
0 => 0,
1 => 1,
n => {
if dp[n] == 0 {
dp[n] = fibonacci_inner(dp, n - 1) + fibonacci_inner(dp, n - 2);
}
dp[n]
}
}
}
pub fn fibonacci(n: usize) -> usize {
let mut dp = vec![0; n + 1];
fibonacci_inner(&mut dp, n)
}
static int fibonacciInner(final int[] dp, final int n) {
switch (n) {
case 0:
return 0;
case 1:
return 1;
default:
if (dp[n] == 0) {
dp[n] = fibonacciInner(dp, n - 1) + fibonacciInner(dp, n - 2);
}
return dp[n];
}
}
public static int fibonacci(final int n) {
final int[] dp = new int[n + 1];
return fibonacciInner(dp, n);
}
function fibonacciInner(dp: number[], n: number) {
switch (n) {
case 0:
return 0;
case 1:
return 1;
default:
if (dp[n] === 0) {
dp[n] = fibonacciInner(dp, n - 1) + fibonacciInner(dp, n - 2);
}
return dp[n];
}
}
function fibonacci(n: number): number {
const dp = new Array(n + 1).fill(0);
return fibonacciInner(dp, n);
}
func fibonacciInner(dp []int, n int) int {
switch n {
case 0:
return 0
case 1:
return 1
default:
if dp[n] == 0 {
dp[n] = fibonacciInner(dp, n-1) + fibonacciInner(dp, n-2)
}
return dp[n]
}
}
func Fibonacci(n int) int {
dp := make([]int, n+1)
return fibonacciInner(dp, n)
}
pub fn climb_stairs(single_step: &[usize], n: usize) -> usize {
if n < single_step[0] {
if n == 0 {
1
} else {
0
}
} else {
let mut sum = 0;
for k in single_step.iter().copied() {
if n < k {
break;
}
sum += climb_stairs(single_step, n - k);
}
sum
}
}
public static int climbStairs(final int[] singleStep, final int n) {
if (n < singleStep[0]) {
return n == 0 ? 1 : 0;
} else {
int sum = 0;
for (final int k : singleStep) {
if (n < k) {
break;
}
sum += climbStairs(singleStep, n - k);
}
return sum;
}
}
function climbStairs(singleStep: number[], n: number) {
if (n < singleStep[0]) {
return n === 0 ? 1 : 0;
} else {
let sum = 0;
for (const k of singleStep) {
if (n < k) {
break;
}
sum += climbStairs(singleStep, n - k);
}
return sum;
}
}
func ClimbStairs(singleStep []int, n int) int {
if n < singleStep[0] {
if n == 0 {
return 1
} else {
return 0
}
} else {
sum := 0
for _, k := range singleStep {
if n < k {
break
}
sum += ClimbStairs(singleStep, n-k)
}
return sum
}
}
由於以上程式碼有重疊子問題,所以可以用動態規劃的記憶法來優化或是用製表法將其改寫成迭代函數。
以製表法為例,改寫如下:
pub fn climb_stairs(single_step: &[usize], n: usize) -> usize {
let mut dp = vec![0; n + 1];
dp[0] = 1;
for i in 1..=n {
if i >= single_step[0] {
let mut sum = 0;
for k in single_step.iter().copied() {
if i < k {
break;
}
sum += dp[i - k];
}
dp[i] = sum;
}
}
dp[n]
}
public static int climbStairs(final int[] singleStep, final int n) {
final int[] dp = new int[n + 1];
dp[0] = 1;
for (int i = 1; i <= n; ++i) {
if (i >= singleStep[0]) {
int sum = 0;
for (final int k : singleStep) {
if (i < k) {
break;
}
sum += dp[i - k];
}
dp[i] = sum;
}
}
return dp[n];
}
function climbStairs(singleStep: number[], n: number) {
const dp = new Array<number>(n + 1).fill(0);
dp[0] = 1;
for (let i = 1;i <= n;i++) {
if (i >= singleStep[0]) {
let sum = 0;
for (const k of singleStep) {
if (i < k) {
break;
}
sum += dp[i - k];
}
dp[i] = sum;
}
}
return dp[n];
}
func ClimbStairs(singleStep []int, n int) int {
dp := make([]int, n+1)
dp[0] = 1
for i := 1; i <= n; i++ {
if i >= singleStep[0] {
sum := 0
for _, k := range singleStep {
if i < k {
break
}
sum += dp[i-k]
}
dp[i] = sum
}
}
return dp[n]
}
還可以繼續優化:
pub fn climb_stairs(single_step: &[usize], n: usize) -> usize {
let mut dp = vec![0; n + 1];
dp[0] = 1;
for i in single_step[0]..=n {
let mut sum = 0;
for k in single_step.iter().copied() {
if i < k {
break;
}
sum += dp[i - k];
}
dp[i] = sum;
}
dp[n]
}
public static int climbStairs(final int[] singleStep, final int n) {
final int[] dp = new int[n + 1];
dp[0] = 1;
for (int i = singleStep[0]; i <= n; ++i) {
int sum = 0;
for (final int k : singleStep) {
if (i < k) {
break;
}
sum += dp[i - k];
}
dp[i] = sum;
}
return dp[n];
}
function climbStairs(singleStep: number[], n: number) {
const dp = new Array<number>(n + 1).fill(0);
dp[0] = 1;
for (let i = singleStep[0];i <= n;i++) {
let sum = 0;
for (const k of singleStep) {
if (i < k) {
break;
}
sum += dp[i - k];
}
dp[i] = sum;
}
return dp[n];
}
func ClimbStairs(singleStep []int, n int) int {
dp := make([]int, n+1)
dp[0] = 1
for i := singleStep[0]; i <= n; i++ {
sum := 0
for _, k := range singleStep {
if i < k {
break
}
sum += dp[i-k]
}
dp[i] = sum
}
return dp[n]
}
public static int placeTiles(final int x, final int y) {
if (x > y) {
return 1;
} else if (x == y) {
return 2;
} else {
return placeTiles(x, y - 1) + placeTiles(x, y - x);
}
}
function placeTiles(x: number, y: number): number {
if (x > y) {
return 1;
} else if (x === y) {
return 2;
} else {
return placeTiles(x, y - 1) + placeTiles(x, y - x);
}
}
func PlaceTiles(x int, y int) int {
if x > y {
return 1
} else if x == y {
return 2
} else {
return PlaceTiles(x, y-1) + PlaceTiles(x, y-x)
}
}
由於以上程式碼有重疊子問題,所以可以用動態規劃的記憶法來優化或是用製表法將其改寫成迭代函數。
以製表法為例,改寫如下:
pub fn place_tiles(x: usize, y: usize) -> usize {
if x > y {
1
} else if x == y {
2
} else {
let mut dp = Vec::with_capacity(y + 1);
unsafe {
dp.set_len(y + 1);
}
for i in 1..=y {
match x.cmp(&i) {
Ordering::Greater => {
dp[i] = 1;
}
Ordering::Equal => {
dp[i] = 2;
}
Ordering::Less => {
dp[i] = dp[i - 1] + dp[i - x];
}
}
}
dp[y]
}
}
public static int placeTiles(final int x, final int y) {
if (x > y) {
return 1;
} else if (x == y) {
return 2;
} else {
final int[] dp = new int[y + 1];
for (int i = 1; i <= y; ++i) {
if (x > i) {
dp[i] = 1;
} else if (x == i) {
dp[i] = 2;
} else {
dp[i] = dp[i - 1] + dp[i - x];
}
}
return dp[y];
}
}
function placeTiles(x: number, y: number) {
if (x > y) {
return 1;
} else if (x === y) {
return 2;
} else {
const dp = new Array<number>(y + 1);
for (let i = 1;i <= y;i++) {
if (x > i) {
dp[i] = 1;
} else if (x === i) {
dp[i] = 2;
} else {
dp[i] = dp[i - 1] + dp[i - x];
}
}
return dp[y];
}
}
func PlaceTiles(x int, y int) int {
if x > y {
return 1
} else if x == y {
return 2
} else {
dp := make([]int, y+1)
for i := 1; i <= y; i++ {
if x > i {
dp[i] = 1
} else if x == i {
dp[i] = 2
} else {
dp[i] = dp[i-1] + dp[i-x]
}
}
return dp[y]
}
}
fn buy_items_inner(items_cost: &[usize], target_cost: usize, max_cost_index: usize) -> usize {
if target_cost < items_cost[0] {
if target_cost == 0 {
1
} else {
0
}
} else {
let mut sum = 0;
for (cost_index, cost) in items_cost.iter().copied().enumerate() {
if target_cost < cost || cost_index > max_cost_index {
break;
}
sum += buy_items_inner(items_cost, target_cost - cost, cost_index);
}
sum
}
}
pub fn buy_items(items_cost: &[usize], target_cost: usize) -> usize {
buy_items_inner(items_cost, target_cost, items_cost.len() - 1)
}
static int buyItemsInner(final int[] itemsCost, final int targetCost, final int maxCostIndex) {
if (targetCost < itemsCost[0]) {
return targetCost == 0 ? 1 : 0;
} else {
int sum = 0;
for (int costIndex = 0; costIndex < itemsCost.length; ++costIndex) {
final int cost = itemsCost[costIndex];
if (targetCost < cost || costIndex > maxCostIndex) {
break;
}
sum += buyItemsInner(itemsCost, targetCost - cost, costIndex);
}
return sum;
}
}
public static int buyItems(final int[] itemsCost, final int targetCost) {
return buyItemsInner(itemsCost, targetCost, itemsCost.length - 1);
}
function buyItemsInner(itemsCost: number[], targetCost: number, maxCostIndex: number) {
if (targetCost < itemsCost[0]) {
return targetCost === 0 ? 1 : 0;
} else {
let sum = 0;
for (let costIndex = 0;costIndex < itemsCost.length;costIndex++) {
const cost = itemsCost[costIndex];
if (targetCost < cost || costIndex > maxCostIndex) {
break;
}
sum += buyItemsInner(itemsCost, targetCost - cost, costIndex);
}
return sum;
}
}
function buyItems(itemsCost: number[], targetCost: number) {
return buyItemsInner(itemsCost, targetCost, itemsCost.length - 1);
}
func buyItemsInner(itemsCost []int, targetCost int, maxCostIndex int) int {
if targetCost < itemsCost[0] {
if targetCost == 0 {
return 1
} else {
return 0
}
} else {
sum := 0
for costIndex, cost := range itemsCost {
if targetCost < cost || costIndex > maxCostIndex {
break
}
sum += buyItemsInner(itemsCost, targetCost-cost, costIndex)
}
return sum
}
}
func BuyItems(itemsCost []int, targetCost int) int {
return buyItemsInner(itemsCost, targetCost, len(itemsCost)-1)
}
由於以上程式碼有重疊子問題,所以可以用動態規劃的記憶法來優化或是用製表法將其改寫成迭代函數。
以製表法為例,改寫如下:
pub fn buy_items(items_cost: &[usize], target_cost: usize) -> usize {
let items_cost_len = items_cost.len();
let mut dp = vec![vec![0; items_cost_len]; target_cost + 1];
for i in 0..items_cost_len {
dp[0][i] = 1;
}
for max_cost_index in 0..items_cost_len {
for i in items_cost[0]..=target_cost {
let mut sum = 0;
for (cost_index, cost) in items_cost.iter().copied().enumerate() {
if i < cost || cost_index > max_cost_index {
break;
}
sum += dp[i - cost][cost_index];
}
dp[i][max_cost_index] = sum;
}
}
dp[target_cost][items_cost_len - 1]
}
public static int buyItems(final int[] itemsCost, final int targetCost) {
final int itemsCostLen = itemsCost.length;
final int[][] dp = new int[targetCost + 1][itemsCostLen];
for (int i = 0; i < itemsCostLen; ++i) {
dp[0][i] = 1;
}
for (int maxCostIndex = 0; maxCostIndex < itemsCostLen; ++maxCostIndex) {
for (int i = itemsCost[0]; i <= targetCost; ++i) {
int sum = 0;
for (int costIndex = 0; costIndex < itemsCostLen; ++costIndex) {
final int cost = itemsCost[costIndex];
if (i < cost || costIndex > maxCostIndex) {
break;
}
sum += dp[i - cost][costIndex];
}
dp[i][maxCostIndex] = sum;
}
}
return dp[targetCost][itemsCostLen - 1];
}
function buyItems(itemsCost: number[], targetCost: number) {
const itemsCostLen = itemsCost.length;
const dp = new Array<number[]>(targetCost + 1);
dp[0] = new Array<number>(itemsCostLen).fill(1);
for (let i = 1;i <= targetCost;i++) {
dp[i] = new Array<number>(itemsCostLen).fill(0);
}
for (let maxCostIndex = 0;maxCostIndex < itemsCostLen;maxCostIndex++) {
for (let i = itemsCost[0];i <= targetCost;i++) {
let sum = 0;
for (let costIndex = 0;costIndex < itemsCost.length;costIndex++) {
const cost = itemsCost[costIndex];
if (i < cost || costIndex > maxCostIndex) {
break;
}
sum += dp[i - cost][costIndex];
}
dp[i][maxCostIndex] = sum;
}
}
return dp[targetCost][itemsCostLen - 1];
}
func BuyItems(itemsCost []int, targetCost int) int {
itemsCostLen := len(itemsCost)
dp := make([][]int, targetCost+1)
for i := 0; i <= targetCost; i++ {
dp[i] = make([]int, itemsCostLen)
}
for i := 0; i < itemsCostLen; i++ {
dp[0][i] = 1
}
for maxCostIndex := 0; maxCostIndex < itemsCostLen; maxCostIndex++ {
for i := itemsCost[0]; i <= targetCost; i++ {
sum := 0
for costIndex, cost := range itemsCost {
if i < cost || costIndex > maxCostIndex {
break
}
sum += dp[i-cost][costIndex]
}
dp[i][maxCostIndex] = sum
}
}
return dp[targetCost][itemsCostLen-1]
}
觀察以上程式,可以發現dp陣列能簡化成長度為amount + 1的一維陣列。程式繼續優化如下:
pub fn buy_items(items_cost: &[usize], target_cost: usize) -> usize {
let mut dp = vec![0; target_cost + 1];
dp[0] = 1;
for cost in items_cost.iter().copied() {
for i in cost..=target_cost {
dp[i] += dp[i - cost];
}
}
dp[target_cost]
}
public static int buyItems(final int[] itemsCost, final int targetCost) {
final int[] dp = new int[targetCost + 1];
dp[0] = 1;
for (int cost : itemsCost) {
for (int i = cost; i <= targetCost; ++i) {
dp[i] += dp[i - cost];
}
}
return dp[targetCost];
}
function buyItems(itemsCost: number[], targetCost: number) {
const dp = new Array<number>(targetCost + 1).fill(0);
dp[0] = 1;
for (const cost of itemsCost) {
for (let i = cost;i <= targetCost;i++) {
dp[i] += dp[i - cost];
}
}
return dp[targetCost];
}
func BuyItems(itemsCost []int, targetCost int) int {
dp := make([]int, targetCost+1)
dp[0] = 1
for _, cost := range itemsCost {
for i := cost; i <= targetCost; i++ {
dp[i] += dp[i-cost]
}
}
return dp[targetCost]
}
而以上程式,又可以再優化成:
pub fn buy_items(items_cost: &[usize], target_cost: usize) -> usize {
let mut dp = vec![0; target_cost + 1];
dp[0] = 1;
for i in (items_cost[0]..=target_cost).step_by(items_cost[0]) {
dp[i] = 1;
}
for cost in items_cost[1..].iter().copied() {
for i in cost..=target_cost {
dp[i] += dp[i - cost];
}
}
dp[target_cost]
}
public static int buyItems(final int[] itemsCost, final int targetCost) {
final int[] dp = new int[targetCost + 1];
dp[0] = 1;
for (int i = itemsCost[0]; i <= targetCost; i += itemsCost[0]) {
dp[i] = 1;
}
for (int costIndex = 1; costIndex < itemsCost.length; ++costIndex) {
final int cost = itemsCost[costIndex];
for (int i = cost; i <= targetCost; ++i) {
dp[i] += dp[i - cost];
}
}
return dp[targetCost];
}
function buyItems(itemsCost: number[], targetCost: number) {
const dp = new Array<number>(targetCost + 1).fill(0);
dp[0] = 1;
for (let i = itemsCost[0];i <= targetCost;i += itemsCost[0]) {
dp[i] = 1;
}
itemsCost = itemsCost.slice(1);
for (const cost of itemsCost) {
for (let i = cost;i <= targetCost;i++) {
dp[i] += dp[i - cost];
}
}
return dp[targetCost];
}
func BuyItems(itemsCost []int, targetCost int) int {
dp := make([]int, targetCost+1)
dp[0] = 1
for i := itemsCost[0]; i <= targetCost; i += itemsCost[0] {
dp[i] = 1
}
for _, cost := range itemsCost[1:] {
for i := cost; i <= targetCost; i++ {
dp[i] += dp[i-cost]
}
}
return dp[targetCost]
}
pub fn buy_items(items_cost: &[usize], target_cost: usize) -> usize {
let mut dp = vec![0; target_cost + 1];
dp[0] = 1;
for i in (items_cost[0]..=target_cost).step_by(items_cost[0]) {
dp[i] = 1;
}
let mut step = items_cost[0];
for cost in items_cost[1..].iter().copied() {
step = gcd(step, cost);
for i in (cost..=target_cost).step_by(step) {
dp[i] += dp[i - cost];
}
}
dp[target_cost]
}
pub fn gcd(mut a: usize, mut b: usize) -> usize {
if b > a {
swap(&mut a, &mut b);
}
let mut m = a % b;
while m != 0 {
a = b;
b = m;
m = a % b;
}
b
}
public static int buyItems(final int[] itemsCost, final int targetCost) {
final int[] dp = new int[targetCost + 1];
dp[0] = 1;
for (int i = itemsCost[0]; i <= targetCost; i += itemsCost[0]) {
dp[i] = 1;
}
int step = itemsCost[0];
for (int costIndex = 1; costIndex < itemsCost.length; ++costIndex) {
final int cost = itemsCost[costIndex];
step = gcd(step, cost);
for (int i = cost; i <= targetCost; i += step) {
dp[i] += dp[i - cost];
}
}
return dp[targetCost];
}
public static int gcd(int a, int b) {
if (b > a) {
final int c = b;
b = a;
a = c;
}
int m = a % b;
while (m != 0) {
a = b;
b = m;
m = a % b;
}
return b;
}
function buyItems(itemsCost: number[], targetCost: number) {
const dp = new Array<number>(targetCost + 1).fill(0);
dp[0] = 1;
for (let i = itemsCost[0];i <= targetCost;i += itemsCost[0]) {
dp[i] = 1;
}
let step = itemsCost[0];
itemsCost = itemsCost.slice(1);
for (const cost of itemsCost) {
step = gcd(step, cost);
for (let i = cost;i <= targetCost;i += step) {
dp[i] += dp[i - cost];
}
}
return dp[targetCost];
}
function gcd(a: number, b: number) {
if (b > a) {
const c = b;
b = a;
a = c;
}
let m = a % b;
while (m !== 0) {
a = b;
b = m;
m = a % b;
}
return b;
}
func BuyItems(itemsCost []int, targetCost int) int {
dp := make([]int, targetCost+1)
dp[0] = 1
for i := itemsCost[0]; i <= targetCost; i += itemsCost[0] {
dp[i] = 1
}
step := itemsCost[0]
for _, cost := range itemsCost[1:] {
step = Gcd(step, cost)
for i := cost; i <= targetCost; i += step {
dp[i] += dp[i-cost]
}
}
return dp[targetCost]
}
func Gcd(a int, b int) int {
if b > a {
c := b
b = a
a = c
}
m := a % b
for m != 0 {
a = b
b = m
m = a % b
}
return b
}