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

C语言 | Leetcode C语言题解之第327题区间和的个数

题目:

题解:

#define FATHER_NODE(i)      (0 == (i) ? -1 : ((i) - 1 >> 1))
#define LEFT_NODE(i)        (((i) << 1) + 1)
#define RIGHT_NODE(i)       (((i) << 1) + 2)/* 优先队列(小根堆)。 */
typedef struct
{int *arr;int arrSize;
}
PriorityQueue;/* 二进制树(01字典树)。 */
typedef struct
{int *arr;int highestBit;
}
BinaryTree;/* 几个自定义函数的声明,具体实现见下。 */
static void queuePush(PriorityQueue *queue, long long *prefix, int x);
static void queuePop(PriorityQueue *queue, long long *prefix);
static int treeHighestBit(int mostVal);
static void treePush(BinaryTree *tree, int x);
static void treePop(BinaryTree *tree, int x);
static int treeSmaller(BinaryTree *tree, int x);/* 主函数:treeSize:         二进制树的数组空间大小,等于里面最大值的3倍,具体证明略,大致就是等比数列求和的结果。prefix[]:         其中prefix[x]表示[0, x]范围内子数组的前缀和。这里必须以long long类型存储。window[]:         里面存储prefix[]数组的下标,即prefix[window[x]]才真正表示一个前缀和。buff1[],buff2[]:  优先队列与二进制树各自使用的数组空间。其中buff2[]必须初始化为全0。queue:            优先队列(小根堆),为了不打乱prefix[]数组中的数值顺序,而且window[]数组中实际存放的是下标,所以借用堆排序。tree:             二进制树(01字典树)。 */
int countRangeSum(int *nums, int numsSize, int lower, int upper)
{const int treeSize = numsSize * 3;int x = 0, y = 0, z = 0, t = 0, result = 0;long long sum = 0;long long prefix[numsSize];int window[numsSize], buff1[numsSize], buff2[treeSize];PriorityQueue queue;BinaryTree tree;/* 初始化。 */queue.arr = buff1;queue.arrSize = 0;memset(buff2, 0, sizeof(buff2));tree.arr = buff2;tree.highestBit = treeHighestBit(numsSize - 1);/* 计算前缀和,并将前缀和的下标放到一个小根堆里面,小根堆里面以对应的前缀和为优先级。 */for(x = 0; numsSize > x; x++){sum += nums[x];prefix[x] = sum;queuePush(&queue, prefix, x);/* 如果[0, x]的子数组和本来就在[lower, upper]之间,计数累计。 */if((long long)lower <= sum && (long long)upper >= sum){result++;}}/* 将前缀和数组的下标,以对应的prefix值从小到大的顺序,放到window数组中。 */while(0 < queue.arrSize){window[t] = queue.arr[0];t++;queuePop(&queue, prefix);}/* 开始以滑动窗口的形式移动窗口的左右指针。 */for(x = 0; numsSize > x; x++){/* 将所有prefix[window[x]] - prefix[window[y]] >= lower的下标y都加入。 */while(numsSize > y && prefix[window[x]] - lower >= prefix[window[y]]){treePush(&tree, window[y]);y++;}/* 将所有prefix[window[x]] - prefix[window[z]] > upper的下标z都移除。 */while(numsSize > z && prefix[window[x]] - upper > prefix[window[z]]){treePop(&tree, window[z]);z++;}/* 将窗口内(树内)剩余的下标值中,小于window[x]的数量加到结果中。 */t = treeSmaller(&tree, window[x]);result += t;}return result;
}/* 小根堆的push操作。由于堆中存储的是prefix[]数组的下标,所以入参需带上prefix。 */
static void queuePush(PriorityQueue *queue, long long *prefix, int x)
{int son = queue->arrSize, father = FATHER_NODE(son);/* 新加入数值之后,数量加一。 */queue->arrSize++;/* 根据对应prefix[]值的大小关系,调整父子节点的位置。 */while(-1 != father && prefix[x] < prefix[queue->arr[father]]){queue->arr[son] = queue->arr[father];son = father;father = FATHER_NODE(son);}/* 放到实际满足父子节点大小关系的位置。 */queue->arr[son] = x;return;
}/* 小根堆的pop操作。由于堆中存储的是prefix[]数组的下标,所以入参需带上prefix。 */
static void queuePop(PriorityQueue *queue, long long *prefix)
{int father = 0, left = LEFT_NODE(father), right = RIGHT_NODE(father), son = 0;/* 堆顶pop之后,数量减一。默认将堆尾的数值补充上来填补空位。 */queue->arrSize--;/* 根据对应prefix[]值的大小关系,调整父子节点的位置。 */while((queue->arrSize > left && prefix[queue->arr[queue->arrSize]] > prefix[queue->arr[left]])|| (queue->arrSize > right && prefix[queue->arr[queue->arrSize]] > prefix[queue->arr[right]])){son = (queue->arrSize > right && prefix[queue->arr[left]] > prefix[queue->arr[right]]) ? right : left;queue->arr[father] = queue->arr[son];father = son;left = LEFT_NODE(father);right = RIGHT_NODE(father);}/* 放到实际满足父子节点大小关系的位置。 */queue->arr[father] = queue->arr[queue->arrSize];return;
}/* 计算二进制树中,可能出现的最大的数值,所占据的最高二进制比特。比如,最大值的二进制是101100(b),那么返回的最高比特是100000(b)。特殊的,最大是0的时候返回1(b)。 */
static int treeHighestBit(int mostVal)
{int x = 1;if(0 < mostVal){while(0 < mostVal){x++;mostVal = mostVal >> 1;}x = 1 << x - 2;}return x;
}/* 往二进制树中push一个数值。 */
static void treePush(BinaryTree *tree, int x)
{int i = 0, bit = tree->highestBit;/* 从最高位到最低位的顺序,该位为1就给右分支加1,为0就给左分支加1。 */while(0 < bit){i = (bit & x) ? RIGHT_NODE(i) : LEFT_NODE(i);tree->arr[i]++;bit = bit >> 1;}return;
}/* 从二进制树中pop一个数值。 */
static void treePop(BinaryTree *tree, int x)
{int i = 0, bit = tree->highestBit;/* 从最高位到最低位的顺序,该位为1就给右分支减1,为0就给左分支减1。 */while(0 < bit){i = (bit & x) ? RIGHT_NODE(i) : LEFT_NODE(i);tree->arr[i]--;bit = bit >> 1;}return;
}/* 在二进制树中查找比输入数值小的数值数量。 */
static int treeSmaller(BinaryTree *tree, int x)
{int i = 0, bit = tree->highestBit, result = 0;/* 从高位到低位的顺序查看。 */while(0 < bit){/* 该位为1,则肯定比高位相同,该位为0的数值更大,即把左分支的数量加到结果中。 */if(bit & x){result += tree->arr[LEFT_NODE(i)];i = RIGHT_NODE(i);}/* 该位为0,就往左分支走,不做任何其它处理。 */else{i = LEFT_NODE(i);}bit = bit >> 1;}return result;
}

