当前位置: 首页 > wzjs >正文

亚马逊网站交友小程序开发

亚马逊网站,交友小程序开发,游戏系统网站开发说明书,沈阳高端网站制作公司哪家好文章目录 前言题目:乘积小于 K 的子数组参考思路方法一:滑动窗口方法二:二分查找 参考题解方法一:滑动窗口解法方法二:二分查找解法 深入思考浮点精度?right - left 1?二分法?哈希优…

文章目录

  • 前言
  • 题目:乘积小于 K 的子数组
  • 参考思路
    • 方法一:滑动窗口
    • 方法二:二分查找
  • 参考题解
    • 方法一:滑动窗口解法
    • 方法二:二分查找解法
  • 深入思考
    • 浮点精度?
    • right - left + 1?
    • 二分法?
    • 哈希优化?


前言

在这里插入图片描述

本题与 力扣713题 相同


题目:乘积小于 K 的子数组

给你一个整数数组 nums 和一个整数 k ,请你返回子数组内所有元素的乘积严格小于 k 的连续子数组的数目。

示例 1:
输入:nums = [10,5,2,6], k = 100
输出:8

解释:8 个乘积小于 100 的子数组分别为:[10]、[5]、[2]、[6]、[10,5]、[5,2]、[2,6]、[5,2,6]。
需要注意的是 [10,5,2] 并不是乘积小于 100 的子数组。

示例 2:
输入:nums = [1,2,3], k = 0
输出:0

提示:
1 <= nums.length <= 3 * 104
1 <= nums[i] <= 1000
0 <= k <= 106

参考思路

方法一:滑动窗口

注意!!这里的数字都是正数
联想之前的滑动窗口,如果满足非负数组的单调性

  • 也就是在非负数组中,子数组和随着窗口的扩展(右边界右移)是单调不减的

参考深入思考中的滑动窗口解析:【算法】力扣560题:和为 K 的连续子数组之深入思考

那么使用滑动窗口是非常好的办法!

  • 使用滑动窗口来维护一个满足条件的子数组范围 [left, right]。
  • 对于每个右边界 right,找到最小的左边界 left,使得窗口内的乘积小于 k。
  • 统计以 nums[right] 结尾的满足条件的子数组个数:right - left + 1。

但是要注意处理极端情况:if (k <= 1) return 0;

复杂度分析

  • 时间复杂度:O(n)
    每个元素最多被访问两次(一次加入窗口,一次移出窗口)。

  • 空间复杂度:O(1)
    只使用了常数级别的额外空间。

方法二:二分查找

如果有做过 和为k的子数组 这个题,可能会延伸思考,那么这题如果求乘积。那么我能不能也有前缀乘积的方法来解题呢?

可以!但是仔细一想前缀乘积会使得数字变得很大,从而溢出

所以我们对于数组中的每个元素 nums[i],取自然对数 ln(nums[i])。
乘积小于 k 的条件可以转换为:

nums[left] * nums[left+1] * ... * nums[right] < k

两边取对数之后

ln(nums[left]) + ln(nums[left+1]) + ... + ln(nums[right]) < ln(k)

此时一看,这不是我们熟悉的前缀和吗?
因此计算对数数组的前缀和

prefixSum[i] = ln(nums[0]) + ln(nums[1]) + ... + ln(nums[i-1])

对其变形
对于每个右边界 right,我们需要找到最小的左边界 left,使得:

prefixSum[right+1] - prefixSum[left] < ln(k)

之后,问题就转换成了找到一某一个 prefixSum 使其值 < ln(k)
所以核心就是:两边取对数将乘积问题转换为求和问题,然后利用前缀和 + 二分查找来解决

那么注意到数组的数字都是大于1的数字
所以计算前缀和数组是单调递增的,因此可以使用二分查找来高效地找到满足条件的 left。
这里可以选择直接调用库函数来实现二分查找,只需要快速找到第一个大于等于 ln(k)的位置即可

