★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:MindDraft
➤博主域名:https://www.zengqiang.org
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:
https://www.cnblogs.com/strengthen/p/10709048.html
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
热烈欢迎,请直接点击!!!
进入博主App Store主页,下载使用各个作品!!!
注:博主将坚持每月上线一个新app!!!
数组:有序的元素序列。 若将有限个类型相同的变量的集合命名,那么这个名称为数组名。组成数组的各个变量称为数组的分量,也称为数组的元素,有时也称为下标变量。用于区分数组的各个元素的数字编号称为下标。数组是在程序设计中,为了处理方便, 把具有相同类型的若干元素按无序的形式组织起来的一种形式。这些无序排列的同类数据元素的集合称为数组。数组是用于储存多个相同类型数据的集合。
二维数组:本质上是以数组作为数组元素的数组,即“数组的数组”。二维数组又称为矩阵,行列数相等的矩阵称为方阵。
对称矩阵:a[i][j] = a[j][i]
对角矩阵:n阶方阵主对角线外都是零元素
三维数组:指维数为三的数组结构。三维数组是最常见的多维数组,由于其可以用来描述三维空间中的位置或状态而被广泛使用。
定义二维数组
1 //方式1
2 var arr1 = [[Int]]()
3 print(arr1)
4 //Print []
6 //方式2
7 var arr2 = Array<Array<Int>>()
8 print(arr2)
9 //Print []
11 //方式3:定义3列4行的二维数组,元素初始化为0
12 var arr3 = [[Int]](repeating: [Int](repeating: 0, count: 3), count: 4)
13 print(arr3)
14 //Print [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]
二维数组的遍历
1 //遍历行
2 for row in arr3
4 print(row)
5 //Print [0, 0, 0]
6 //遍历列
7 for col in row
9 //从左到右,从上到下进行遍历
10 print(col)
11 //Print 0
12 }
定义三维数组
1 //方式1
2 var arr1 = [[[Int]]]()
3 print(arr1)
4 //Print []
6 //方式2
7 var arr2 = Array<Array<Array<Int>>>()
8 print(arr2)
9 //Print []
11 //方式3:定义三维数组,元素初始化为0,由内往外
12 var arr3 = [[[Int]]](repeating: [[Int]](repeating: [Int](repeating: 0, count: 2), count: 3), count: 4)
13 print(arr3)
14 //2个元素的一维数组,3个元素的二维数组,4个元素的三位数组
15 /*
16 [
17 [
18 [0, 0], [0, 0], [0, 0]
19 ],
20 [
21 [0, 0], [0, 0], [0, 0]
22 ],
23 [
24 [0, 0], [0, 0], [0, 0]
25 ],
26 [
27 [0, 0], [0, 0], [0, 0]
28 ]
29 ]
30 */
三维数组的遍历
1 //遍历高height
2 for height in arr3
4 print(height)
5 //Print [[0, 0], [0, 0], [0, 0]]
6 //遍历长depth
7 for depth in height
9 print(depth)
10 //Print [0, 0]
11 //遍历宽width
12 for width in depth
13 {
14 print(width)
15 //Print 0
16 }
17 }
使用函数来创建多维数组
1 //num:元素个数
2 //value:元素初始值
3 func dimension<T>(_ num: Int, _ value: T) -> [T] {
4 return [T](repeating: value, count: num)
示例代码:
1 //用嵌套的方式创建多维数组
2 //创建一维数组
3 let arr1 = dimension(1,0)
4 print(arr1)
5 //Print [0]
7 //创建二维数组
8 let arr2 = dimension(2,arr1)
9 //即:let arr2 = dimension(2,dimension(1,0))
10 print(arr2)
11 //Print [[0], [0]]
13 //创建三维数组
14 let arr3 = dimension(3,arr2)
15 //即:let arr3 = dimension(3,dimension(2,dimension(1,0)))
16 print(arr3)
17 //Print [[[0], [0]], [[0], [0]], [[0], [0]]]
19 //创建四维数组
20 let arr4 = dimension(4,arr3)
21 //即:let arr4 = dimension(4,dimension(3,dimension(2,dimension(1,0))))
22 print(arr4)
23 //Print [[[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]]]
25 //创建五维数组
26 let arr5 = dimension(5,arr4)
27 //即:arr5 = dimension(5,dimension(4,dimension(3,dimension(2,dimension(1,0)))))
28 print(arr5)
29 //Print [[[[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]]], [[[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]]], [[[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]]], [[[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]]], [[[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]], [[[0], [0]], [[0], [0]], [[0], [0]]]]]
31 //......
使用函数嵌套的方法创建多维数组有一个很大的缺陷:无法明确维度所代表的意义。
所以,可以考虑使用一维数组存储多维数组的数据。
创建一个Array2D类,用一维数组存储二维数组的数据。
此时我们只需关注“列”和“行”的数值,细节交由Array2D来处理,这就是将原始数据类型包装成包装器类型或结构体的优点。
二维数组A[rows][columns]放到一维数组B中的对应公式:
两种方式 :
(1)、按行遍历
A[i][j] = B[ i + j * rows ]
(2)、按列遍历
A[i][j] = B[ i * columns + j ]
1 public struct Array2D<T> {
2 //列数
3 public let columns:Int
4 //行数
5 public
let rows:Int
6 fileprivate var array: [T]
8 //初始化
9 public init(columns: Int, rows: Int, initialValue: T) {
10 self.columns = columns
11 self.rows = rows
12 array = .init(repeating: initialValue, count: rows*columns)
13 }
15 //subscript函数可以检索数组中的值
16 public subscript(column: Int, row: Int) -> T {
17 //读取
18 get {
19 //先决条件
20 precondition(column <= columns, "Column \(column) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
21 precondition(row <= rows, "Row \(row) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
22 return array[row * columns + column]
23 //或 return array[row + column * rows]
24 }
25 //写入
26 set {
27 //先决条件
28 precondition(column <= columns, "Column \(column) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
29 precondition(row <= rows, "Row \(row) Index is out of range. Array<T>(columns: \(columns), rows:\(rows))")
30 array[row * columns + column] = newValue
31 //或 array[row + column * rows] = newValue
32 }
33 }
示例代码:
1 // 创建一个二维数组的实例
2 var arr2D = Array2D(columns: 2, rows:3, initialValue: 0)
3 print(arr2D)
4 //Print Array2D<Int>(columns: 2, rows: 3, array: [0, 0, 0, 0, 0, 0])
6 //subscript函数可以检索数组中的元素值
7 let num = arr2D[1, 1]
8 print(num)
9 //Print 0
11 //给数组中的元素赋值
12 arr2D[1, 1] = 88
13 print(arr2D[1, 1])
14 //Print 88
创建一个Array3D类,用一维数组存储三维维数组的数据。
此时我们只需关注“长”、“宽”和“高”的数值,细节交由Array3D来处理,这就是将原始数据类型包装成包装器类型或结构体的优点。
三维数组A[widths][depths][heights]放到一维数组B中的对应公式:
A[i][j][k] = B[ ( i - 1 ) * ( depths * heights ) + ( j - 1 ) * heights + k ]
1 public struct Array3D<T> {
2 //宽
3 public let widths:Int
4 //长
5 public let depths:Int
6 //高
7 public let heights:Int
8 fileprivate var array: [T]
10 //初始化
11 public init(widths: Int, depths: Int, heights: Int, initialValue: T) {
12 self.widths = widths
13 self.depths = depths
14 self.heights = heights
15 array = .init(repeating: initialValue, count: widths * depths * heights)
16 }
18 //subscript函数可以检索数组中的值
19 public subscript(width: Int, depth: Int, height: Int) -> T {
20 //读取
21 get {
22 //先决条件
23 precondition(width <= widths, "Width \(width) Index is out of range. Array<T>(widths: \(widths), depths:\(depths), heights:\(heights))")
24 precondition(depth <= depths, "Depth \(depth) Index is out of range. Array<T>(widths: \(widths), depths:\(depths), heights:\(heights))")
25 precondition(height <= heights, "Height \(height) Index is out of range. Array<T>(widths: \(widths), depths:\(depths), heights:\(heights))")
26 return array[(width - 1) * (depths * heights) + (depth - 1) * heights + height]
27 }
28 //写入
29 set {
30 //先决条件
31 precondition(width <= widths, "Width \(width) Index is out of range. Array<T>(widths: \(widths), depths:\(depths), heights:\(heights))")
32 precondition(depth <= depths, "Depth \(depth) Index is out of range. Array<T>(widths: \(widths), depths:\(depths), heights:\(heights))")
33 precondition(height <= heights, "Height \(height) Index is out of range. Array<T>(widths: \(widths), depths:\(depths), heights:\(heights))")
34 array[(width - 1) * (depths * heights) + (depth - 1) * heights + height] = newValue
35 }
36 }
示例代码:
1 // 创建一个三维数组的实例
2 var arr3D = Array3D(widths: 2, depths: 3, heights: 4, initialValue: 0)
3 print(arr3D)
4 //Print Array3D<Int>(widths: 2, depths: 3, heights: 4, array: [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0])
6 //subscript函数可以检索数组中的元素值
7 let num = arr3D[1, 1, 1]
8 print(num)
9 //Print 0
11 //给数组中的元素赋值
12 arr3D[1, 1, 1] = 88
13 print(arr3D[1, 1, 1])
14 //Print 88
四维维数组A[a][b][c][d]放到一维数组B中的对应公式:
A[i][j][k][w] = B[(i - 1) * (b * c * d) + (j - 1) * (c * d) + (k - 1) * d + w]
归纳演绎......
N维数组映射到一维数组
由此及彼,由表及里,归纳总结,创建一个Dim类,用一维数组存储n维数组的数据,
此时我们只需关注每一个维度的数值,细节交由Dim来处理,这就是将原始数据类型包装成包装器类型或结构体的优点。
深入思考:
(1)、多维度中各维度所表示意义的顺序可以任意确定,确定维度顺序之后,就按照既定的维度顺序进行对一维数组进行读写。
(2)、如同二维数组中可以按照行遍历或者按照列遍历一样。多维数组也可以任意确定多维数组中下标i、j、k、w、...的顺序。
下标顺序确定之后就不可变更,根据下标顺序得出对应公式,公式从上文中请归纳,就按照既定的下标顺序进行对一维数组进行读写。
1 public struct Dim<T> {
2 //用一个数组来接收维度信息
3 //元素个数为维度
4 //元素数值为对应维度的具体数量
5 public let dimension:[Int]
6 fileprivate var array:[T]
7
//只能初始化一次
8 public let product:Int
9 //数组信息
10 public let arrayInfo:String
12 //初始化
13 public init(dimension:[Int], initialValue: T) {
14 self.dimension = dimension
15 //数组各元素求积reduce(1)
16 //用于一维数组保存多维数组的信息
17 self.product = dimension.reduce(1) {$0 * $1}
18 //初始化数组
19 array = .init(repeating: initialValue, count: product)
20 //初始化维度信息
21 var str:String = " Array<T>("
22 for i in 0...(dimension.count - 1)
23 {
24 str += String(i + 1) + "Dimension: \(dimension[i]),"
25 }
26 //删除最后一个字符串‘,’
27 str.remove(at: str.index(before: str.endIndex))
28 str += ")"
29 arrayInfo = str
30 }
32 //subscript函数可以检索数组中的值
33 //T?:读取时如果输入的维度不等于原维度则返回nil
34 //取值需使用强制解包
35 public subscript(_ numbers: Int...) -> T? {
36 //读取
37 get
38 {
39 //判断元素个数是否等于维度数组个数
40 if numbers.count == dimension.count
41 {
42 for i in 0...(dimension.count - 1)
43 {
44 //先决条件
45 precondition( numbers[i] <= dimension[i], "\(String(i + 1))Dimension:\(numbers[i]) Index is out of range. " + arrayInfo)
46 }
47 return array[getIndex(numbers)]
48 }
49 return nil
50 }
52 //写入
53 set
54 {
55 //判断元素个数是否等于维度数组个数
56 if numbers.count == dimension.count
57 {
58 for i in 0...(dimension.count - 1)
59 {
60 //先决条件
61 precondition( numbers[i] <= dimension[i], "\(String(i + 1))Dimension:\(numbers[i]) Index is out of range. " + arrayInfo)
62 }
63 array[getIndex(numbers)] = newValue!
64 }
65 }
67 }
68 //求解多维数组的元素在一维数组中的索引
69 private func getIndex(_ dim: [Int]) -> Int
70 {
71 var sum:Int = 0
72 for index in 0...(dim.count - 1)
73 {
74 sum += (dim[index] - 1) * getProduct(index)
75 }
76 return sum
77 }
78 //求部分元素的积
79 private func getProduct(_ index:Int) -> Int
80 {
81 //数组各元素求积
82 var accumulate:Int = 1
83 //加1
84 var front:Int = index + 1
85 let real:Int = dimension.count - 1
86 if real > front
87 {
88 let arr:[Int] = [Int](dimension[front...real])
89 if arr.count != 0
90 {
91 //数组各元素求积reduce(1)
92 accumulate = arr.reduce(1){$0 * $1}
93 }
94 }
95 return accumulate
96 }
Dim类,用一维数组存储n维数组的数据,示例:
1 // 创建一维数组的实例
2 var arr1 = Dim(dimension:[3], initialValue: 1)
3 print(arr1)
4 //Print Dim<Int>(dimension: [3], array: [1, 1, 1], product: 3, arrayInfo: " Array<T>(1Dimension: 3)")
5 // 创建二维数组的实例
6 var arr2 = Dim(dimension:[1,2], initialValue: 2)
7 print(arr2)
8 //Print Dim<Int>(dimension: [1, 2], array: [2, 2], product: 2, arrayInfo: " Array<T>(1Dimension: 1,2Dimension: 2)")
9 // 创建三维数组的实例
10 var arr3 = Dim(dimension:[1,2,3], initialValue: 3)
11 print(arr3)
12 //Print Dim<Int>(dimension: [1, 2, 3], array: [3, 3, 3, 3, 3, 3], product: 6, arrayInfo: " Array<T>(1Dimension: 1,2Dimension: 2,3Dimension: 3)")
13 // 创建四维数组的实例
14 var arr4 = Dim(dimension:[1,2,3,4], initialValue: 4)
15 print(arr4)
16 //Print Dim<Int>(dimension: [1, 2, 3, 4], array: [4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4], product: 24, arrayInfo: " Array<T>(1Dimension: 1,2Dimension: 2,3Dimension: 3,4Dimension: 4)")
17 // 创建五维数组的实例
18 var arr5 = Dim(dimension:[1,2,3,4,5], initialValue: 5)
19 print(arr5)
20 //Print Dim<Int>(dimension: [1, 2, 3, 4, 5], array: [5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5], product: 120, arrayInfo: " Array<T>(1Dimension: 1,2Dimension: 2,3Dimension: 3,4Dimension: 4,5Dimension: 5)")
21 //......
23 //subscript函数可以检索数组中的元素值,Optional为可选类型
24 //一维数组
25 arr1[2] = 11
26 print(arr1)
27 //Print Dim<Int>(dimension: [3], array: [1, 11, 1], product: 3, arrayInfo: " Array<T>(1Dimension: 3)")
28 let num1 = arr1[1]
29 print(num1)
30 //Print Optional(1)
31 //二维数组
32 arr2[1,2] = 22
33 print(arr2)
34 //Print Dim<Int>(dimension: [1, 2], array: [2, 22], product: 2, arrayInfo: " Array<T>(1Dimension: 1,2Dimension: 2)")
35 let num2 = arr2[1,1]
36 print(num2)
37 //Print Optional(22)
38 //三维数组
39 arr3[1,1,1] = 33
40 print(arr3)
41 //Print Dim<Int>(dimension: [1, 2, 3], array: [33, 3, 3, 3, 3, 3], product: 6, arrayInfo: " Array<T>(1Dimension: 1,2Dimension: 2,3Dimension: 3)")
42 let num3 = arr3[1,1,1]
43 print(num3)
44 //Print Optional(33)
45 //四维数组
46 arr4[1,1,1,1] = 44
47 print(arr4)
48 //Print Dim<Int>(dimension: [1, 2, 3, 4], array: [44, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4], product: 24, arrayInfo: " Array<T>(1Dimension: 1,2Dimension: 2,3Dimension: 3,4Dimension: 4)")
49 let num4 = arr4[1,1,1,1]
50 print(num4)
51 //Print Optional(44)
52 //五维数组
53 arr5[1,1,1,1,1] = 55
54 print(arr5)
55 //Print Dim<Int>(dimension: [1, 2, 3, 4, 5], array: [55, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5], product: 120, arrayInfo: " Array<T>(1Dimension: 1,2Dimension: 2,3Dimension: 3,4Dimension: 4,5Dimension: 5)")
56 let num5 = arr5[1,1,1,1,1]
57 print(num5)
58 //Print Optional(55)
59 //......