首页 > 编程语言 >【唐叔学算法】第七天:差分算法-高效处理数组区间更新的利器

【唐叔学算法】第七天:差分算法-高效处理数组区间更新的利器

时间:2024-12-08 23:29:36浏览次数:13  
标签:int 唐叔学 差分 算法 数组 区间 diff 第七天

你是否曾为如何高效地修改数组中某个区间内所有元素的值而苦恼?差分算法,就像一把神奇的魔法棒,能帮你轻松实现区间修改。今天,就让我们一起揭开差分算法的神秘面纱,探索它在Java编程中的应用。

什么是差分?

定义

差分(Difference)可以看作是前缀和的逆运算。给定一个数组 a,其对应的差分数组 b 满足:

  • b[0] = a[0]
  • b[i] = a[i] - a[i-1] 对于 i > 0

例如,对于原数组 [1, 2, 3, 4],差分数组为 [1, 1, 1, 1]。

而原数组 a 可以通过差分数组 b 的前缀和来恢复。即:

  • a[i] = b[0] + b[1] + ... + b[i]

基本原理

差分的主要用途在于当我们需要对数组中的某个区间 [l, r] 内的所有元素加上或减去一个相同的值 c 时,我们可以只对差分数组进行两次操作:

  • b[l] += c,表示从位置 l 开始的元素都增加 c
  • b[r+1] -= c(如果 r+1 存在),表示从位置 r+1 开始的元素减少 c,从而抵消了对后续元素的影响。

应用场景

差分算法常用于以下场景:

  • 区间更新:当需要对数组中的一段区间内的所有元素执行相同的加减操作时。
  • 区间统计:如统计数组中某个区间内满足某种条件的元素个数。
  • 前缀和或后缀和
  • 差值问题
  • 优化时间复杂度:通过差分数组,我们可以将多次区间操作的时间复杂度降低到 O(n)。

如何使用差分?

实现步骤

使用差分解决问题的一般步骤如下:

  1. 初始化差分数组:创建一个与原数组长度相同的差分数组,并根据原数组计算初始的差分值。

  2. 执行区间更新:对于每个区间更新操作,调整差分数组中的相应位置。

  3. 还原原始数组:通过对差分数组求前缀和,得到最终的更新后的数组。

注意事项

  • 差分数组的长度:差分数组的长度比原数组多 1。
  • 区间修改的处理:需要正确处理区间起始位置和结束位置的偏移。
  • 空间复杂度:虽然差分数组提供了时间效率上的优势,但也会占用额外的空间,因此在内存有限的情况下需要注意。

LeetCode实战解析

入门题:1109. 航班预订统计

题目链接:1109. 航班预订统计

题目描述:有 n 个航班,按顺序编号为 1 到 n。我们有 k 个预定记录,每个记录包含两个整数 i 和 j,表示第 i 个航班到第 j 个航班之间(包括两端)的座位被预订了一次。请返回一个长度为 n 的数组,其中答案 [k] 表示第 k 个航班上预订的座位总数。

解题思路

这个问题可以通过差分数组来解决。我们创建一个大小为 n+1 的差分数组 diff,然后遍历每个预订记录,对差分数组的相应位置进行更新。最后,通过前缀和的方式计算出每个航班的预订座位数。

Java代码实现
class Solution {
    public int[] corpFlightBookings(int[][] bookings, int n) {
        int[] diff = new int[n + 1];
        for (int[] booking : bookings) {
            int start = booking[0], end = booking[1], seats = booking[2];
            diff[start - 1] += seats;
            if (end < n) {
                diff[end] -= seats;
            }
        }

        // 计算前缀和
        int[] result = new int[n];
        result[0] = diff[0];
        for (int i = 1; i < n; i++) {
            result[i] = result[i - 1] + diff[i];
        }

        return result;
    }
}

中等题:1456. 定长子串中元音的最大数目

题目链接:1456. 定长子串中元音的最大数目

题目描述:给你一个字符串 s 和一个整数 k,请你返回 s 中长度为 k 的子串中元音字母的最大数量。

解题思路

此题可以通过滑动窗口结合差分思想来解决。首先,我们需要定义一个辅助函数来判断字符是否为元音。接着,我们利用一个计数器来跟踪当前窗口内元音的数量,并通过滑动窗口来更新最大值。

Java代码实现
class Solution {
    public int maxVowels(String s, int k) {
        int maxCount = 0, currentCount = 0;
        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            if (isVowel(c)) {
                currentCount++;
            }
            if (i >= k && isVowel(s.charAt(i - k))) {
                currentCount--;
            }
            maxCount = Math.max(maxCount, currentCount);
        }
        return maxCount;
    }

    private boolean isVowel(char c) {
        return "aeiou".indexOf(c) != -1;
    }
}

更多LeetCode题目推荐

结语