此时,可能有疑问
1.之前那题“子数组和为k”不是说不能用二分法吗?为什么这里又可以用?
2.那这里这题可以用哈希表优化来做吗?
参考答案可以看本文的第三部分:深入思考

复杂度分析

  • 时间复杂度:O(n log n)
    计算前缀乘积的时间复杂度是 O(n)。
    对于每个 j,二分查找的时间复杂度是 O(log n),总共有 n 个 j,因此二分查找的总时间复杂度是 O(n log n)。

  • 空间复杂度:O(n)
    需要存储前缀乘积数组。

二分法可以用来解决乘积小于 K 的子数组问题,但它的时间复杂度是 O(n log n),不如滑动窗口方法高效

参考题解

方法一:滑动窗口解法

class Solution {
public:int numSubarrayProductLessThanK(vector<int>& nums, int k) {if (k <= 1) return 0;int result = 0;int left = 0;int product = 1;for (int right = 0; right < nums.size(); ++right) {product *= nums[right];while (product >= k && left <= right) {product /= nums[left];++left;}result += right - left + 1;}return result;}
};

方法二:二分查找解法


class Solution {
public:int numSubarrayProductLessThanK(vector<int>& nums, int k) {if (k <= 1) return 0;int n = nums.size();vector<double> logPrefix(n + 1, 0.0);double logK = log(k); // ln(k)for (int i = 0; i < n; ++i) {logPrefix[i + 1] = logPrefix[i] + log(nums[i]);}int count = 0;// 对于每个右边界 right,使用二分查找找到最小的 leftfor (int right = 0; right < n; ++right) {// 找到第一个大于等于 target 的位置int left = upper_bound(logPrefix.begin(), logPrefix.begin() + right + 1, logPrefix[right + 1] - logK + 1e-10) - logPrefix.begin();count += right + 1 - left;}return count;}
};

深入思考

浮点精度?

在二分查找中,我们比较的是浮点数(prefixSum[mid] 和 target)。
由于浮点数的精度有限,直接比较可能会导致结果不准确。
例如,prefixSum[mid] 可能非常接近 target,但由于精度问题,prefixSum[mid] >= target 的判断可能会出错。

修正方法:
在比较时,添加一个很小的值(例如 1e-10)来避免浮点数精度问题。

这样可以确保 prefixSum[mid] 和 target 的比较更加准确。

right - left + 1?

为什么最后求解的答案是 right - left + 1?

为什么子数组个数是 right - left + 1?

由于子数组必须是连续的,因此以 nums[right] 结尾的子数组可以表示为:

[left, right], [left+1, right], [left+2, right], ..., [right, right]

简而言之,就是当在遍历左右边界的时候,子数组的个数是right - left + 1。表示以 nums[right] 结尾的满足条件的子数组个数。

right - left 表示从 left 到 right 之间的元素个数(不包括 left)。

  • +1 表示包括 left 本身。
  • 因此,right - left + 1 表示从 left 到 right 的所有子数组的个数

二分法?

首先思考这题为什么可以用二分法去查找

因为数组数字都是大于或等于 1 ,因此取对数后的前缀和数组是单调递增的,也就是越乘肯定是越大的
所以说可以使用二分法去快速查找

哈希优化?

这题可以效仿【算法】力扣560题:和为 K 的连续子数组之深入思考 使用哈希优化吗?

需要注意的是,哈希表方法通常用于解决“等于某个值”的问题
哈希表通常用于解决以下类型的问题:

  • 查找“等于某个值”的情况:例如,求和等于 k 的子数组。
  • 快速查找和更新:哈希表可以在 O(1) 时间内完成查找和更新操作。

在求和等于 K 的子数组问题中,哈希表的作用是记录前缀和的出现次数,从而快速判断是否存在子数组的和等于 k。具体来说:

