动态规划算法 - LC354. 俄罗斯套娃信封问题

354. 俄罗斯套娃信封问题

困难

给你一个二维整数数组 envelopes ,其中 envelopes[i] = [wi, hi] ,表示第 i 个信封的宽度和高度。

当另一个信封的宽度和高度都比这个信封大的时候,这个信封就可以放进另一个信封里,如同俄罗斯套娃一样。

请计算 最多能有多少个 信封能组成一组“俄罗斯套娃”信封(即可以把一个信封放到另一个信封里面)。

注意:不允许旋转信封。

前言

这道题是最长上升子序列的变种题,难点在于:首先需要先对给定的二维数组进行排序后,再求上升子序列。

题解

首先贴出经典的解法,动态规划求上升子序列。

func maxEnvelopes(envelopes [][]int) int {
	n := len(envelopes)
	// w升序,h降序
	sort.Slice(envelopes, func(i, j int) bool {
		ei, ej := envelopes[i], envelopes[j]
		return ei[0] < ej[0] || (ei[0] == ej[0] && ei[1] > ej[1])
	})

	var dp = make([]int, n)
	for i := 0; i < n; i++ {
		dp[i] = 1
	}
	// var res int
	for i := 1; i < n; i++ {
		for j := 0; j < i; j++ {
			if envelopes[i][1] > envelopes[j][1] {
				dp[i] = max(dp[i], dp[j]+1)
			}
		}
		// res = max(res, dp[i])
	}
	return max(dp...)
}

func max(a ...int) int {
	res := a[0]
	for _, v := range a[1:] {
		if v > res {
			res = v
		}
	}
	return res
}

但是很遗憾,昨天发现这个解法已经无法通过leetcode的所有测试用例了(之前是可以的),看了下官方的题解,原来是出了新的方法求上升子序列,通过二分查找的方式,时间复杂度更低。

func maxEnvelopes(envelopes [][]int) int {
	//n := len(envelopes)
	// w升序,h降序
	sort.Slice(envelopes, func(i, j int) bool {
		ei, ej := envelopes[i], envelopes[j]
		return ei[0] < ej[0] || (ei[0] == ej[0] && ei[1] > ej[1])
	})

	var dp = make([]int, 0)
	for i := range envelopes {
		h := envelopes[i][1]
		idx := sort.SearchInts(dp, h)
		if idx < len(dp) {
			dp[idx] = h
		} else {
			dp = append(dp, h)
		}
	}

	return len(dp)
}

题解虽然看起来更简单,其实是因为golang已经内置实现sort.SearchInts函数,通过这个函数可以找到h在上升数组dp中的index下标:

(1)如果h在dp中存在,则返回h对应的下标。

(2)如果h大于dp中最大元素,则返回下标=len(dp) (注意⚠️这个下标直接索引会越界),否则返回最小的严格大于h的元素的下标

  • 9
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Sure! Here's your code with comments added: ```matlab F = zeros(length(z), 1); % Initialize the F vector with zeros for i = 1:length(z) % Define the Phi function using anonymous function Phi = @(theta, R, r) (z(i) + lc - lm) .* r.R .(R - r.sin(theta)) ./ ... ((R.^2 + r.^2 - 2*R.*r.*sin(theta)).sqrt(R.^2 + r.^2 + (z(i) + lc - lm).^2 - 2*R.*r.*sin(theta))) + ... (z(i) - lc + lm) .* r.R .(R - r.sin(theta)) ./ ... ((R.^2 + r.^2 - 2*R.*r.*sin(theta)).sqrt(R.^2 + r.^2 + (z(i) - lc + lm).^2 - 2*R.*r.*sin(theta))) + ... (z(i) + lc + lm) .* r.R .(R - r.sin(theta)) ./ ... ((R.^2 + r.^2 - 2*R.*r.*sin(theta)).sqrt(R.^2 + r.^2 + (z(i) + lc + lm).^2 - 2*R.*r.*sin(theta))) + ... (z(i) - lc - lm) .* r.R .(R - r.sin(theta)) ./ ... ((R.^2 + r.^2 - 2*R.*r.sin(theta)).sqrt(R.^2 + r.^2 + (z(i) - lc - lm).^2 - 2*R.*r.sin(theta))); % Calculate the value of F(i) using the integral3 function F(i) = BrNI / (4 * lc * (Rc - rc)) * integral3(Phi, 0, 2*pi, rc, Rc, rm, Rm); end ``` This code calculates the values of the vector `F` using a loop. The `Phi` function is defined as an anonymous function that takes `theta`, `R`, and `r` as input parameters. It performs a series of calculations and returns a value. The integral of `Phi` is then calculated using the `integral3` function. The result is stored in the corresponding element of the `F` vector. Please note that I have made some assumptions about the variables and functions used in your code since I don't have the complete context. Feel free to modify or clarify anything as needed.

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值