首页 > 编程语言 >每日算法一练:剑指offer——数组篇(7)

每日算法一练:剑指offer——数组篇(7)

时间:2024-10-31 20:49:30浏览次数:6  
标签:target places offer int 复杂度 数组 算法 朝代

1.文物朝代确认

        展览馆展出来自 13 个朝代的文物,每排展柜展出 5 个文物。某排文物的摆放情况记录于数组 places,其中 places[i] 表示处于第 i 位文物的所属朝代编号。其中,编号为 0 的朝代表示未知朝代。请判断并返回这排文物的所属朝代编号是否能够视为连续的五个朝代(如遇未知朝代可算作连续情况)。

示例 1:

输入: places = [0, 6, 9, 0, 7]
输出: True

示例 2:

输入: places = [7, 8, 9, 10, 11]
输出: True

        这道题要求判断 5 个展出朝代是否能看作是连续的朝代编号,允许出现“未知朝代”的编号 0。在解题时,我们可以利用两个思路来判断是否满足连续条件:

  1. 除未知朝代外的朝代编号无重复
  2. 最大编号朝代与最小编号朝代的差小于 5

1.1使用辅助哈希表

解题思路

  • 使用哈希表 (Set) 来存储非 0 的朝代编号,以便检查重复。
  • 记录最大编号朝代和最小编号朝代,如果满足 max - min < 5,则表示编号是连续的。

算法流程

  1. 初始化 Set<Integer> repeat 用于存放非 0 编号的朝代,max 用于记录最大朝代编号,min 用于记录最小朝代编号。
  2. 遍历 places 数组:
    • 遇到 0 表示未知朝代,直接跳过。
    • 更新 maxmin
    • 如果 repeat 中已包含当前朝代编号,说明出现重复,直接返回 false
    • 否则,将当前朝代编号加入 repeat
  3. 遍历结束后,检查 max - min < 5 是否成立,如果成立,返回 true,否则返回 false

代码示例

class Solution {
    public boolean checkDynasty(int[] places) {
        Set<Integer> repeat = new HashSet<>();
        int max = 0, min = 14;
        for (int place : places) {
            if (place == 0) continue; // 跳过未知朝代
            max = Math.max(max, place); // 更新最大编号朝代
            min = Math.min(min, place); // 更新最小编号朝代
            if (repeat.contains(place)) return false; // 若有重复,提前返回 false
            repeat.add(place); // 添加此朝代至 Set
        }
        return max - min < 5; // 判断是否连续
    }
}

复杂度分析

  • 时间复杂度:O(1)。遍历固定长度 5 的数组,复杂度为 O(5) = O(1)。
  • 空间复杂度:O(1)。哈希表最多存储 5 个元素,空间复杂度为 O(1)。

1.2排序+遍历        

解题思路

  • 先对数组排序,使重复的元素变得相邻,便于检测重复朝代。
  • 排序后可以很方便地找到最大值和最小值(排除未知朝代后)。
  • 最后通过 max - min < 5 来判断是否连续。

算法流程

  1. places 数组进行排序。
  2. 遍历排序后的数组:
    • 统计未知朝代的数量。
    • 如果出现两个相同的非 0 编号,直接返回 false
  3. 遍历结束后,判断 places[4] - places[unknown] < 5 是否成立,如果成立,返回 true,否则返回 false

代码示例

class Solution {
    public boolean checkDynasty(int[] places) {
        int unknown = 0;
        Arrays.sort(places); // 数组排序
        for (int i = 0; i < 4; i++) {
            if (places[i] == 0) unknown++; // 统计未知朝代数量
            else if (places[i] == places[i + 1]) return false; // 若有重复,提前返回 false
        }
        return places[4] - places[unknown] < 5; // 判断是否连续
    }
}

复杂度分析

  • 时间复杂度:O(1)。排序和遍历 5 个元素,复杂度为 O(5 log 5) + O(5) = O(1)。
  • 空间复杂度:O(1)。仅使用固定大小的变量 unknown

2.设计机械累计器

        请设计一个机械累加器,计算从 1、2... 一直累加到目标数值 target 的总和。注意这是一个只能进行加法操作的程序,不具备乘除、if-else、switch-case、for 循环、while 循环,及条件判断语句等高级功能。

示例 1:

输入: target = 5
输出: 15

示例 2:

输入: target = 7
输出: 28

