golang实现剑指offer:动态规划题型

丑数

LeetCode 面试题49:丑数

题目描述

我们把只包含因子 2、3 和 5 的数称作丑数(Ugly Number)。求按从小到大的顺序的第 n 个丑数。

示例:

输出: 12
解释: 1, 2, 3, 4, 5, 6, 8, 9, 10, 12 是前 10 个丑数。

核心思想:

  • 动态规划

  • 三指针

解题思路:

  • 已知丑数只包含因子 2, 3, 5,因此第N个丑数一定是 前面某个丑数 * 某个因子(2,3,5)得到

  • 我们可以创建一个数组,里面的数字是排好序的丑数,里面的每一个丑数是前面的某丑数乘以2、3或者5得到的

  • 定义三个指针p2,p3,p5,它们指向的数字分别只 X 2,X3,X5

  • 每次基于p2,p3,p5指向的数字计算出三个丑数,取最小的minVal

  • 将minVal添加进数组

func nthUglyNumber(n int) int {
	if n < 1 {
		return 1
	}
	dp := make([]int, n)
	//第一个丑数,即1
	dp[0] = 1
	//三指针初始指向数组第一个元素
	p2, p3, p5 := 0, 0, 0
	cur := 1

	for cur < n {
		//计算丑数,取最小值
		minVal := min(dp[p2]*2, dp[p3]*3, dp[p5]*5)
		dp[cur] = minVal
		// 每次谁计算出来,谁的指针就后移一位
		if minVal == dp[p2]*2 {
			p2++
		}
		if minVal == dp[p3]*3 {
			p3++
		}
		if minVal == dp[p5]*5 {
			p5++
		}
		cur++
	}
	return dp[cur-1]
}

func min(a, b, c int) int {
	if a < b {
		if a < c {
			return a
		}
		return c
	}

	if b < c {
		return b
	}
	return c
}

礼物的最大价值

LeetCode 面试题47

题目描述:

在一个 m*n 的棋盘的每一格都放有一个礼物,每个礼物都有一定的价值(价值大于 0)。你可以从棋盘的左上角开始拿格子里的礼物,并每次向右或者向下移动一格、直到到达棋盘的右下角。给定一个棋盘及其上面的礼物的价值,请计算你最多能拿到多少价值的礼物?

示例:

输入:
[
[1,3,1],
[1,5,1],
[4,2,1]
]
输出: 12
解释: 路径 1→3→5→2→1 可以拿到最多价值的礼物

核心思想:

  • 动态规划
  • 原地修改,使空间复杂度为O(1)
  • 从格子右下角开始计算

解题思路:

  • 明确一个点,当前格子只能向右,向下移动
  • 计算每个格子最大价值,顺序从右下角开始,从右到左,从下到上
  • 每个格子在计算时,它的右边格子,下边格子最大价值已计算完毕。
  • 当前格子最大价值 等于 当前格子价格 加上 max(右边格子最大价值,下边格子最大价值)
func maxValue(grid [][]int) int {
	row := len(grid)
	if row == 0 {
		return 0
	}
	col := len(grid[0])
	if col == 0 {
		return 0
	}
	//从格子最后一行开始
	for i := row - 1; i >= 0; i-- {
		//从最右边一列开始
		for j := col - 1; j >= 0; j-- {
			tmp1, tmp2 := 0, 0
			//获取右边格子的价值
			if j < col-1 {
				tmp1 = grid[i][j+1]
			}
			//获取下边格子的价值
			if i < row-1 {
				tmp2 = grid[i+1][j]
			}
			//比较,计算当前格子最大价值,原地修改
			grid[i][j] = grid[i][j] + max(tmp1, tmp2)
		}
	}
	return grid[0][0]
}

func max(a, b int) int {
	if a > b {
		return a
	}
	return b
}

青蛙跳台阶问题

LeetCode 面试题10-II

题目描述

一只青蛙一次可以跳上1级台阶,也可以跳上2级台阶。求该青蛙跳上一个 n 级的台阶总共有多少种跳法。答案需要取模 1e9+7(1000000007),如计算初始结果为:1000000008,请返回1.

示例

输入:n = 2
输出:2

核心思想

  • 第N级台阶跳法 = N-1级台阶跳法 + N-2级台阶跳法

实现代码

func numWays(n int) int {
    if n < 2 {
        return 1
    }
    num1,num2 :=1,1
    res :=0
    for i:=2;i <=n ;i ++ {
        res =(num1+num2) % (1e9+7)
        num1,num2 = num2,res
    }
    return res
}

复杂度分析

  • 时间复杂度 O(N): 循环计算N次。
  • 空间复杂度 O(1): 几个标志变量使用常数大小的额外空间。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值