02.数组基础

本文详细介绍了数组作为一种线性表数据结构的基本概念,包括顺序存储结构、随机访问特性以及在C/C++、Java和Python等编程语言中的实现差异。同时涵盖了数组的增删改查操作及其时间复杂度分析。
摘要由CSDN通过智能技术生成

数组定义

数组(Array):一种线性表数据结构。它使用一组连续的内存空间,来存储一组具有相同类型的数据。

我们可以从两个方面来解释数组的定义。

  1. 线性表:线性表就是所有数据元素排成像一条线一样的结构,线性表上的数据元素都是相同类型,且每个数据元素最多只有前、后两个方向。数组就是一种线性表结构,此外,栈、队列、链表都是线性表结构。
  2. 连续的内存空间:线性表有两种存储结构:「顺序存储结构」和「链式存储结构」。其中,「顺序存储结构」是指占用的内存空间是连续的,相邻数据元素之间,物理内存上的存储位置也相邻。数组也是采用了顺序存储结构,并且存储的数据都是相同类型的。

综合这两个角度,数组就可以看做是:使用了「顺序存储结构」的「线性表」的一种实现方式。

如何随机访问数据元素

数组的一个最大特点是:可以进行随机访问。即数组可以根据下标,直接定位到某一个元素存放的位置。 

那么,计算机是如何实现根据下标随机访问数组元素的?

计算机给一个数组分配了一组连续的存储空间,其中第一个元素开始的地址被称为 「首地址」。每个数据元素都有对应的下标索引和内存地址,计算机通过地址来访问数据元素。当计算机需要访问数组的某个元素时,会通过 「寻址公式」 计算出对应元素的内存地址,然后访问地址对应的数据元素。

寻址公式如下:下标 i 对应的数据元素地址 = 数据首地址 + i × 单个数据元素所占内存大小

不同编程语言中数组的实现 

在具体的编程语言中,数组这个数据结构的实现方式具有一定差别。

C / C++ 语言中的数组最接近数组结构定义中的数组,使用的是一块存储相同类型数据的、连续的内存空间。不管是基本类型数据,还是结构体、对象,在数组中都是连续存储的。例如:

int arr[3][4] = {{0, 1, 2, 3}, {4, 5, 6, 7}, {8, 9, 10, 11}};

Java 中的数组跟数据结构定义中的数组不太一样。Java 中的数组也是存储相同类型数据的,但所使用的内存空间却不一定是连续(多维数组中)。且如果是多维数组,其嵌套数组的长度也可以不同。例如:

int[][] arr = new int[3][]{ {1,2,3}, {4,5}, {6,7,8,9}};

原生 Python 中其实没有数组的概念,而是使用了类似 Java 中的 ArrayList 容器类数据结构,叫做列表。通常我们把列表来作为 Python 中的数组使用。Python 中列表存储的数据类型可以不一致,数组长度也可以不一致。例如:

arr = ['python', 'java', ['asp', 'php'], 'c']

数组的增删改查

访问数组元素、改变数组元素的时间复杂度为 O(1),在数组尾部插入、删除元素的时间复杂度也是 O(1),普通情况下插入、删除元素的时间复杂度为 O(n)。

练习

T0066. 加一

def plusOne(self, digits: List[int]) -> List[int]:
    digits = [0] + digits #在数组开头加0,处理加分过程中可能发生的进位
    digits[len(digits) - 1] += 1
    for i in range(len(digits)-1, 0, -1):
        if digits[i] != 10:
            break
        else:
            digits[i] = 0
            digits[i - 1] += 1
        
    if digits[0] == 0:
        return digits[1:] 
    else:
        return digits

T0724. 寻找数组的中心下标

class Solution:
    def pivotIndex(self, nums: List[int]) -> int:
        sum = 0
        for i in range(len(nums)): #第一次遍历先求出数组全部元素和
            sum += nums[i]
        curr_sum = 0
        for i in range(len(nums)): #第二次遍历找到左侧元素和恰好为全部元素和一半的位置
            if curr_sum * 2 + nums[i] == sum:
                return i
            curr_sum += nums[i]
        return -1

T0189. 轮转数组

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        n = len(nums)
        k = k % n ##处理 k 值大于数组长度 n 的情况,以避免不必要的重复旋转
        self.reverse(nums, 0, n-1)
        self.reverse(nums, 0, k-1)
        self.reverse(nums, k, n-1)
    def reverse(self, nums: List[int], left: int, right: int) -> None:
        while left < right :
            tmp = nums[left]
            nums[left] = nums[right]
            nums[right] = tmp
            left += 1
            right -= 1

T0048. 旋转图像

思路1:原地旋转

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        n = len(matrix)

        for i in range(n // 2):
            for j in range((n + 1) // 2):
                # 四元组交换
                matrix[i][j], matrix[n - j - 1][i], matrix[n - i - 1][n - j - 1], matrix[j][n - i - 1] = matrix[n - j - 1][i], matrix[n - i - 1][n - j - 1], matrix[j][n - i - 1], matrix[i][j]

思路2:原地翻转 

def rotate(self, matrix: List[List[int]]) -> None:
    n = len(matrix)
    
    #水平翻转:沿主对角线翻转矩阵的行,使得行的首尾元素交换位置。
    #对角线转置:对每一行的前半部分进行转置,即将行元素与其对应的列元素交换。
    for i in range(n // 2):
        for j in range(n):
            matrix[i][j], matrix[n - i - 1][j] = matrix[n - i - 1][j], matrix[i][j]
    
    for i in range(n):
        for j in range(i):
            matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]

T0054. 螺旋矩阵

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        up, down, left, right = 0, len(matrix)-1, 0, len(matrix[0])-1
        ans = []
        while True:
            for i in range(left, right + 1):
                ans.append(matrix[up][i])
            up += 1
            if up > down:
                break
            for i in range(up, down + 1):
                ans.append(matrix[i][right])
            right -= 1
            if right < left:
                break
            for i in range(right, left - 1, -1):
                ans.append(matrix[down][i])
            down -= 1
            if down < up:
                break
            for i in range(down, up - 1, -1):
                ans.append(matrix[i][left])
            left += 1
            if left > right:
                break
        return ans

T0498. 对角线遍历

class Solution:
    def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]:
        rows = len(mat)
        cols = len(mat[0])
        count = rows * cols
        x, y = 0, 0
        ans = []

        for i in range(count):
            ans.append(mat[x][y])

            if (x + y) % 2 == 0:
                # 最后一列
                if y == cols - 1:
                    x += 1
                # 第一行
                elif x == 0:
                    y += 1
                # 右上方向
                else:
                    x -= 1
                    y += 1
            else:
                # 最后一行
                if x == rows - 1:
                    y += 1
                # 第一列
                elif y == 0:
                    x += 1
                # 左下方向
                else:
                    x += 1
                    y -= 1
        return ans

  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值