相关文章:

C语言 | Leetcode C语言题解之第327题区间和的个数

题目&#xff1a; 题解&#xff1a; #define FATHER_NODE(i) (0 (i) ? -1 : ((i) - 1 >> 1)) #define LEFT_NODE(i) (((i) << 1) 1) #define RIGHT_NODE(i) (((i) << 1) 2)/* 优先队列&#xff08;小根堆&#xff09;。 */ typedef s…...

统计学:条件概率模型

照片由Edge2Edge Media在Unsplash上拍摄 一、介绍 在概率的许多应用中&#xff0c;不可能直接观察实验的结果&#xff1b;而是观察与结果相关的事件。因此&#xff0c;条件概率模型对于考虑和利用从观察到的事件中获得的信息至关重要。此外&#xff0c;条件概率模型与贝叶斯定理…...

前端工程师学习springboot2.x之配置idea热更新实现高效率开发节奏

目前已经学习springboot实现了增删改查分页查询&#xff0c;每次修改业财或者是代码重启项目都让我觉得很闹心&#xff0c;现在给出idea2021版本自带热更新操作设置&#xff0c;设置过程分享给大家 总结&#xff1a;以上就是配置的全部过程&#xff0c;祝大家写代码快乐…...

文本rerank与图像rerank

1、文本rerank&#xff1a; 这里介绍的是目前比较流行和通用一套方案&#xff1a;先利用特征检索&#xff08;这里是特征空间上的相似度&#xff09;&#xff0c;召回相关信息&#xff0c;然后对query与召回的相关信息进行rerank&#xff08;这里是利用cross-encoder网络做一个…...

