02-数组(Array)详解¶
重要性:⭐⭐⭐⭐⭐ 难度:⭐ 学习时间:2-3天 前置知识:无
📚 目录¶
什么是数组?¶
基本概念¶
数组是最基础的数据结构,用于存储相同类型的元素序列。
生活中的例子¶
想象一排储物柜:
- 每个柜子(格子)存放一个物品
- 每个柜子都有一个编号(索引)
- 所有柜子连成一排,位置固定
为什么学数组?¶
✅ 优点: 1. 快速访问:通过索引直接访问,O(1)时间 2. 内存紧凑:元素连续存储,节省空间 3. 缓存友好:连续内存提高CPU缓存命中率
❌ 缺点: 1. 大小固定:创建后不能改变大小(大多数语言) 2. 插入删除慢:需要移动其他元素
数组的内存结构¶
内存可视化¶
内存地址: 1000 1004 1008 1012 1016
┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐
数组内容: │ 10 │ │ 20 │ │ 30 │ │ 40 │ │ 50 │
└────┘ └────┘ └────┘ └────┘ └────┘
索引: 0 1 2 3 4
假设int占4字节,每个元素间隔4个字节
图:数组在内存中的连续存储结构
关键特性¶
- 连续内存:数组元素在内存中是连续存放的
- 相同大小:每个元素占用相同的内存空间
- 随机访问:可以通过索引直接访问任意元素
为什么能O(1)访问?¶
公式:元素地址 = 起始地址 + (索引 × 元素大小)
示例:
起始地址 = 1000
索引 = 3
元素大小 = 4字节(int)
访问arr[3]:
地址 = 1000 + (3 × 4) = 1012 ✅ 直接计算,无需遍历!
数组的操作详解¶
操作1:访问元素 (O(1))¶
# 直接通过索引访问
arr = [10, 20, 30, 40, 50]
# 访问第3个元素(索引2)
element = arr[2] # 30
# 访问第一个元素
first = arr[0] # 10
# 访问最后一个元素
last = arr[-1] # 50(Python特有)
时间复杂度:O(1) 原理:通过公式直接计算地址
操作2:修改元素 (O(1))¶
arr = [10, 20, 30, 40, 50]
# 修改索引2的元素
arr[2] = 100
# 结果:[10, 20, 100, 40, 50]
# 复杂度:O(1) - 直接定位到位置并修改
操作3:在末尾添加 (均摊O(1))¶
arr = [10, 20, 30]
# 添加到末尾
arr.append(40)
# 结果:[10, 20, 30, 40]
# 原理:
# 1. 如果有剩余空间,直接放入 → O(1)
# 2. 如果空间不足,扩容后放入 → O(n)
# 平均下来:均摊O(1)
扩容过程(Python list):
初始容量:4
[10, 20, 30, _] 添加40 → [10, 20, 30, 40] ✓
添加50 → 空间不足,扩容!
旧数组:[10, 20, 30, 40]
新数组:[10, 20, 30, 40, _, _, _, _] 容量翻倍
复制所有元素 → [10, 20, 30, 40, 50, _, _, _]
操作4:在开头/中间插入 (O(n)) ⚠️¶
arr = [10, 20, 30, 40, 50]
# 在索引1处插入25
arr.insert(1, 25)
# 过程:
# 步骤1:[10, 20, 30, 40, 50, _] 扩容
# 步骤2:[10, __, 20, 30, 40, 50] 从后往前移动
# 步骤3:[10, 25, 20, 30, 40, 50] 插入
# 结果:[10, 25, 20, 30, 40, 50]
# 为什么是O(n)?因为要移动n个元素!
插入过程详解:
初始: [10, 20, 30, 40, 50]
索引: 0 1 2 3 4
在索引1插入25:
第1步:从后往前,每个元素向后移一位
50 → 索引5
40 → 索引4
30 → 索引3
20 → 索引2
10 → 索引0(不动)
第2步:在索引1处放入25
[10, 25, 20, 30, 40, 50]
移动了4个元素 → O(n)
图:在索引1处插入25的过程演示
操作5:删除元素 (O(n)) ⚠️¶
arr = [10, 20, 30, 40, 50]
# 删除索引2的元素
del arr[2]
# 过程:
# 初始: [10, 20, 30, 40, 50]
# 删除30: [10, 20, __, 40, 50]
# 前移: [10, 20, 40, 50] 40和50向前移动
# 结果:[10, 20, 40, 50]
# 为什么是O(n)?因为要移动n个元素!
删除过程详解:
初始: [10, 20, 30, 40, 50]
索引: 0 1 2 3 4
删除索引2的元素(30):
第1步:删除30
[10, 20, __, 40, 50]
第2步:从前往后,每个元素向前移一位
40 → 索引2
50 → 索引3
第3步:数组缩小
[10, 20, 40, 50]
移动了2个元素 → O(n)
操作6:查找元素 (O(n))¶
arr = [10, 20, 30, 40, 50]
# 线性查找30
for i in range(len(arr)):
if arr[i] == 30:
print(f"找到30,索引为{i}")
break
# 为什么是O(n)?最坏情况要遍历整个数组!
查找过程详解:
目标:查找30
数组:[10, 20, 30, 40, 50]
第1次比较:arr[0] = 10 ≠ 30
第2次比较:arr[1] = 20 ≠ 30
第3次比较:arr[2] = 30 = 30 ✓ 找到了!
最坏情况:查找50或不存在的元素
需要比较n次 → O(n)
操作7:遍历数组 (O(n))¶
arr = [10, 20, 30, 40, 50]
# 方法1:for循环
for i in range(len(arr)):
print(arr[i])
# 方法2:for-each循环
for element in arr:
print(element)
# 方法3:enumerate(获取索引和值)
for index, value in enumerate(arr):
print(f"索引{index}: {value}")
Python中的数组¶
Python List详解¶
# 创建数组
arr = [1, 2, 3, 4, 5]
# 基本操作
print(len(arr)) # 长度: 5
print(arr[0]) # 访问: 1
print(arr[-1]) # 最后一个: 5
print(arr[1:4]) # 切片: [2, 3, 4]
print(arr[::2]) # 步长: [1, 3, 5]
print(arr[::-1]) # 反转: [5, 4, 3, 2, 1]
# 添加元素
arr.append(6) # 末尾添加: [1, 2, 3, 4, 5, 6]
arr.insert(0, 0) # 开头插入: [0, 1, 2, 3, 4, 5, 6]
arr.extend([7, 8]) # 扩展列表: [0, 1, 2, 3, 4, 5, 6, 7, 8]
# 删除元素
arr.pop() # 删除末尾: 返回8
arr.pop(0) # 删除索引0: 返回0
arr.remove(3) # 删除值3
del arr[1] # 删除索引1
# 查找
print(3 in arr) # 判断是否存在: True
print(arr.index(3)) # 查找索引: 2
print(arr.count(3)) # 计数: 1
# 排序
arr.sort() # 原地排序
arr.sort(reverse=True) # 降序排序
sorted_arr = sorted(arr) # 返回新列表
# 其他操作
arr.reverse() # 反转
arr.clear() # 清空
arr.copy() # 复制
Python数组的高级操作¶
import numpy as np
# NumPy数组(更高效的数值计算)
np_arr = np.array([1, 2, 3, 4, 5])
# 向量化操作
np_arr * 2 # [2, 4, 6, 8, 10]
np_arr + 10 # [11, 12, 13, 14, 15]
np_arr > 3 # [False, False, False, True, True]
# 统计操作
np.mean(np_arr) # 平均值: 3.0
np.sum(np_arr) # 求和: 15
np.max(np_arr) # 最大值: 5
np.min(np_arr) # 最小值: 1
# 多维数组
matrix = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
print(matrix[0, 0]) # 1
print(matrix[:, 0]) # 第0列: [1, 4, 7]
print(matrix[0, :]) # 第0行: [1, 2, 3]
C++中的数组¶
C++原生数组¶
#include <iostream>
using namespace std;
int main() {
// 创建数组
int arr[5] = {1, 2, 3, 4, 5};
// 访问元素
cout << arr[0] << endl; // 1
cout << arr[4] << endl; // 5
// 遍历数组
for (int i = 0; i < 5; i++) {
cout << arr[i] << " ";
}
cout << endl;
// 获取数组大小
int size = sizeof(arr) / sizeof(arr[0]);
cout << "数组大小: " << size << endl;
// 修改元素
arr[2] = 100;
// 数组越界(危险!)
// arr[10] = 100; // 未定义行为
return 0;
}
C++ vector(动态数组)¶
#include <iostream>
#include <vector>
using namespace std;
int main() {
// 创建vector
vector<int> arr = {1, 2, 3, 4, 5};
// 基本操作
cout << arr.size() << endl; // 大小: 5
cout << arr[0] << endl; // 访问: 1
cout << arr.front() << endl; // 第一个: 1
cout << arr.back() << endl; // 最后一个: 5
// 添加元素
arr.push_back(6); // 末尾添加
arr.insert(arr.begin(), 0); // 开头插入
// 删除元素
arr.pop_back(); // 删除末尾
arr.erase(arr.begin() + 2); // 删除索引2
arr.clear(); // 清空
// 遍历
for (int i = 0; i < arr.size(); i++) {
cout << arr[i] << " ";
}
cout << endl;
// for-each循环
for (int val : arr) {
cout << val << " ";
}
cout << endl;
// 排序
sort(arr.begin(), arr.end()); // 升序
sort(arr.begin(), arr.end(), greater<int>()); // 降序
// 查找
auto it = find(arr.begin(), arr.end(), 3);
if (it != arr.end()) {
cout << "找到3" << endl;
}
// 二分查找(需要先排序)
bool found = binary_search(arr.begin(), arr.end(), 3);
return 0;
}
C++ array(固定大小数组)¶
#include <iostream> // 引入头文件
#include <array>
using namespace std;
int main() {
// 创建array(C++11)
array<int, 5> arr = {1, 2, 3, 4, 5};
// 基本操作
cout << arr.size() << endl; // 5
cout << arr[0] << endl; // 1
cout << arr.at(2) << endl; // 3(带边界检查)
// 遍历
for (int val : arr) {
cout << val << " ";
}
cout << endl;
// 填充
arr.fill(0); // 所有元素设为0
return 0;
}
经典面试题¶
题目1:两数之和¶
问题描述: 给定一个整数数组 nums 和一个目标值 target,在数组中找出和为目标值的两个整数,返回它们的索引。
示例:
解法1:暴力法(O(n²))
def two_sum_brute(nums, target):
"""
暴力解法
时间:O(n²)
空间:O(1)
"""
n = len(nums)
for i in range(n):
for j in range(i + 1, n):
if nums[i] + nums[j] == target:
return [i, j]
return []
# 测试
print(two_sum_brute([2, 7, 11, 15], 9)) # [0, 1]
解法2:哈希表(O(n))
def two_sum_hash(nums, target):
"""
哈希表解法
时间:O(n)
空间:O(n)
"""
# 存储值到索引的映射
hash_map = {}
for i, num in enumerate(nums):
complement = target - num
if complement in hash_map:
return [hash_map[complement], i]
hash_map[num] = i
return []
# 测试
print(two_sum_hash([2, 7, 11, 15], 9)) # [0, 1]
# 过程详解:
# i=0, num=2, complement=7, hash_map={}, 7不在hash_map中
# hash_map = {2: 0}
# i=1, num=7, complement=2, hash_map={2: 0}, 2在hash_map中!
# 返回 [hash_map[2], 1] = [0, 1] ✓
题目2:买卖股票的最佳时机¶
问题描述: 给定一个数组 prices,prices[i] 是某只股票在第i天的价格。设计算法计算最大利润。
示例:
解法:一次遍历(O(n))
def max_profit(prices):
"""
时间:O(n)
空间:O(1)
"""
if not prices:
return 0
min_price = prices[0] # 记录最低价格
max_profit = 0 # 记录最大利润
for price in prices:
# 更新最低价格
min_price = min(min_price, price)
# 更新最大利润
max_profit = max(max_profit, price - min_price)
return max_profit
# 测试
print(max_profit([7, 1, 5, 3, 6, 4])) # 5
# 过程详解:
# price=7: min_price=7, profit=0, max_profit=0
# price=1: min_price=1, profit=0, max_profit=0
# price=5: min_price=1, profit=4, max_profit=4
# price=3: min_price=1, profit=2, max_profit=4
# price=6: min_price=1, profit=5, max_profit=5 ✓
# price=4: min_price=1, profit=3, max_profit=5
图解:
价格: 7
│ 6
│ │ 5
│ │ │ 4
│ │ │ │ 3
│ │ │ │ │ 1
│ │ │ │ │ │
└────┴─────┴──┴──┴─────┴
0 1 2 3 4 5
最优:在1买入,在6卖出
利润 = 6 - 1 = 5
题目3:最大子数组和¶
问题描述: 给定一个整数数组 nums,找到一个具有最大和的连续子数组,返回其最大和。
示例:
解法:Kadane算法(O(n))
def max_subarray(nums):
"""
Kadane算法
时间:O(n)
空间:O(1)
核心思想:
- current_sum: 以当前元素结尾的子数组和
- max_sum: 全局最大子数组和
"""
if not nums:
return 0
current_sum = nums[0]
max_sum = nums[0]
for num in nums[1:]: # 切片操作:[start:end:step]提取子序列
# 选择:扩展当前子数组 OR 重新开始
current_sum = max(num, current_sum + num)
# 更新全局最大值
max_sum = max(max_sum, current_sum)
return max_sum
# 测试
print(max_subarray([-2, 1, -3, 4, -1, 2, 1, -5, 4])) # 6
# 过程详解:
# num=-2: current=-2, max=-2
# num=1: current=max(1, -2+1)=1, max=max(-2,1)=1
# num=-3: current=max(-3, 1-3)=-2, max=max(1,-2)=1
# num=4: current=max(4, -2+4)=4, max=max(1,4)=4
# num=-1: current=max(-1, 4-1)=3, max=max(4,3)=4
# num=2: current=max(2, 3+2)=5, max=max(4,5)=5
# num=1: current=max(1, 5+1)=6, max=max(5,6)=6 ✓
# num=-5: current=max(-5, 6-5)=1, max=max(6,1)=6
# num=4: current=max(4, 1+4)=5, max=max(6,5)=6
图解:
数组: [-2, 1, -3, 4, -1, 2, 1, -5, 4]
索引: 0 1 2 3 4 5 6 7 8
───┬───┬───┬───┬───┬───┬───┬───┬───
│
├─ 子数组[0:1]: -2
├─ 子数组[1:1]: 1
├─ 子数组[1:2]: -2
│
├─ 子数组[3:3]: 4
├─ 子数组[3:4]: 3
├─ 子数组[3:5]: 5
├─ 子数组[3:6]: 6 ✓ 最大
├─ 子数组[3:7]: 1
└─ 子数组[3:8]: 5
题目4:删除有序数组中的重复项¶
问题描述: 给定一个升序排列的数组 nums,原地删除重复元素,使每个元素只出现一次,返回新长度。
示例:
输入:nums = [1, 1, 2]
输出:2,nums = [1, 2]
输入:nums = [0, 0, 1, 1, 1, 2, 2, 3, 3, 4]
输出:5,nums = [0, 1, 2, 3, 4]
解法:双指针(O(n))
def remove_duplicates(nums):
"""
双指针解法
时间:O(n)
空间:O(1)
核心思想:
- slow: 慢指针,指向不重复区域的末尾
- fast: 快指针,遍历整个数组
"""
if not nums:
return 0
slow = 0 # 慢指针
for fast in range(1, len(nums)): # 快指针从1开始
if nums[fast] != nums[slow]: # 发现不同元素
slow += 1
nums[slow] = nums[fast]
return slow + 1
# 测试
nums = [0, 0, 1, 1, 1, 2, 2, 3, 3, 4]
length = remove_duplicates(nums)
print(f"新长度: {length}")
print(f"数组前{length}个: {nums[:length]}")
# 输出:新长度: 5
# 数组前5个: [0, 1, 2, 3, 4]
# 过程详解:
# 初始: [0, 0, 1, 1, 1, 2, 2, 3, 3, 4]
# ↑
# slow=0
# fast=1: nums[1]=0 == nums[0]=0,跳过
# fast=2: nums[2]=1 != nums[0]=0
# slow=1, nums[1]=1
# [0, 1, 1, 1, 1, 2, 2, 3, 3, 4]
# ↑ ↑
# slow=1 fast=2
# fast=3: nums[3]=1 == nums[1]=1,跳过
# fast=4: nums[4]=1 == nums[1]=1,跳过
# fast=5: nums[5]=2 != nums[1]=1
# slow=2, nums[2]=2
# [0, 1, 2, 1, 1, 2, 2, 3, 3, 4]
# ↑ ↑
# slow=2 fast=5
# ...继续直到fast遍历完
题目5:轮转数组¶
问题描述: 给定一个数组 nums,将数组中的元素向右轮转 k 步。
示例:
输入:nums = [1, 2, 3, 4, 5, 6, 7], k = 3
输出:[5, 6, 7, 1, 2, 3, 4]
解释:
- 向右轮转1步: [7, 1, 2, 3, 4, 5, 6]
- 向右轮转2步: [6, 7, 1, 2, 3, 4, 5]
- 向右轮转3步: [5, 6, 7, 1, 2, 3, 4]
解法1:使用额外数组(O(n)空间)
def rotate_extra_array(nums, k):
"""
额外数组解法
时间:O(n)
空间:O(n)
"""
n = len(nums)
k %= n # 处理k >= n的情况
# 创建新数组
result = [0] * n
# 将后k个元素放到前面
for i in range(k):
result[i] = nums[n - k + i]
# 将前n-k个元素放到后面
for i in range(n - k):
result[k + i] = nums[i]
# 复制回原数组
for i in range(n):
nums[i] = result[i]
# 测试
nums = [1, 2, 3, 4, 5, 6, 7]
rotate_extra_array(nums, 3)
print(nums) # [5, 6, 7, 1, 2, 3, 4]
解法2:三次翻转(O(1)空间)
def rotate_reverse(nums, k):
"""
三次翻转解法(推荐!)
时间:O(n)
空间:O(1)
核心思想:
1. 翻转整个数组
2. 翻转前k个元素
3. 翻转后n-k个元素
"""
n = len(nums)
k %= n
# 辅助函数:翻转数组的指定区间
def reverse(left, right):
while left < right:
nums[left], nums[right] = nums[right], nums[left]
left += 1
right -= 1
# 三次翻转
reverse(0, n - 1) # 翻转整个数组
reverse(0, k - 1) # 翻转前k个
reverse(k, n - 1) # 翻转后n-k个
# 测试
nums = [1, 2, 3, 4, 5, 6, 7]
rotate_reverse(nums, 3)
print(nums) # [5, 6, 7, 1, 2, 3, 4]
# 过程详解:
# 初始: [1, 2, 3, 4, 5, 6, 7]
#
# 第1次翻转(整体):
# [7, 6, 5, 4, 3, 2, 1]
#
# 第2次翻转(前3个):
# [5, 6, 7, 4, 3, 2, 1]
# ────┘
#
# 第3次翻转(后4个):
# [5, 6, 7, 1, 2, 3, 4]
# └──────┘
图解三次翻转:
原始: [1, 2, 3, 4, 5, 6, 7], k=3
第1步:整体翻转
┌───────────────────────┐
│ 1 2 3 4 5 6 7 │
└───────────────────────┘
↓ 翻转
┌───────────────────────┐
│ 7 6 5 4 3 2 1 │
└───────────────────────┘
第2步:翻转前3个
┌─────┐───────────────────┐
│ 7 6 5 │ 4 3 2 1 │
└─────┘───────────────────┘
↓ 翻转
┌─────┐───────────────────┐
│ 5 6 7 │ 4 3 2 1 │
└─────┘───────────────────┘
第3步:翻转后4个
┌─────┐┬──────────────────┐
│ 5 6 7 ││ 4 3 2 1 │
└─────┘┴──────────────────┘
↓ 翻转
┌─────┐┬──────────────────┐
│ 5 6 7 ││ 1 2 3 4 │
└─────┘┴──────────────────┘
最终: [5, 6, 7, 1, 2, 3, 4] ✓
图:使用三次翻转法将数组向右旋转3步
实战应用¶
应用1:机器学习中的数据预处理¶
import numpy as np
def normalize_data(features):
"""
数据标准化:将特征缩放到[0, 1]范围
"""
feature_array = np.array(features)
# 计算最小值和最大值
min_val = np.min(feature_array, axis=0)
max_val = np.max(feature_array, axis=0)
# 标准化公式:(x - min) / (max - min)
normalized = (feature_array - min_val) / (max_val - min_val)
return normalized
# 示例:标准化鸢尾花数据集
features = [
[5.1, 3.5, 1.4, 0.2], # 花萼长度、宽度,花瓣长度、宽度
[4.9, 3.0, 1.4, 0.2],
[7.0, 3.2, 4.7, 1.4],
[6.3, 3.3, 6.0, 2.5]
]
normalized = normalize_data(features)
print("标准化后的数据:")
print(normalized)
应用2:滑动窗口技术¶
def max_sliding_window(nums, k):
"""
滑动窗口最大值
给定数组nums和窗口大小k,返回每个窗口的最大值
示例:
输入:nums = [1, 3, -1, -3, 5, 3, 6, 7], k = 3
输出:[3, 3, 5, 5, 6, 7]
"""
from collections import deque
result = []
window = deque() # 存储索引(非值!)
for i, num in enumerate(nums): # enumerate同时获取索引和值
# 移除窗口外的元素
while window and window[0] <= i - k:
window.popleft()
# 移除小于当前元素的值
while window and nums[window[-1]] < num: # 负索引:从末尾倒数访问元素
window.pop()
# 添加当前元素
window.append(i)
# 记录窗口最大值
if i >= k - 1:
result.append(nums[window[0]])
return result
# 测试
nums = [1, 3, -1, -3, 5, 3, 6, 7]
k = 3
print(f"滑动窗口最大值: {max_sliding_window(nums, k)}")
# 输出: [3, 3, 5, 5, 6, 7]
# 图解:
# nums = [1, 3, -1, -3, 5, 3, 6, 7]
#
# 窗口1: [1, 3, -1] → 最大值: 3
# 窗口2: [3, -1, -3] → 最大值: 3
# 窗口3: [-1, -3, 5] → 最大值: 5
# 窗口4: [-3, 5, 3] → 最大值: 5
# 窗口5: [5, 3, 6] → 最大值: 6
# 窗口6: [3, 6, 7] → 最大值: 7
图:滑动窗口在数组中移动并找出每个窗口的最大值
应用3:前缀和¶
def prefix_sum(arr):
"""
前缀和数组
用于快速计算区间和
"""
n = len(arr)
prefix = [0] * (n + 1)
# prefix[i] = arr[0] + arr[1] + ... + arr[i-1]
for i in range(1, n + 1):
prefix[i] = prefix[i - 1] + arr[i - 1]
return prefix
def range_sum(prefix, left, right):
"""
计算区间[left, right]的和
时间:O(1)
"""
return prefix[right + 1] - prefix[left]
# 测试
arr = [1, 2, 3, 4, 5]
prefix = prefix_sum(arr)
print(f"前缀和数组: {prefix}") # [0, 1, 3, 6, 10, 15]
# 快速计算区间和
print(f"区间[1, 3]的和: {range_sum(prefix, 1, 3)}") # 2+3+4=9
print(f"区间[0, 4]的和: {range_sum(prefix, 0, 4)}") # 1+2+3+4+5=15
# 图解:
# arr: [1, 2, 3, 4, 5]
# 索引: 0 1 2 3 4
#
# prefix: [0, 1, 3, 6, 10, 15]
# 索引: 0 1 2 3 4 5
#
# prefix[i] = arr[0..i-1]的和
#
# 区间和公式:
# arr[left..right]的和 = prefix[right+1] - prefix[left]
#
# 示例:arr[1..3]的和
# = prefix[4] - prefix[1]
# = 10 - 1
# = 9 ✓ (即 2+3+4)
图:前缀和数组及其快速计算区间和的原理
应用4:矩阵操作¶
import numpy as np
def matrix_operations():
"""矩阵基本操作"""
# 创建矩阵
matrix = np.array([
[1, 2, 3],
[4, 5, 6],
[7, 8, 9]
])
print("原始矩阵:")
print(matrix)
# 访问元素
print(f"\n元素[0,0]: {matrix[0, 0]}") # 1
# 访问行
print(f"第0行: {matrix[0, :]}") # [1, 2, 3]
# 访问列
print(f"第0列: {matrix[:, 0]}") # [1, 4, 7]
# 矩阵转置
print("\n转置矩阵:")
print(matrix.T)
# 矩阵加减
matrix2 = np.array([
[9, 8, 7],
[6, 5, 4],
[3, 2, 1]
])
print("\n矩阵相加:")
print(matrix + matrix2)
# 矩阵乘法
print("\n矩阵乘法:")
print(np.dot(matrix, matrix2))
# 逐元素操作
print("\n每个元素乘以2:")
print(matrix * 2)
# 矩阵求和
print(f"\n所有元素的和: {np.sum(matrix)}")
print(f"每行的和: {np.sum(matrix, axis=1)}")
print(f"每列的和: {np.sum(matrix, axis=0)}")
# 运行
matrix_operations()
练习题¶
基础题¶
-
找出数组中第二大的数
-
反转数组(不使用额外空间)
-
检查数组是否有序
中等题¶
-
合并两个有序数组
-
移除所有等于val的元素
-
找出数组中缺失的数
困难题¶
-
盛水最多的容器
-
除自身以外数组的乘积
📝 总结¶
关键要点¶
✅ 数组特点: - 连续内存存储 - 支持随机访问O(1) - 插入/删除O(n)
✅ 常用操作: - 访问/修改:O(1) - 添加/删除:O(n) - 查找:O(n)(二分搜索除外)
✅ Python vs C++: - Python list:动态数组,功能丰富 - C++ vector:高效,类型安全
✅ 经典技巧: - 双指针 - 滑动窗口 - 前缀和 - 哈希表配合
下一步¶
继续学习: - 链表 - 动态数据结构 - 栈和队列 - 受限操作的线性结构
📚 扩展阅读¶
- NumPy文档:https://numpy.org/doc/
- LeetCode数组标签:https://leetcode.cn/tag/array/
- 数组可视化:https://visualgo.net/zh/array




