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

苏州做企业网站公司沈阳思路网站制作

苏州做企业网站公司,沈阳思路网站制作,电商网站建设优缺点,网站开发编程语言一、前缀和#xff08;Prefix Sum#xff09;算法概述 前缀和算法通过预先计算数组的累加和#xff0c;可以在常数时间内回答多个区间和相关的查询问题#xff0c;是解决子数组和问题中的重要工具。 它的基本思想是通过预先计算和存储数组的前缀和#xff0c;可以在 O(1)…一、前缀和Prefix Sum算法概述 前缀和算法通过预先计算数组的累加和可以在常数时间内回答多个区间和相关的查询问题是解决子数组和问题中的重要工具。 它的基本思想是通过预先计算和存储数组的前缀和可以在 O(1) 的时间复杂度内计算任意子数组的和。 定义 对于数组 nums其前缀和 prefix[i] 定义为从数组起始位置到第 i 个元素的累加和。 具体公式prefix[i] nums[0] nums[1] ... nums[i]。 计算方法 首先创建一个额外的数组或哈希表用来存储每个位置的前缀和。通过一次遍历数组依次计算并填充这个数组或哈希表。 应用 快速计算子数组和通过前缀和可以快速计算任意子数组的和。例如子数组 nums[l...r] 的和可以通过 prefix[r] - prefix[l-1] 来计算其中 l 和 r 分别是子数组的左右边界。 解决相关问题例如最大子数组和、和为特定值的子数组个数等问题都可以通过前缀和算法高效解决。 二、前缀和习题合集 1. LeetCode 930 和相同的二元子数组 思路 假设原数组的前缀和数组为 sum且子数组 (i,j] 的区间和为 goal那么 sum[j]−sum[i]goal。因此我们可以枚举 j 每次查询满足该等式的 i 的数量。 用哈希表记录每一种前缀和出现的次数假设我们当前枚举到元素 nums[j]我们只需要查询哈希表中元素 sum[j]−goal 的数量即可这些元素的数量即对应了以当前 j 值为右边界的满足条件的子数组的数量。 pre[j] - pre[i] goal — pre[i] pre[j] - goal 如果存在前缀和为 pre[j] - goal(也就是pre[i]) 说明从某个位置 j 到当前位置 i 的子数组和为 goal 最后这些元素的总数量即为所有和为 goal 的子数组数量。 代码 class Solution {public int numSubarraysWithSum(int[] nums, int goal) {int n nums.length; // 数组的长度MapInteger,Integer map new HashMap(); // 使用哈希表来记录前缀和的出现次数int pre_J 0; // 初始前缀和为0int ans 0; // 计数器用来记录符合条件的子数组个数for (int i 0; i n; i) {map.put(preJ, map.getOrDefault(pre_J, 0) 1); // 更新前缀和为 preJ 的出现次数pre_J nums[i]; // 计算当前位置的前缀和//pre[j] - pre[i] goal //pre[i] pre[j] - goal// 计算满足条件的子数组个数// 如果存在前缀和为 pre[j] - goal(也就是pre[i])//说明从某个位置 j 到当前位置 i 的子数组和为 goalans map.getOrDefault(pre_J - goal, 0);}return ans; // 返回符合条件的子数组个数} }2. LeetCode 560 和为K的子数组 这里咋一看好像是可以用滑动窗口哈 但是发现数据里有负数。因为nums[i]可以小于0也就是说右指针j向后移1位不能保证区间会增大左指针i向后移1位也不能保证区间和会减小。 思路 同上一题类似 前缀和 哈希 class Solution {public static int subarraySum(int[] nums, int k) {int n nums.length; // 获取数组长度MapInteger,Integer map new HashMap(); // 创建哈希表用于存储前缀和及其出现次数int sum 0; // 初始化前缀和为0int ans 0; // 初始化结果为0map.put(sum,1); // 将初始的前缀和0放入哈希表并设其出现次数为1// 遍历数组for(int num : nums){sum num; // 计算当前位置的前缀和// 如果哈希表中存在前缀和为sum-k的项则说明存在和为k的子数组 sum - (sum-k) kif(map.containsKey(sum - k)){ans map.get(sum - k); // 更新结果累加前缀和为sum-k的子数组数量}map.put(sum, map.getOrDefault(sum, 0) 1); // 更新哈希表将当前前缀和放入并更新出现次数}return ans; // 返回结果} }初始时将前缀和为 0 放入哈希表 map 中表示在初始状态下存在一个前缀和为 0 的情况出现次数为 1。 如果 map 中存在 sum - k则说明从之前的某个位置到当前位置的子数组的和为 k。这是因为 sum - (sum - k) k。 如果存在这样的前缀和则将该前缀和的出现次数累加到 ans 中。 3. LeetCode 523 连续的子数组和 这里要用到数学知识——同余定理 前缀和的定义 设 preSum[i] 表示 nums 数组从 0 到 i 的元素之和。 如果存在一个子数组 nums[j..i] j i其和是 k 的倍数则 preSum[i] - preSum[j-1] 必须是 k 的倍数。 利用余数的性质(同余定理) 如果 preSum[i] 和 preSum[j-1] 对 k 取余得到相同的结果即 (preSum[i] - preSum[j-1]) % k 0则存在这样的子数组。a%k b%k ,则 a-b%k 0 满足条件 使用哈希表记录余数 使用哈希表来记录每个余数第一次出现的位置。 class Solution {public boolean checkSubarraySum(int[] nums, int k) {int n nums.length;int[] pre new int[n 1];for (int i 1; i n; i) {pre[i] pre[i - 1] nums[i - 1]; // 计算前缀和}SetInteger set new HashSet();for (int i 2; i n; i) {set.add(pre[i - 2] % k); // 将前缀和前两项的同余结果加入集合if (set.contains(pre[i] % k)) return true; // 如果当前前缀和对k取模的结果在集合中已经存在说明找到了符合条件的子数组}return false; // 如果遍历完没有找到符合条件的子数组返回false} } 4. LeetCode 724 寻找数组的中心下标 前缀和思想 法一 class Solution {public static int pivotIndex(int[] nums) {int n nums.length;int[] sumLeft new int[n]; // 用于存储每个索引位置左侧元素之和int[] sumRight new int[n]; // 用于存储每个索引位置右侧元素之和sumLeft[0] 0; // 初始化左侧和数组的第一个元素为0因为第一个元素左侧没有元素sumRight[n - 1] 0; // 初始化右侧和数组的最后一个元素为0因为最后一个元素右侧没有元素int sum1 0; // 用于计算累积的左侧和int sum2 0; // 用于计算累积的右侧和// 计算每个索引位置左侧的累积和for (int i 0; i n; i) {sum1 nums[i];sumLeft[i] sum1;}// 计算每个索引位置右侧的累积和for (int i n - 1; i 0; i--) {sum2 nums[i];sumRight[i] sum2;}// 遍历数组找到第一个满足左侧和等于右侧和的索引位置for (int i 0; i n; i) {if (sumLeft[i] sumRight[i]) {return i;}}// 如果没有找到满足条件的索引返回-1return -1;} } 法二 class Solution {public static int pivotIndex(int[] nums) {int totalSum 0; // 计算整个数组的和for (int num : nums) {totalSum num;}int leftSum 0; // 左侧和的初始值为0for (int i 0; i nums.length; i) {int rightSum totalSum - leftSum - nums[i]; // 右侧和等于总和减去左侧和和当前数字if (leftSum rightSum) {return i; // 如果左右两侧和相等则返回当前索引作为轴心索引}leftSum nums[i]; // 更新左侧和将当前数字累加到左侧和中}return -1; // 如果遍历完整个数组都没有找到轴心索引则返回-1表示不存在} }5. LeetCode 238 除自身以外数组的乘积 思路 前缀积 后缀积 左右乘积列表 我们不必将所有数字的乘积除以给定索引处的数字得到相应的答案而是利用索引左侧所有数字的乘积和右侧所有数字的乘积即前缀与后缀相乘得到答案。 注意这里有一个细节就是要除了自己所以在累乘的时候要在当前位置保存 左侧 或者 右侧 不包含自己。 前积乘后积先存后乘避开自己 class Solution {public int[] productExceptSelf(int[] nums) {int n nums.length;// L 和 R 分别表示左右两侧的乘积列表int[] L new int[n];int[] R new int[n];int[] answer new int[n];// L[i] 为索引 i 左侧所有元素的乘积// 对于索引为 0 的元素因为左侧没有元素所以 L[0] 1L[0] 1;for (int i 1; i n; i) {L[i] nums[i - 1] * L[i - 1];}// R[i] 为索引 i 右侧所有元素的乘积// 对于索引为 n-1 的元素因为右侧没有元素所以 R[length-1] 1R[n- 1] 1;for (int i n- 2; i 0; i--) {R[i] nums[i 1] * R[i 1];}// 对于索引 i除 nums[i] 之外其余各元素的乘积就是左侧所有元素的乘积乘以右侧所有元素的乘积for (int i 0; i n; i) {answer[i] L[i] * R[i];}return answer;} }class Solution {public int[] productExceptSelf(int[] nums) {int length nums.length;int[] answer new int[length];// answer[i] 表示索引 i 左侧所有元素的乘积// 因为索引为 0 的元素左侧没有元素 所以 answer[0] 1answer[0] 1;for (int i 1; i length; i) {answer[i] nums[i - 1] * answer[i - 1];}// R 为右侧所有元素的乘积// 刚开始右边没有元素所以 R 1int R 1;for (int i length - 1; i 0; i--) {// 对于索引 i左边的乘积为 answer[i]右边的乘积为 Ranswer[i] answer[i] * R;// R 需要包含右边所有的乘积所以计算下一个结果时需要将当前值乘到 R 上R * nums[i];}return answer;} }更新于 本篇blog会持续更新哦~
http://www.hkea.cn/news/14299376/