Docker 在 Windows 系统下的使用指南:数据卷和数据库

Docker 在 Windows 系统下的使用指南&#xff1a;数据卷和数据库 Docker 提供了强大的功能来创建、管理和持久化数据。数据卷是 Docker 中用于存储和管理数据的机制&#xff0c;使得数据能够在容器的生命周期之外持久化。数据库容器可以利用数据卷来持久化数据库文件&#xff…...

[数据集][目标检测]轴承缺陷划痕检测数据集VOC+YOLO格式1166张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1166 标注数量(xml文件个数)&#xff1a;1166 标注数量(txt文件个数)&#xff1a;1166 标注…...

将本地微服务发布到docker镜像二:

上一篇文章我们介绍了如何将一个简单的springboot服务发布到docker镜像中&#xff0c;这一篇我们将介绍如何将一个复杂的微服务&#xff08;关联mysql、redis&#xff09;发布到docker镜像。 我们将使用以下两种不同的方式来实现此功能。 redis、mysql、springboot微服务分开…...

前端构建工具|vite快速入门

认识vite vite组成部分 Vite是一种新型前端构建工具&#xff0c;能够显著提升前端开发体验。它主要由两部分组成&#xff1a; 一个开发服务器&#xff0c;它基于 原生 ES 模块 提供了 丰富的内建功能&#xff0c;如速度快到惊人的 模块热更新&#xff08;HMR&#xff09;。一…...

拯救PyCharm:击退IDE内存泄漏的策略

拯救PyCharm&#xff1a;击退IDE内存泄漏的策略 PyCharm&#xff0c;作为一款功能强大的集成开发环境&#xff08;IDE&#xff09;&#xff0c;在处理大型项目或长时间开发过程中&#xff0c;可能会遇到内存泄漏的问题&#xff0c;导致IDE运行缓慢甚至崩溃。本文将提供一系列解…...

在vue3的开发环境中为什么使用vite而不是用webpack

1、vite在开发阶段没有打包过程&#xff0c;直接启动一个服务器 2、请求一个模块到开发服务器 3、开发服务器编译模块&#xff0c;根据页面用所需要的依赖去加载文件 4、加载完成后&#xff0c;开发服务器把编译的结果返回给页面 这使得提高了我们在开发阶段运行的效率 vite是…...

mybatis结合generator进行分页插件PluginAdapter开发

mybatis结合generator生成的代码没有分页的功能&#xff0c;可以尝试自己继承分页插件PluginAdapter&#xff0c;进行开发&#xff0c;实现自己的分页插件这样generator生产的代码 带分页功能了。 MyBatis MySQL自动生成带分页插件 继承PluginAdapter类&#xff0c;实现相关方…...

面试:ArrayList和LinkedList

ArrayList和LinkedList是什么&#xff1f; ArrayList&#xff1a; ArrayList是Java集合框架中的一个类&#xff0c;它实现了List接口&#xff0c;底层基于数组实现。ArrayList的特点是支持动态数组&#xff0c;可以自动扩容&#xff0c;适合顺序访问和随机访问。LinkedList&am…...

【uniapp】uniapp+vue2微信小程序实现分享功能

uniappvue2做的微信小程序实现分享功能 问题描述 uniappvue2做的微信小程序&#xff0c;发布以后点击右上角三个点&#xff0c;分享小程序的时候&#xff0c;转发和分享按钮都是灰色 解决方案 转发、分享、复制链接这几个功能需要自己来手动写方法&#xff0c;考虑到每个页…...

WEB渗透Web突破篇-目录爆破

开源 工具名称下载地址工具描述cansinahttps://github.com/deibit/cansina网站的敏感目录发掘工具Cewlcewl | Kali Linux Tools你可以给它的爬虫指定URL地址和爬取深度&#xff0c;接下来Cewl会给你返回一个字典文件dirsearchhttps://github.com/maurosoria/dirsearch目录扫描…...

