轩辕十四

探索科技与创新的个人博客

前言

队列(Queue)是一种遵循先进先出(FIFO,First In First Out)原则的线性数据结构。在 iOS 开发中,我们经常需要使用队列来处理各种场景,比如:任务调度、消息队列、事件处理等。

在上一篇文章《数据结构:循环数组详解》中,我们详细介绍了循环数组的原理。本文将基于实际项目中的代码,深入对比循环数组实现的队列链表实现的队列这两种方案,帮助你在实际开发中做出正确的选择。

阅读全文 »

什么是 MMap

MMap(Memory Mapping)是一种内存映射技术,它允许将文件或其他对象映射到进程的地址空间。在 iOS 开发中,mmap 是一个强大的系统调用,能够将磁盘文件的内容直接映射到内存地址空间,使得对文件的读写操作可以像访问内存一样简单高效。

与传统的文件 I/O(通过 read()/write() 系统调用)不同,mmap 通过虚拟内存机制,让应用程序可以像访问数组一样访问文件内容,操作系统会自动处理磁盘和内存之间的数据传输。

核心特点

  • 零拷贝:数据不需要在用户空间和内核空间之间复制
  • 延迟加载:只有真正访问数据时才从磁盘加载(页面调度)
  • 共享内存:多个进程可以映射同一文件实现进程间通信
  • 高效访问:随机访问文件时性能更优
阅读全文 »

什么是循环数组

循环数组(Circular Array),也称为环形数组或环形缓冲区(Ring Buffer),是一种特殊的数组结构。它在逻辑上将数组的首尾相连,形成一个环形结构。当数组索引到达末尾时,会自动回到数组的开头,实现循环访问。

循环数组的核心思想是:通过取模运算,让索引在固定范围内循环

为什么需要循环数组?

在传统的线性数组中,当我们需要在数组头部插入或删除元素时,需要移动大量元素,时间复杂度为 O(n)。而循环数组通过维护头尾指针,可以高效地在两端进行操作,实现 O(1) 的时间复杂度。

阅读全文 »

React Native 新架构简介

React Native 的新架构是为了解决旧架构中存在的性能瓶颈和开发体验问题而推出的重大升级。新架构主要包含以下几个核心组件:

  1. JSI (JavaScript Interface): 取代了旧架构中的 JSC (JavaScriptCore),提供了 JS 和原生代码之间的直接通信能力。
  2. Fabric: 新的渲染系统,通过 C++ 桥接层实现了更高效的 UI 渲染。
  3. TurboModules: 新的原生模块系统,允许更高效地调用原生 API。
  4. CodeGen: 自动代码生成工具,减少了手动编写样板代码的工作量。
  5. Hermes: Facebook 开发的专为移动应用优化的 JavaScript 引擎。

相比于旧架构,新架构最大的优势在于消除了异步桥接带来的性能损耗,允许 JavaScript 和原生代码直接通信,大幅提升了应用性能和开发体验。

阅读全文 »

给你一个链表,删除链表的倒数第 n 个结点,并且返回链表的头结点。

示例 1:

img

1
2
输入:head = [1,2,3,4,5], n = 2
输出:[1,2,3,5]

示例 2:

1
2
输入:head = [1], n = 1
输出:[]

示例 3:

1
2
输入:head = [1,2], n = 1
输出:[1]

提示:

  • 链表中结点的数目为 sz
  • 1 <= sz <= 30
  • 0 <= Node.val <= 100
  • 1 <= n <= sz

**进阶:**你能尝试使用一趟扫描实现吗?

阅读全文 »

题目

给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false

回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

  • 例如,121 是回文,而 123 不是。

示例 1:

1
2
输入:x = 121
输出:true

示例 2:

1
2
3
输入:x = -121
输出:false
解释:从左向右读, 为 -121 。 从右向左读, 为 121- 。因此它不是一个回文数。

示例 3:

1
2
3
输入:x = 10
输出:false
解释:从右向左读, 为 01 。因此它不是一个回文数。

提示:

  • -231 <= x <= 231 - 1

**进阶:**你能不将整数转为字符串来解决这个问题吗?

阅读全文 »

题目

给定一个字符串 s ,请你找出其中不含有重复字符的 最长 子串 的长度。

示例 1:

1
2
3
输入: s = "abcabcbb"
输出: 3
解释: 因为无重复字符的最长子串是 "abc",所以其长度为 3。

示例 2:

1
2
3
输入: s = "bbbbb"
输出: 1
解释: 因为无重复字符的最长子串是 "b",所以其长度为 1。

示例 3:

1
2
3
4
输入: s = "pwwkew"
输出: 3
解释: 因为无重复字符的最长子串是 "wke",所以其长度为 3。
请注意,你的答案必须是 子串 的长度,"pwke" 是一个子序列,不是子串。

提示:

  • 0 <= s.length <= 5 * 104
  • s 由英文字母、数字、符号和空格组成
阅读全文 »

题目

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。

请你将两个数相加,并以相同形式返回一个表示和的链表。

你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例 1:

img

1
2
3
输入:l1 = [2,4,3], l2 = [5,6,4]
输出:[7,0,8]
解释:342 + 465 = 807.

示例 2:

1
2
输入:l1 = [0], l2 = [0]
输出:[0]

示例 3:

1
2
输入:l1 = [9,9,9,9,9,9,9], l2 = [9,9,9,9]
输出:[8,9,9,9,0,0,0,1]

提示:

  • 每个链表中的节点数在范围 [1, 100]
  • 0 <= Node.val <= 9
  • 题目数据保证列表表示的数字不含前导零
阅读全文 »

题目

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案,并且你不能使用两次相同的元素。

你可以按任意顺序返回答案。

示例 1:

1
2
3
输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

1
2
输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

1
2
输入:nums = [3,3], target = 6
输出:[0,1]

提示:

  • 2 <= nums.length <= 104
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
  • 只会存在一个有效答案

**进阶:**你可以想出一个时间复杂度小于 O(n2) 的算法吗?

阅读全文 »

在讲解数据结构时,数组总是一个大家早期接触的主题。但你可能会发现,不同编程语言中“数组”这一概念的使用方式和 API 有所区别。其实我们可以把「数组」分为两大类:

静态数组

静态数组在创建时就已经确定了元素的个数以及连续的内存空间。我们可以通过下标索引访问数组中存储的元素,这正是数组最原始的形式,也是其 “随机访问” 能力得以实现的根本原因。

动态数组

动态数组是在静态数组基础上,为了方便编程引入的一层封装。动态数组在内部依然使用静态数组存储数据,但会自动进行扩容和提供一些常用的增删查改 API,如 ⁠push、⁠insert、⁠remove 等。了解动态数组的底层原理,有助于我们深入理解后续实现其他数据结构(例如队列、栈、哈希表等)的核心思想。

本文将围绕静态数组的基本原理,并用 C 语言代码手把手实现简单版本的动态数组,展示其增删查改操作。

阅读全文 »
0%