相关文章:

  • dw做的网站不显示网页设计软件免费下载
  • 企业做网站需要多少钱做网站市场大不大
  • 设计网站手机app客户端成套小说网站模板
  • 厦门网站建设 九来网站弹出文字
  • 商城网站功能列表广安 网站建设
  • 网站推广介绍中国互联网协会成立于哪一年
  • 宝安中心做网站多少钱深圳网站建设深圳网
  • 公司注册查询网站扁平化设计网站 国内
  • 云南住房与城乡建设厅网站网站SEO优化实训
  • 西宁建设厅培训中心网站WordPress允许用户发布文章
  • ps网站交互设计网站建设后续说明
  • 个人免费网站制作seo软文外包公司
  • 企业网站如何做自然搜索wordpress+假用户插件
  • 网页设计网站建设的基本流程福州百度开户多少钱
  • 成都网站推广营销微信深圳做微商网站设计
  • 常用wap网站开发工具 手机网站制作软件建设合同施工合同示范文本
  • 邳州做网站的公司买权重网站
  • 如何让网站自适应手机网站弹出窗口代码
  • 淘客网站怎么做 知乎网站开发部门工资入什么科目
  • 苏州品牌网站制作公司外贸人才网属于什么电子商务模式
  • 山东省济宁市最新消息北京seo百科
  • 河南网站推广优化公司做任务送科比网站
  • phpcmsv9网站地图推广公司的网站
  • 旅行社网站建设规划书论文观察者网wordpress
  • 一键制作网站php招生网站开发
  • 网站上传服务器教程网店代运营就是个坑
  • 南京电信网站空间扩容小程序开发需要多少钱知乎
  • 东莞南城网站建设价格洛阳网站建设启辰网络
  • 自己做黑彩网站外贸网站销售方式
  • 7天精通网站建设实录网站群建设方案.doc