提示:

  • 1 <= target <= 10000

2.1短路效应

解题思路

        在这个问题中,由于有许多限制条件(例如禁止使用乘法、循环和条件判断),我们只能通过递归和短路效应来实现目标。

  1. 平均计算:使用公式 (1+target)×target/2是不可行的,因为涉及乘除法。

  2. 迭代方法:使用循环结构(如 for 或 while)也被排除。

  3. 递归方法:使用递归进行累加是可行的,但我们需要处理递归的终止条件,而不直接使用 if 语句。

        通过逻辑运算符的短路效应,我们可以实现当 target = 1 时停止递归:

  • target > 1 时,我们继续递归调用 mechanicalAccumulator(target - 1)
  • target = 1 时,target > 1 不成立,短路效果使得后续的递归调用不再执行,从而达到了停止条件。

复杂度分析

  • 时间复杂度:O(target)
    • 每次递归调用都会处理一个目标值,直到 target 减至 1,总共进行 target 次递归。
  • 空间复杂度:O(target)
    • 递归的深度为 target,因此需要 O(target) 的栈空间。

代码实现:

class Solution {
    int res = 0;

    public int mechanicalAccumulator(int target) {
        // 使用短路效应进行递归
        boolean x = target > 1 && mechanicalAccumulator(target - 1) > 0;
        res += target; // 每次累加目标值
        return res; // 返回当前累加和
    }
}

代码说明

  • res 变量用于记录累加的结果。
  • mechanicalAccumulator 方法中,通过逻辑与运算符的短路特性判断 target > 1
  • 递归调用会在 target 递减到 1 时停止继续调用,最终将所有值累加到 res 中。

3.按规则计算统计结果

        为了深入了解这些生物群体的生态特征,你们进行了大量的实地观察和数据采集。数组 arrayA 记录了各个生物群体数量数据,其中 arrayA[i] 表示第 i 个生物群体的数量。请返回一个数组 arrayB,该数组为基于数组 arrayA 中的数据计算得出的结果,其中 arrayB[i] 表示将第 i 个生物群体的数量从总体中排除后的其他数量的乘积。

示例 1:

输入:arrayA = [2, 4, 6, 8, 10]
输出:[1920, 960, 640, 480, 384]

提示:

  • 所有元素乘积之和不会溢出 32 位整数
    • arrayA.length <= 100000

解题思路

我们需要计算一个数组 arrayA 中每个元素排除后的其他元素的乘积,生成新数组 arrayB。为了不使用除法,我们可以利用数组的上下三角结构来计算。

根据题目中 B[i] 的定义,我们可以将其视作一个矩阵,其中主对角线的值为1。这个矩阵可以分为上三角和下三角两部分。我们可以分别计算这两个部分的乘积并相乘,从而得到结果。

算法流程

  1. 初始化

    • 创建结果数组 B,并设置 B[0] = 1
    • 初始化一个辅助变量 tmp 为 1,用于存储上三角的乘积。
  2. 计算下三角乘积

    • 从左到右遍历数组 A,更新 B[i]
      • 对于每个 i,将 B[i] 设为 B[i-1] 乘以 arrayA[i-1],计算下三角的乘积。
  3. 计算上三角乘积

    • 从右到左遍历数组 A
      • 对于每个 i,将 tmp 乘以 arrayA[i+1],然后将 tmp 乘入 B[i],计算上三角的乘积。
  4. 返回结果

    • 返回数组 B

复杂度分析

  • 时间复杂度:O(N),其中 N 是数组的长度。我们对数组 A 进行了两轮遍历。
  • 空间复杂度:O(1),我们只使用了常数大小的额外空间(辅助变量 tmp),而 B 数组不计入复杂度分析。

代码示例

下面是对应的 Java 代码实现:

class Solution {
    public int[] statisticalResult(int[] arrayA) {
        int len = arrayA.length;
        if (len == 0) return new int[0];
        
        int[] arrayB = new int[len];
        arrayB[0] = 1; // 初始化 B[0] 为 1
        int tmp = 1; // 辅助变量
        
        // 计算下三角乘积
        for (int i = 1; i < len; i++) {
            arrayB[i] = arrayB[i - 1] * arrayA[i - 1];
        }
        
        // 计算上三角乘积
        for (int i = len - 2; i >= 0; i--) {
            tmp *= arrayA[i + 1];
            arrayB[i] *= tmp;
        }
        
        return arrayB; // 返回结果数组
    }
}

