数组(Array)是一种线性表数据结构。它用一组连续的内存空间,来存储一组具有相同类型的数据。
线性表:线性表就是数据排成像一条线一样的结构。每个线性表上的数据最多只有前和后两个方向。其实除了数组,链表、队列、栈等也是线性表结构。
连续的内存空间和相同类型的数:因为这两个限制,它才有了一个堪称“杀手锏”的特性:“随机访问”。但有利就有弊,这两个限制也让数组的很多操作变得非常低效,比如要想在数组中删除、插入一个数据,为了保证连续性,就需要做大量的数据搬移工作。
数组是适合查找操作,但是查找的时间复杂度并不为 O(1)。即便是排好序的数组,你用二分查找,时间复杂度也是 O(logn)。数组支持随机访问,根据下标随机访问的时间复杂度为 O(1)。
假设数组的长度为 n,现在,如果我们需要将一个数据插入到数组中的第 k 个位置。为了把第 k 个位置腾出来,给新来的数据,我们需要将第 k~n 这部分的元素都顺序地往后挪一位。数组插入操作的最好时间复杂度为O(1),最坏时间复杂度为O(n),平均时间复杂度为O(n)。
如果数组中的数据是有序的,我们在某个位置插入一个新的元素时,就必须按照刚才的方法搬移 k 之后的数据。但是,如果数组中存储的数据并没有任何规律,数组只是被当作一个存储数据的集合。在这种情况下,如果要将某个数据插入到第 k 个位置,为了避免大规模的数据搬移,我们还有一个简单的办法就是,直接将第 k 位的数据搬移到数组元素的最后,把新的元素直接放入第 k 个位置。该场景下,在第k个位置插入一个元素的时间复杂度就变为O(1)。
如果我们要删除第 k 个位置的数据,为了内存的连续性,也需要搬移数据,不然中间就会出现空洞,内存就不连续了。如果删除数组末尾的数据,则最好情况时间复杂度为 O(1);如果删除开头的数据,则最坏情况时间复杂度为 O(n);平均情况时间复杂度也为 O(n)。
在某些特殊场景下,我们并不一定非得追求数组中数据的连续性。如果我们将多次删除操作集中在一起执行,这样能够有效提升删除的效率。删除数据时可以先记录下已经删除的数据。每次的删除操作并不是真正地搬移数据,只是记录数据已经被删除。当数组没有更多空间存储数据时,再触发执行一次真正的删除操作。
在使用数组的时候,一定要警惕数组越界,像C语言这种没有数组越界检测机制的语言,出现数组越界可能会带来意想不到的逻辑错误。在进行程序开发过程中,一定记得数组边界条件的检查,防止数组越界。
ArrayList 、vector最大的优势就是可以将很多数组操作的细节封装起来。比如前面提到的数组插入、删除数据时需要搬移其他数据等。另外,它还有一个优势,就是支持动态扩容。动态扩容操作涉及内存申请和数据搬移,是比较耗时的。所以,如果事先能确定需要存储的数据大小,最好在创建 ArrayList 的时候事先指定数据大小。指定大小能够减少不必要的内存申请和数据搬移,提升性能。
对于业务开发,直接使用容器就足够了,省时省力。毕竟损耗一丢丢性能,完全不会影响到系统整体的性能。但如果你是做一些非常底层的开发,比如开发网络框架,性能的优化需要做到极致,这个时候数组就会优于容器,成为首选。
1、实现两个有序数组合并为一个有序数组
-
- package main
-
- import (
- "fmt"
- )
-
- func mergeTwoArray(arr1 []int, arr2 []int) []int {
- lengthOfArray1 := len(arr1)
- lengthOfArray2 := len(arr2)
- mergedArray := make([]int, 0)
-
- i := 0
- j := 0
- for i < lengthOfArray1 && j < lengthOfArray2 {
- if arr1[i] <= arr2[j] {
- mergedArray = append(mergedArray, arr1[i])
- i++
- } else if arr1[i] >= arr2[j] {
- mergedArray = append(mergedArray, arr2[j])
- j++
- }
- }
-
- for i
- mergedArray = append(mergedArray, arr1[i])
- i++
- }
- for j
- mergedArray = append(mergedArray, arr2[j])
- j++
- }
- return mergedArray
- }
-
- func main() {
- arr1 := []int{1, 3, 5, 7}
- arr2 := []int{2, 4, 6, 8, 9, 10}
- arr := mergeTwoArray(arr1, arr2)
- fmt.Println(arr)
- }
-
-
-
- [1 2 3 4 5 6 7 8 9 10]
声明:参考极客时间《数据结构与算法之美》专栏
-
相关阅读:
路由器——交换机——网络交换机:区别
mac M2 pytorch_geometric安装
C++ STL重点、难点复习总结
spring 请求 出现实体类大小写不一致 出现的问题
箭头函数的缺点
ant的javac任务的相关属性配置
C#设计模式详解(1)——Template Method(模板方法)
如何搭建跨境独立站?
一个简单的HTML篮球网页【学生网页设计作业源码】
【Transformer 相关理论深入理解】注意力机制、自注意力机制、多头注意力机制、位置编码
-
原文地址:https://blog.csdn.net/u012967763/article/details/126451240