Java线段树(含面试大厂题和源码)

这篇具有很好参考价值的文章主要介绍了Java线段树(含面试大厂题和源码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

线段树(Segment Tree)是一种用于处理区间查询和更新问题的数据结构,特别是在需要对连续区间进行操作时非常有效。线段树可以快速地对区间求和、求最小值/最大值、判断某个值的存在性等问题进行响应。

线段树的特点:

  1. 高效性:线段树能够在对数时间内完成区间查询和更新操作。
  2. 空间优化:线段树通过节点合并来避免不必要的重复计算,节省了空间。
  3. 适用性:适用于需要对区间数据进行多次查询和更新的场景。

线段树的基本操作:

  1. 构建(Build):从给定的数据数组出发,递归地构建线段树。
  2. 查询(Query):根据给定的区间,在线段树中查找对应的合并结果。
  3. 更新(Update):更新线段树中的某个位置的值,并递归地更新所有受影响的祖先节点。

线段树的Java实现:

class SegmentTree {
    private int[] tree;
    private int n;

    public SegmentTree(int[] nums) {
        if (nums.length > 0) {
            n = nums.length;
            tree = new int[n * 4];
            build(nums, 0, 0, n - 1);
        }
    }

    private void build(int[] nums, int treeIndex, int left, int right) {
        if (left == right) {
            tree[treeIndex] = nums[left];
            return;
        }
        int mid = left + (right - left) / 2;
        build(nums, 2 * treeIndex + 1, left, mid);
        build(nums, 2 * treeIndex + 2, mid + 1, right);
        tree[treeIndex] = tree[2 * treeIndex + 1] + tree[2 * treeIndex + 2];
    }

    public int query(int left, int right) {
        return query(0, 0, n - 1, left, right);
    }

    private int query(int treeIndex, int start, int end, int left, int right) {
        if (left > end || start > end) {
            return 0;
        }
        if (start >= left && end <= right) {
            return tree[treeIndex];
        }
        int mid = start + (end - start) / 2;
        return query(2 * treeIndex + 1, start, mid, left, right) +
               query(2 * treeIndex + 2, mid + 1, end, left, right);
    }

    public void update(int index, int val) {
        update(0, 0, n - 1, index, val);
    }

    private void update(int treeIndex, int start, int end, int index, int val) {
        if (start == end) {
            tree[treeIndex] = val;
            return;
        }
        int mid = start + (end - start) / 2;
        if (index <= mid) {
            update(2 * treeIndex + 1, start, mid, index, val);
        } else {
            update(2 * treeIndex + 2, mid + 1, end, index, val);
        }
        tree[treeIndex] = tree[2 * treeIndex + 1] + tree[2 * treeIndex + 2];
    }
}

线段树的应用场景:

  1. 区间求和:快速计算给定区间内的元素和。
  2. 区间最小/最大值:查找给定区间内的最小值或最大值。
  3. 区间更新:更新某个区间内的元素值。
  4. 二维线段树:解决二维平面上的区间问题,如矩形区域的查询和更新。

面试大厂题示例:

  1. 区间求和
    描述:给定一个整数数组和一个区间列表,对于每个区间,计算其内所有元素的和。
    示例

    输入: nums = [1, 3, 5, 7, 9, 11], intervals = [[1, 3], [2, 5], [1, 1]]
    输出: [16, 15, 3]
    
  2. 区间最小值
    描述:给定一个整数数组和一个区间列表,对于每个区间,找到其中的最小值。
    示例

    输入: nums = [3, 4, 5, 1, 6, 2], intervals = [[2, 3], [1, 3], [0, 5]]
    输出: [5, 1, 2]
    
  3. 区间更新
    描述:给定一个整数数组和一个更新操作列表,对于每个更新操作,将其应用到数组的指定区间。
    示例

    输入: nums = [1, 3, 5, 7, 9, 11], updates = [[1, 2, 10], [3, 4, 20], [5, 5, 30]]
    输出: [10, 13, 15, 30, 9, 11]
    

这些题目和源码展示了线段树在解决实际问题中的应用。在面试中,能够根据问题的特点选择合适的算法并实现其解决方案是非常重要的。希望这些示例能够帮助你更好地准备面试!线段树是一种高效的数据结构,特别适合处理区间查询和更新问题。以下是三道可能出现在大厂面试中的与线段树相关的编程题目,以及相应的Java源码实现。

题目 1:区间求和

描述
给定一个整数数组和一个区间列表,对于每个区间,计算其内所有元素的和。

示例

输入: nums = [1, 3, 5, 7, 9, 11], intervals = [[1, 3], [2, 5], [1, 1]]
输出: [16, 15, 3]

Java 源码

public class IntervalSumQuery {
    private int[] tree;
    private int n;

    public IntervalSumQuery(int[] nums) {
        n = nums.length;
        tree = new int[n * 4];
        buildTree(nums, 0, 0, n - 1);
    }

    private void buildTree(int[] nums, int treeIndex, int start, int end) {
        if (start == end) {
            tree[treeIndex] = nums[start];
            return;
        }
        int mid = start + (end - start) / 2;
        buildTree(nums, 2 * treeIndex + 1, start, mid);
        buildTree(nums, 2 * treeIndex + 2, mid + 1, end);
        tree[treeIndex] = tree[2 * treeIndex + 1] + tree[2 * treeIndex + 2];
    }

    public int query(int start, int end) {
        return query(0, 0, n - 1, start, end);
    }

    private int query(int treeIndex, int start, int end, int qStart, int qEnd) {
        if (qStart > qEnd || start > qEnd || end < qStart) {
            return 0;
        }
        if (start >= qStart && end <= qEnd) {
            return tree[treeIndex];
        }
        int mid = start + (end - start) / 2;
        int left = query(2 * treeIndex + 1, start, mid, qStart, qEnd);
        int right = query(2 * treeIndex + 2, mid + 1, end, qStart, qEnd);
        return left + right;
    }

    public static void main(String[] args) {
        IntervalSumQuery query = new IntervalSumQuery(new int[]{1, 3, 5, 7, 9, 11});
        int[] intervals = {{1, 3}, {2, 5}, {1, 1}};
        int[] results = new int[intervals.length];
        for (int i = 0; i < intervals.length; i++) {
            results[i] = query.intervalSumQuery(intervals[i][0], intervals[i][1]);
            System.out.println("Sum of interval " + Arrays.toString(intervals[i]) + ": " + results[i]);
        }
    }
}

题目 2:区间最小值

描述
给定一个整数数组和一个区间列表,找到每个区间内的最小值。

示例

输入: nums = [3, 4, 5, 1, 6, 2], intervals = [[2, 3], [1, 3], [0, 5]]
输出: [5, 1, 2]

Java 源码

public class IntervalMinQuery {
    private int[] tree;
    private int n;

    public IntervalMinQuery(int[] nums) {
        n = nums.length;
        tree = new int[n * 4];
        buildTree(nums, 0, 0, n - 1);
    }

    private void buildTree(int[] nums, int treeIndex, int start, int end) {
        if (start == end) {
            tree[treeIndex] = nums[start];
            return;
        }
        int mid = start + (end - start) / 2;
        buildTree(nums, 2 * treeIndex + 1, start, mid);
        buildTree(nums, 2 * treeIndex + 2, mid + 1, end);
        tree[treeIndex] = Math.min(tree[2 * treeIndex + 1], tree[2 * treeIndex + 2]);
    }

    public int query(int start, int end) {
        return query(0, 0, n - 1, start, end);
    }

    private int query(int treeIndex, int start, int end, int qStart, int qEnd) {
        if (qStart > qEnd || start > qEnd || end < qStart) {
            return Integer.MAX_VALUE;
        }
        if (start >= qStart && end <= qEnd) {
            return tree[treeIndex];
        }
        int mid = start + (end - start) / 2;
        int left = query(2 * treeIndex + 1, start, mid, qStart, qEnd);
        int right = query(2 * treeIndex + 2, mid + 1, end, qStart, qEnd);
        return Math.min(left, right);
    }

    public static void main(String[] args) {
        IntervalMinQuery query = new IntervalMinQuery(new int[]{3, 4, 5, 1, 6, 2});
        int[] intervals = {{2, 3}, {1, 3}, {0, 5}};
        int[] results = new int[intervals.length];
        for (int i = 0; i < intervals.length; i++) {
            results[i] = query.intervalMinQuery(intervals[i][0], intervals[i][1]);
            System.out.println("Minimum of interval " + Arrays.toString(intervals[i]) + ": " + results[i]);
        }
    }
}

题目 3:区间更新

描述
给定一个整数数组和一个更新操作列表,对于每个更新操作,将其应用到数组的指定区间。

示例

输入: nums = [1, 3, 5, 7, 9, 11], updates = [[1, 2, 10], [3, 4, 20], [5, 5, 30]]
输出: [10, 13, 15, 30, 9, 11]

Java 源码

public class IntervalUpdate {
    private int[] tree;
    private int n;

    public IntervalUpdate(int[] nums) {
        n = nums.length;
        tree = new int[n * 4];
        buildTree(nums, 0, 0, n - 1);
    }

    private void buildTree(int[] nums, int treeIndex, int start, int end) {
        if (start == end) {
            tree[treeIndex] = nums[start];
            return;
        }
        int mid = start + (end - start) / 2;
        buildTree(nums, 2 * treeIndex + 1, start, mid);
        buildTree(nums, 2 * treeIndex + 2, mid + 1, end);
        tree[treeIndex] = tree[2 * treeIndex + 1] + tree[2 * treeIndex + 2];
    }

    public void update(int start, int end, int val) {
        update(0, 0, n - 1, start, end, val);
    }

    private void update(int treeIndex, int start, int end, int qStart, int qEnd, int val) {
        if (qStart > qEnd || start > qEnd || end < qStart) {
            return;
        }
        if (start >= qStart && end <= qEnd) {
            tree[treeIndex] = val;
            return;
        }
        int mid = start + (end - start) / 2;
        update(2 * treeIndex + 1, start, mid, qStart, qEnd, val);
        update(2 * treeIndex + 2, mid + 1, end, qStart, qEnd, val);
        tree[treeIndex] = tree[2 * treeIndex + 1] + tree[2 * treeIndex + 2];
    }

    public static void main(String[] args) {
        IntervalUpdate update = new IntervalUpdate(new int[]{1, 3, 5, 7, 9, 11});
        int[][] updates = {{1, 2, 10}, {3, 4, 20}, {5, 5, 30}};
        for (int[] update : updates) {
            update.update(update[0], update[1], update[2]);
            System.out.println("Array after update " + Arrays.toString(update) + ": " + Arrays.toString(update.getArray()));
        }
    }
}

这些题目和源码展示了线段树在解决实际问题中的应用。在面试中,能够根据问题的特点选择合适的算法并实现其解决方案是非常重要的。希望这些示例能够帮助你更好地准备面试!文章来源地址https://www.toymoban.com/news/detail-849046.html

到了这里,关于Java线段树(含面试大厂题和源码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Segment Tree 线段树算法(java)

    什么是线段树算法: 线段树(Segment Tree)是一种基于树结构的数据结构,用于解决区间查询问题,例如区间最大值、最小值、区间和等。线段树是一种高度平衡的二叉树,每个节点都代表了一个区间。下面我们来详细了解一下线段树算法。 线段树的构建 线段树的构建过程可

    2024年02月16日
    浏览(28)
  • 【大厂Java面试题】简问简答篇

    什么是Java中的内存模型(Memory Model)?请解释一下主内存(Main Memory)和工作内存(Working Memory)的概念。 答:Java内存模型定义了多线程程序中共享变量的访问规则。主内存是所有线程共享的内存区域,而工作内存是每个线程独享的内存区域。 说说Java中的垃圾回收(Garbag

    2024年02月20日
    浏览(29)
  • 2023Java岗面试,进互联网大厂必备Java面试八股文真题解析

    前言 一般技术面试官都会通过自己的方式去考察程序员的技术功底与基础理论知识。 很多时候,面试官问的问题会和自己准备的“题库”中的问题不太一样,即使做了复盘,下次面试还是不知道该从何处下手。 为此鄙人软磨硬泡才把阿里P8专门归纳整理的 《Java进阶知识典藏

    2023年04月10日
    浏览(46)
  • 2023Java 岗面试,进互联网大厂必备 Java 面试八股文真题解析

    前言 一般技术面试官都会通过自己的方式去考察程序员的技术功底与基础理论知识。 很多时候,面试官问的问题会和自己准备的“题库”中的问题不太一样,即使做了复盘,下次面试还是不知道该从何处下手。 为此鄙人软磨硬泡才把阿里 P8 专门归纳整理的 《Java 进阶知识典

    2024年02月15日
    浏览(36)
  • 大厂面试题一文讲通jvm,Java虚拟机高频面试题

    薪资范围:6-16K 一个类完整的生命周期,会经历五个阶段,分别为: 加载、连接、初始化、使用 、和 卸载 。其中的连接又分为 验证、准备 和 解析 三个步骤。如下图所示 加载(Loading) 简单一句话概括,类的加载阶段就是: 找到需要加载的类并把类的信息加载到jvm的方法

    2024年01月18日
    浏览(33)
  • Java 大厂面试 —— 常见集合篇 List HashMap 红黑树

    23Java面试专题 八股文面试全套真题(含大厂高频面试真题)多线程_软工菜鸡的博客-CSDN博客 02-算法复杂度分析 2.1 数组 2.1.1 数组概述 数组(Array)是一种用 连续的内存空间 存储 相同数据类型 数据的线性数据结构。 我们定义了这么一个数组之后,在内存的表示是这样的:

    2024年02月11日
    浏览(44)
  • 大厂HR经常会问到的Java线程池面试题

    一、什么是线程池         线程池和数据库连接池非常类似,可以统一管理和维护线程,减少没有必要的开销。 二、为什么要使用线程池         因为在项目开发过程中频繁的开启线程或者停止线程,线程需要重新被CPU从就绪状态调度到运行状态,需要发生CPU的上下

    2024年02月14日
    浏览(26)
  • 字节跳动大厂面试题详解:java中有哪些类型的锁

    作者简介 :一名后端开发人员,每天分享后端开发以及人工智能相关技术,行业前沿信息,面试宝典。 座右铭 :未来是不可确定的,慢慢来是最快的。 个人主页 :极客李华-CSDN博客 合作方式 :私聊+ 这个专栏内容 :BAT等大厂常见后端java开发面试题详细讲解,更新数目10

    2024年02月21日
    浏览(34)
  • 2023互联网大厂最全Java面试八股文(附大厂 P5-P8 技术栈)

    为什么感觉 Java 面试变难了? 几年前,你只需要简单的 ssm 框架 ,就能轻松找到一份 Java 的工作,但现在不一样了,随着涌入这个行业的人越来越多,同一个岗位需要筛选掉更多人,要求自然水涨船高, 这也就是现在越来越多 Java 程序员抱怨行业越来越卷的原因 ,当然这个

    2024年02月15日
    浏览(38)
  • 大厂最全1100道Java面试题及答案整理(2023最新版)

    春招,秋招,社招,我们 Java 程序员的面试之路,是挺难的,过了 HR,还得被技术面,小刀在去各个厂面试的时候,经常是通宵睡不着觉,头发都脱了一大把,还好最终侥幸能够入职一个独角兽公司,安稳从事喜欢的工作至今... 近期也算是抽取出大部分休息的时间,为大家准

    2024年02月09日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包