Windows设备文件同步平台

使用咨询: 扫码添加QQ 永久免费: Gitee下载最新版本 使用说明: CSDN查看使用说明 功能: 定时(全量采集or增量采集) SCADA,MES等系统采集工控机,办公电脑文件. 优势1: 开箱即用. 解压直接运行.插件集成下载. 优势2: 批管理设备. 配置均在后台配置管理. 优势3: 无人值守 采集端…...

用九方智投学习机,学会应对回撤风险

&#xff08;九方智投属于九方智投控股有限公司&#xff08;9636.HK&#xff09;旗下品牌&#xff09;      近期国内海风项目密集落地&#xff0c;行业景气度提升。2023年下半年以来&#xff0c;各省加快建设“十四五”规划&#xff0c;我国海风建设重新迈入快车道&#x…...

maven打包加入本地jar包

在使用maven打包的过程中&#xff0c;有时候我们需要添加一些本地的jar包&#xff0c;并将其打到jar包的lib中。 首先将需要本地的jar包&#xff0c;放到项目的的src/resources/lib下面。 然后在对应的项目的pom中加入一下依赖&#xff1a; <dependency><groupId>…...

从TiDB迁移到OceanBase的实践分享

本文来自OceanBase热心用户的分享 近期&#xff0c;我们计划将业务数据库从TiDB迁移到OceanBase&#xff0c;但面临的一个主要挑战是如何更平滑的完成这一迁移过程。经过研究&#xff0c;了解到OceanBase提供的OMS数据迁移工具能够支持从TiDB到OceanBase的迁移&#xff0c;并且…...

DL00765-光伏故障检测高分辨率无人机热红外图像细粒度含数据集4000+张

光伏发电作为清洁能源的重要组成部分&#xff0c;近年来得到了广泛应用。然而&#xff0c;随着光伏电站规模的扩大&#xff0c;光伏组件在运行过程中可能会出现各种故障&#xff0c;如热斑、遮挡、接线盒故障等。这些故障不仅会影响光伏电站的发电效率&#xff0c;还可能导致更…...

CICD流水线

一、CICD流水线简介 CICD概念 CI/CD流水线是现代软件开发的一个核心概念&#xff0c;它涉及自动化和管理软件从开发到部署的整个生命周期 概念定义 具体有三点&#xff1a;持续集成、持续交付、持续部署 流水线组成为&#xff1a;代码提交、测试、构建、部署、结果通知 二…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

云计算——弹性云计算器(ECS)

弹性云服务器&#xff1a;ECS 概述 云计算重构了ICT系统&#xff0c;云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台&#xff0c;包含如下主要概念。 ECS&#xff08;Elastic Cloud Server&#xff09;&#xff1a;即弹性云服务器&#xff0c;是云计算…...

练习(含atoi的模拟实现,自定义类型等练习)

一、结构体大小的计算及位段 &#xff08;结构体大小计算及位段 详解请看&#xff1a;自定义类型&#xff1a;结构体进阶-CSDN博客&#xff09; 1.在32位系统环境&#xff0c;编译选项为4字节对齐&#xff0c;那么sizeof(A)和sizeof(B)是多少&#xff1f; #pragma pack(4)st…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...

Xela矩阵三轴触觉传感器的工作原理解析与应用场景

Xela矩阵三轴触觉传感器通过先进技术模拟人类触觉感知&#xff0c;帮助设备实现精确的力测量与位移监测。其核心功能基于磁性三维力测量与空间位移测量&#xff0c;能够捕捉多维触觉信息。该传感器的设计不仅提升了触觉感知的精度&#xff0c;还为机器人、医疗设备和制造业的智…...

针对药品仓库的效期管理问题,如何利用WMS系统“破局”

案例&#xff1a; 某医药分销企业&#xff0c;主要经营各类药品的批发与零售。由于药品的特殊性&#xff0c;效期管理至关重要&#xff0c;但该企业一直面临效期问题的困扰。在未使用WMS系统之前&#xff0c;其药品入库、存储、出库等环节的效期管理主要依赖人工记录与检查。库…...