差分算法作为一种高效的算法技巧,能够显著提升区间增减值问题的解决效率。通过本文的学习,相信大家对差分算法有了更深入的理解。在实际应用中,差分算法虽然强大,但也需要注意边界条件的设定和操作的准确性。希望各位读者朋友能够在实践中灵活运用差分算法,解决更多的编程问题。如果有任何疑问或建议,欢迎在评论区留言交流!让我们一起享受编程的乐趣,不断探索和学习!

如果喜欢这篇文章,别忘了点赞和分享哦!我是唐叔,我们下次再见!

标签:int,唐叔学,差分,算法,数组,区间,diff,第七天
From: https://blog.csdn.net/Tang_is_learning/article/details/144334525

相关文章

  • 【唐叔学算法】第八天:并查集-图论连通性的大杀器
    你是否曾为如何高效地解决图论中的连通性问题而烦恼?并查集算法,就像一张无形的网,能帮你轻松连接所有节点。今天,就让我们一起揭开并查集算法的神秘面纱,探索它在Java编程中的应用。并查集是什么?并查集(Union-Find)是一种数据结构,用于处理一些不交集的合并及查询问题。它支持两......
  • 代码随想录算法训练营第二十五天|491.递增子序列、46.全排列、47。全排列ii。
    491.递增子序列1.递归传参:多加一个startIndex来控制每次递归起始位置即可。2.终止条件:其实可以不加终止条件,因为startIndex每次都会+1,不会无线递归,但是题目要求子序列大小至少为2,所以size>2就行。3.单层搜索逻辑:如下图,同一父节点下的同层上的元素使用过就不能再使用了。......
  • floyd算法及注意事项
    卡码网_97.小明逛公园对于floyd算法的写法有几个注意点:对边松弛的中间点的循环要放在三个for循环的最外层使用邻接矩阵存图时,每个点自己到自己的距离要初始化为0,即对角线的位置要初始化为0,其他点没有边直接相连时,要初始化为inf(inf依照题目定),如果初始化INT_MAX,在判断是否需......
  • 分布式系统架构1:共识算法Paxos
    1.背景今天开始更新分布式的文章,工作几年后还没系统的学习分布式的内容,趁着还有时间学习沉淀的时候多输出些文章2.为什么需要分布式共识算法思考:现在你有一份随时变动的数据,需要确保它正确存储在网络的几台不同机器上,并且要保证数据是随时可用的,应该怎么做?在分布式环境下,可以......
  • 算法题 - ACM 模式中常用输入输出用法总结
    Tips:由于算法题中的ACM模式需要自己解析输入输出,因此需要熟悉Scanner、字符串格式化等基本用法 可以在此网站进行ACM模式训练:https://kamacoder.com/problemset.php?search=%E5%9F%BA%E7%A1%80一、Scanner用法1.1构造函数://用法一:读取System.in输入的内容Scann......
  • 算法分析中的符号表示:大小 $O$、大小 $\Omega$ 及大 $\Theta$
    在算法分析中,使用符号来表示时间复杂度或空间复杂度是数学化描述算法性能的常用方式。这些符号包括大\(O\)(Big-O)、大\(\Theta\)(Big-Theta)、大\(\Omega\)(Big-Omega)以及小\(o\)(Little-o)和小\(\omega\)(Little-omega)。它们为我们提供了评估算法效率的工具,但每种符号的使用场景和重要性......
  • 数据结构与算法之美:单链表
            Hello大家好!很高兴我们又见面啦!给生活添点passion,开始今天的编程之路!我的博客:<但凡.我的专栏:《数据结构与算法之美》、《编程之路》、《题海拾贝》欢迎点赞,关注!目录 1、什么是链表2、链表的实现(C语言)2.1节点的初始化2.2节点的打印2.3节点的插入......
  • 代码随想录算法训练营第三十八天|leetcode322. 零钱兑换、leetcode279.完全平方数、le
    1leetcode322.零钱兑换题目链接:322.零钱兑换-力扣(LeetCode)文章链接:代码随想录视频链接:动态规划之完全背包,装满背包最少的物品件数是多少?|LeetCode:322.零钱兑换哔哩哔哩bilibili思路:感觉跟之前的方法思路差不多,就是对dp初始化的时候,我开始弄错了,应该初始成无限大,对dp[......
  • 数据结构与算法——顺序表
    前言本章讲解线性表中最基础的顺序表,觉得有用的话记得点点关注。正文1.线性表线性表(linearlist)是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串 ….线性表在逻辑上是线性结构,也就说......
  • 【算法】【优选算法】位运算(上)
    目录一、位运算简介及常用操作二、191.位1的个数三、338.比特位计数四、461.汉明距离五、136.只出现一次的数字六、260.只出现一次的数字III一、位运算简介及常用操作基础位运算:右移:>>左移:<<按位取反:~按位与:&:有0就是0按位或:|:有1就是1按位异或:^:相同为0......