  • 对于当前前缀和 sum,我们查找 sum - k 是否在哈希表中。
  • 如果存在,则说明存在若干个子数组的和等于 k。

而对于这道题:
在乘积小于 K 的子数组问题中,我们需要找到满足以下条件的子数组:

nums[left] * nums[left+1] * ... * nums[right] < k

取对数后:

ln(nums[left]) + ln(nums[left+1]) + ... + ln(nums[right]) < ln(k)

哈希表的核心功能是快速查找“等于某个值”的情况,而“小于”条件需要遍历哈希表中的所有键值对,时间复杂度会从 O(1) 退化为 O(n)。
例如,对于每个右边界 right,我们需要找到所有满足 prefixSum[left] > prefixSum[right+1] - ln(k) 的 left,这需要遍历哈希表中的所有前缀和。


文章转载自:

http://KWMob1MW.Lnbcg.cn
http://k9KUWjWo.Lnbcg.cn
http://ksW7iIdd.Lnbcg.cn
http://6MzoNr1k.Lnbcg.cn
http://K3mCNyLb.Lnbcg.cn
http://vJZJ9Ic3.Lnbcg.cn
http://bQyeUp8I.Lnbcg.cn
http://QUMXa0WB.Lnbcg.cn
http://tfcqkw0F.Lnbcg.cn
http://IWuTTkil.Lnbcg.cn
http://jIxre7Ad.Lnbcg.cn
http://DRTdZfqI.Lnbcg.cn
http://8RC2H8ZK.Lnbcg.cn
http://vgiMOybE.Lnbcg.cn
http://fkLZrJYE.Lnbcg.cn
http://7lCNrYYJ.Lnbcg.cn
http://gmrwNecm.Lnbcg.cn
http://3NqjJggG.Lnbcg.cn
http://J6mCv8Uc.Lnbcg.cn
http://jbi9FZA9.Lnbcg.cn
http://lP6upWM4.Lnbcg.cn
http://iAKRX2At.Lnbcg.cn
http://g4lxWs2M.Lnbcg.cn
http://hsm4imxt.Lnbcg.cn
http://p9NgrPg0.Lnbcg.cn
http://EKnogn23.Lnbcg.cn
http://HYLADBFR.Lnbcg.cn
http://cI8PY2MC.Lnbcg.cn
http://KzmW7umD.Lnbcg.cn
http://3bqv1hyP.Lnbcg.cn
http://www.dtcms.com/wzjs/639943.html

相关文章:

  • 广东网站建设微信商城开发下载手机微信
  • 市场营销策划ppt免费模板网站优化的文章
  • 企业网站怎么扣费的青海住房与建设厅网站
  • 邢台高端网站建设重庆网站建设cq
  • 未备案网站查询阿里巴巴做网站需要多少钱
  • 课堂资源管理网站开发需求分析企业网站公示怎么做
  • 重庆模板网站哪个好网站怎么做才是对搜索引擎友好
  • 做简单网站怎么做.tv可以做门户网站不
  • 旅游商务网站开发好用的wordpress编辑器
  • 公司的网站的设计网站制作时间代码
  • 做企业网站需要买什么资料湖南网站建设公司 尖端磐石网络
  • 大连网站开发公司电话朋友 合同 网站制作
  • dw做网站乱码wordpress 板块
  • 网站后台设置关键词在哪设网站app封装怎么做
  • 商务网站模板下载公司网站如何做宣传
  • 潮动九州网站建设网站开发技术流程
  • 凡科做的网站手机版织梦网站栏目如何做下拉
  • 国外在线代理服务器免费吉林seo推广系统
  • 微网站域名惠州网络问政平台官网
  • 网站开发需要怎么做平面广告设计行业
  • 网站建设方案可以乱写吗简单描述一下网站制作的流程
  • wordpress 文章标签调用seo营销培训咨询
  • 论文网站建设格式辽宁建设厅查询网站首页
  • 如何做视频卖给网站电子网站
  • 网站建设的流程图示网站流量太高 如何做负载均衡
  • 公众号里链接的网站怎么做的网站建设的重要性
  • 宁波公司做网站美食网站建设内容规划
  • 网站连锁店查询怎么做郴州刚刚发生的事
  • wordpress直播网站主题目前最好的找工作平台
  • 网站建设与管理职责ui网页设计学院