这个代码实现了我们的思路,首先初始化 arrayB,然后通过两轮遍历计算上下三角的乘积,最后返回结果。

标签:target,places,offer,int,复杂度,数组,算法,朝代
From: https://blog.csdn.net/m0_53926113/article/details/143402802

相关文章

  • 数组排序简介-计数排序(Counting Sort)
    基本思想        通过统计数组中每个元素在数组中出现的次数,根据这些统计信息将数组元素有序的放置到正确位置,从而达到排序的目的。算法步骤计算排序范围:遍历数组,找出待排序序列中最大值元素 nums_max和最小值元素 nums_min,计算出排序范围为 nums_max−nums_min......
  • 数组排序简介-快速排序(Quick Sort)
    基本思想        采用经典的分治策略,选择数组中某个元素作为基准数,通过一趟排序将数组分为独立的两个子数组,一个子数组中所有元素值都比基准数小,另一个子数组中所有元素值都比基准数大。然后再按照同样的方式递归的对两个子数组分别进行快速排序,以达到整个数组有序。......
  • [SCOI2014] 方伯伯的玉米田(树状数组优化 DP)
     loj传送门https://loj.ac/p/2211洛谷题目传送门https://www.luogu.com.cn/problem/P3287解题思路首先,我们可以贪心地思考一下:对于每一次区间的加一操作,右端点是在末尾会比右端点在中间的情况更好。因为,当你的右端点在序列中间的时候,相对之下,后面的数就更小了一些,这样是......
  • 常用算法模板
    数论组合数方法1(小数据)数据范围\(1\leqn\leq10000\),\(1\leqb\leqa\leq2000\)说明通过递推预处理组合数公式\(C^{b}_{a}=C^{b}_{a-1}+C^{b-1}_{a-1}\)LLC[N][N];voidinit(){for(inti=0;i<N;i++){for(intj=0;j<=......
  • 108-二叉树-将有序数组转换为二叉搜索树
    树|二叉搜索树|数组|分治|二叉树二叉搜索树(BinarySearchTree,简称BST)和平衡二叉搜索树(BalancedBinarySearchTree)是计算机科学中非常重要的数据结构,广泛应用于各种算法和系统中。理解它们的定义、特点和性质对于掌握数据结构和算法至关重要。下面,我们将详细......
  • 【算法笔记】位运算算法原理深度剖析
    【算法笔记】位运算算法原理深度剖析......
  • Python深度学习进阶与前沿应用(注意力机制详解、生成式模型详解、自监督学习模型详解、
    近年来,伴随着以卷积神经网络(CNN)为代表的深度学习的快速发展,人工智能迈入了第三次发展浪潮,AI技术在各个领域中的应用越来越广泛。注意力机制、Transformer模型(BERT、GPT-1/2/3/3.5/4、DETR、ViT、SwinTransformer等)、生成式模型(变分自编码器VAE、生成式对抗网络GAN、扩散模型Di......
  • bellman_ford算法原理
    是什么松弛在《算法四》中,对松弛的解释是:relaxtheedge,看起来比较抽象,不过如果我们从生活中的实例去理解,就简单多了:试想一根绳索,当你握着绳索的两头使劲用力拉伸时,绳子紧绷,长度会变长;而当你减小用力时,绳子松弛,长度会变短。当你没有用任何力时,此时绳子的长度最短。这里当用力减......
  • 非煤矿山算法智慧矿山一体机皮带跑偏识别非煤矿山监控系统对提升生产效率有哪些帮助?
    在当今这个科技迅猛发展的时代,各个行业都在积极寻求通过智能化转型来提升工作效率、确保作业安全和优化资源配置。非煤矿山行业,作为国家经济的重要组成部分,同样承受着技术革新和安全管理的双重压力。在这一背景下,引入非煤矿山算法智慧矿山一体机对提高非煤矿山的安全监管能力、预......
  • AI智能分析视频分析网关区域人数不足检测算法:智能监控的新篇章
    在当今社会快速发展的背景下,公共场所如购物中心、交通枢纽、教育机构等地的人群聚集现象越来越普遍。如何高效地管理和控制这些区域的人流,保障安全的同时提升服务水平,成为一个迫切需要解决的挑战。传统的人流统计方法,例如人工计数或基础的传感器技术,常常因效率低和准确度不足而受......