Array Basics (Day 03 ~ 04)

This article is based on the notes of the Datawhale open source tutorial LeetCode algorithm notes (Leetcode-Notes) https://github.com/datawhalechina/leetcode-notes . It mainly records some important knowledge points in the learning process.

Array basics

1. Definition

| Array: A linear table data structure. It uses a set of contiguous memory spaces to store a set of data of the same type.

Please add image description

Features:

  • Occupies continuous memory space
  • The data types stored are the same
  • Each element occupies the same amount of memory
  • It is the basis for implementing the sequential storage structure of linear tables.
  • It can also be seen as an implementation of a linear table using a sequential storage structure.
Why can array elements be accessed randomly based on subscripts?

Answer: This is because the array occupies a continuous storage space. Each data element has a corresponding subscript index and memory address. According to the first address of the array, the address of any other subscript index can be deduced.

The addressing formula is as follows: subscript iiThe data element address corresponding to i = data first address + iii × the memory size occupied by a single data element.

2. Multidimensional array

It is also called an array within an array because the equivalent elements in a one-dimensional array are another one-dimensional array. The first dimension of a two-dimensional array represents rows, and the second dimension represents columns.

3. Implementation of arrays in different programming languages

3.1 C / C++

The array in C/C++ is closest to the array in the definition of the array structure, using a continuous memory space that stores the same type of data . Whether it is basic type data, structures, or objects, they are stored continuously in arrays. For example:

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

3.2 JAVA

Arrays in Java are not the same as arrays in data structure definitions. Arrays in Java also store the same type of data, but the memory space used is not necessarily continuous (in multi-dimensional arrays). And if it is a multi-dimensional array, the length of the nested arrays can also be different . For example:

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

3.3 python

There is actually no concept of arrays in native Python. Instead, a container class data structure similar to the ArrayList in Java is used, called 列表. Usually we use lists as arrays in Python . The data types stored in lists in Python can be inconsistent, and the array lengths can also be inconsistent . For example:

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

4. Basic operations on arrays

4.1 Access elements

Accessing the i-th element in the array: Since it does not depend on the number of elements in the array, the time complexity is O(1)

The sample code is as follows:

# 从数组 nums 中读取下标为 i 的数据元素值
def value(nums, i):
    if 0 <= i <= len(nums) - 1:
        print(nums[i])
        
arr = [0, 5, 2, 3, 7, 1, 6]
value(arr, 3)

4.2 Modify elements (modification)

Change the value of the i-th element in the array to val: that is, assign the value of the i-th element to val. Since it does not depend on the number of elements in the array, the time complexity is O(1)

The sample code is as follows:

def change(nums, i, val):
    if 0 <= i <= len(nums) - 1:
        nums[i] = val
        
arr = [0, 5, 2, 3, 7, 1, 6]
i, val = 2, 4
change(arr, i, val)
print(arr)

4.3 Find elements (check)

Find the position in the array where the element value is val: When the array is unordered, it can only be retrieved by comparing val with the data elements in the array one by one, also known as linear search. Build a subscript-based loop that compares val to the current data element nums[i] each time. Returns the element subscript when the element is found, and can return a special value (such as -1) when it is not found. The linear search operation depends on the number of elements in the array, so the time complexity is O(n)

# 从数组 nums 中查找元素值为 val 的数据元素第一次出现的位置
def find(nums, val):
    for i in range(len(nums)):
        if nums[i] == val:
            return i
    return -1

arr = [0, 5, 2, 3, 7, 1, 6]
print(find(arr, 5))

4.4 Insert elements (increase)

Add at the end: append() O(1)
Add at any position: add(i,k) Add element k at position i O(n)

Note: If the tail capacity of the array is not full, place val directly in the free position at the tail of the array and update the element count value of the array. If the array capacity is full, the insertion fails. However, the list in Python does other processing. When the array capacity is full, new space will be opened for insertion.

arr = [0, 5, 2, 3, 7, 1, 6]
val = 4
arr.append(val)
print(arr)

arr = [0, 5, 2, 3, 7, 1, 6]
i, val = 2, 4
arr.insert(i, val)
print(arr)

4.5 Delete elements (delete)

Delete at the end: pop() O(1)
Delete at any position: pop(i) Delete the element whose subscript position is i O(n)

arr = [0, 5, 2, 3, 7, 1, 6]
arr.pop()
print(arr)

arr = [0, 5, 2, 3, 7, 1, 6]
i = 3
arr.pop(i)
print(arr)

Please check the reference content for detailed study content. This article is mainly used as a brief summary and notes.

Reference content:
https://algo.itcharge.cn/01.Array/01.Array-Basic/01.Array-Basic/

01.02.02 Practice questions (Day 03)

1. 0066. plus one

1.1 General idea of ​​the question

Description : Given an array of non-negative integers, each bit of the array corresponds to a digit of the integer.

Requirement : Calculate integer addition 1 1The result after 1 .

Description :

  • 1 ≤ digits length ≤ 100 1 \and digits.length \and1digits.length100
  • 0 ≤ d i g i t s [ i ] ≤ 9 0 \le digits[i] \le 9 0digits[i]9

Example :

  • Example 1:
输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123,加 1 之后为 124
  • Example 2:
输入:digits = [4,3,2,1]
输出:[4,3,2,2]
解释:输入数组表示数字 4321

| Examination points: Conversion between integers, strings, and lists

class Solution:
    def plusOne(self, digits: List[int]) -> List[int]:
        digits = [str(i) for i in digits]  #列表里的元素,整数转换成字符
        s = ''.join(digits)  #列表转换成字符串
        num = str(int(s)+1)  #转换成字符串,方便遍历每个元素
        # num = int(s)  #转换成整数方便运算
        # num+=1
        # num=str(num)
        result = []
        for i in num:
            result.append(int(i))
        
        return result    

2. 0724. Find the center index of the array

2.1 General idea of ​​the question

Description : Given an integer array nums, please calculate the center subscript of the array.

The center subscript of an array is an array subscript such that the sum of all the elements on the left is equal to the sum of all the elements on the right.

If the center subscript is at the leftmost end of the array, the sum of the numbers on the left is considered to be 0 because there is no element to the left of the subscript. This is also true for center subscripts located at the far right end of the array.

If the array has multiple center subscripts, the one closest to the left should be returned. If the array does not have a center subscript, -1 is returned.

Requirement : Calculate the center subscript of the array.

Description :

  • 1 <= nums.length <= 104
  • -1000 <= nums[i] <= 1000

Example :

  • Example 1:
输入:nums = [1, 7, 3, 6, 5, 6]
输出:3
解释:
中心下标是 3
左侧数之和 sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11
右侧数之和 sum = nums[4] + nums[5] = 5 + 6 = 11 ,二者相等。
  • Example 2:
输入:nums = [1, 2, 3]
输出:-1
解释:
数组中不存在满足此条件的中心下标。
  • Example 3:
输入:nums = [2, 1, -1]
输出:0
解释:
中心下标是 0
左侧数之和 sum = 0 ,(下标 0 左侧不存在元素),
右侧数之和 sum = nums[1] + nums[2] = 1 + -1 = 0

Solution 1

class Solution:
    def pivotIndex(self, nums: List[int]) -> int:
        l = len(nums)
        for i  in range(len(nums)):
            if i == 0: #边界条件,首元素满足的情况
                if sum(nums[1:])==0:
                    return 0
                else:
                    continue
            elif i == (l-1):  #边界条件,最后一个满足的情况
                if sum(nums[0:l-1])==0:
                    return l-1
                else:
                    continue
            else:   #普通情况
                if sum(nums[0:i])==sum(nums[i+1:]):  #注意这里的右边界
                    return i
                else:
                    continue
        return -1

The simplest method, regardless of efficiency and memory
Please add image description

Solution 2

class Solution:
    def pivotIndex(self, nums: List[int]) -> int:
        pre_sum = 0
        total = sum(nums)
        for i in range(len(nums)):
            if total - nums[i] == pre_sum*2:
                return i
            pre_sum+=nums[i]
        return -1

Traverse the array from left to right. When traversing to the i position of the array, pre_sum represents the sum of the elements to the left of the i position.
Please add image description

3. 0189. Rotate array

3.1 General idea of ​​the question

Description : Given an array nums numsn u m s , and then given a numberkkk

Requirement : Move the elements in the array kk to the rightk positions.

Description :

  • 1 ≤ n u m s . l e n g t h ≤ 1 0 5 1 \le nums.length \le 10^5 1nums.length105
  • − 2 31 ≤ nums [ i ] ≤ 2 31 − 1 -2^{31} \le nums[i] \le 2^{31} - 1231nums[i]2311
  • 0 ≤ k ≤ 1 0 5 0 \le k \le 10^50k105

Example :

输入: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]

Advanced:

  • Try to come up with as many solutions as possible. There are at least three different ways to solve the problem.
  • Can you solve this problem using an in-place algorithm with O(1) space complexity?

Solution 1: Traverse k elements from back to front, inserting each time into the head of the list

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        for _ in range(len(nums)):
            nums.insert(0,nums.pop())

Please add image description

Solution 2: intercept the last k characters and splice them into the header

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        # nums[:] = XX 的赋值,nums 的地址不变;nums = XX的赋值,nums 是新地址。
        l = len(nums)
        k = k % l 
        nums[:] =  nums[l-k:] + nums[0:l-k]

| Note: Use nums[:] to refer to the original address, and num to the new address.

Please add image description

Solution 3: Flip the cubic array

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        n=len(nums)
        k=k%n

        def swap(l,r):
            while(l<r):
                nums[l],nums[r]=nums[r],nums[l]
                l=l+1
                r=r-1

        swap(0,n-k-1)
        swap(n-k,n-1)
        swap(0,n-1)

Please add image description


1. 0048. Rotate image

1.1 General idea of ​​the question

Description : Given an n × nn \times nn×A two-dimensional matrix of n size (representing an image)matrix matrixmatrix

Requirement : Convert the two-dimensional matrix matrix matrixma t r i x rotates 90° clockwise.

Description :

  • No additional array space can be used.
  • n = = m a t r i x . l e n g t h = = m a t r i x [ i ] . l e n g t h n == matrix.length == matrix[i].length n==matrix.length==matrix[i].length
  • 1 ≤ n ≤ 20 1 \le n \le 201n20
  • − 1000 ≤ m a t r i x [ i ] [ j ] ≤ 1000 -1000 \le matrix[i][j] \le 1000 1000matrix[i][j]1000

Example :

  • Example 1:

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]
  • Example 2:

输入:matrix = [[5,1,9,11],[2,4,8,10],[13,3,6,7],[15,14,12,16]]
输出:[[15,13,2,5],[14,3,4,1],[12,6,8,9],[16,7,10,11]]

Ideas

  • The first step is to swap along the diagonal (that is, transpose the rows and columns)

  • In the second step, for each row, reverse

Code

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        # 沿对角线交换
        l = len(matrix)
        for i in range(l):
            for j in range(0,i):    # 这个范围确保了我们只处理矩阵的上三角部分或下三角部分,并且避免了重复的互换操作
                matrix[i][j],matrix[j][i] = matrix[j][i],matrix[i][j]
        
        # 每行反转
        for line in matrix:
            line.reverse()

Please add image description

Expand

This is how you rotate 90° clockwise, but what about counterclockwise?

The principle is the same, just swap the elements on both sides with the sub-diagonal line as the main one!

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        n = len(matrix)
        # 既然副对角线为主那么i的范围就是从n-1到0啦 因为python的range是左闭右开所以是n-1和-1
        for i in range(n-1,-1):
            # 注意这里j的范围 如果j的范围也是0到n-1那么会出现交换后又交换回来 等于没有交换
            for j in range(i):
                matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
        
        for line in matrix:
            line.reverse()

2. 0054. Spiral matrix

2.1 General idea of ​​the question

Description : Given a m × nm \times nm×n- sized two-dimensionalmatrix matrix matrixmatrix

Requirement : Return all elements in the matrix in clockwise rotation order.

Description :

  • m = = m a t r i x . l e n g t h m == matrix.length m==matrix.length
  • n = = m a t r i x [ i ] . l e n g t h n == matrix[i].length n==matrix[i].length
  • 1 ≤ m, n ≤ 10 1 \le m, n \le 101m,n10
  • − 100 ≤ m a t r i x [ i ] [ j ] ≤ 100 -100 \le matrix[i][j] \le 100 100matrix[i][j]100

Example :

  • Example 1:

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,3,6,9,8,7,4,5]
  • Example 2:

输入:matrix = [[1,2,3,4],[5,6,7,8],[9,10,11,12]]
输出:[1,2,3,4,8,12,11,10,9,5,6,7]

Ideas

  1. Initialize four boundary variables top, bottom, left, and right to respectively represent the upper boundary, lower boundary, left boundary, and right boundary of the current spiral traversal.

  2. Initialize a result array result to store the elements obtained by traversal.

  3. Use a loop to simulate the process of spiral traversal. The loop conditions are top <= bottom and left <= right, that is, the upper boundary does not exceed the lower boundary and the left boundary does not exceed the right boundary.

  4. In each round of loop, the upper boundary is first traversed from left to right, the traversed elements are added to the result array, and then the upper boundary is moved down one row, that is, top is increased.

  5. Then traverse the right boundary from top to bottom, add the traversed elements to the result array, and then reduce the right boundary by one column to the left, that is, reduce right.

  6. If the upper boundary still does not exceed the lower boundary at this time, continue to traverse the lower boundary from right to left, add the traversed elements to the result array, and then move the lower boundary up one line, that is, reduce the bottom.

  7. Finally, if the left boundary still does not exceed the right boundary at this time, continue to traverse the left boundary from bottom to top, add the traversed elements to the result array, and then expand the left boundary by one column to the right, that is, increase left.

Repeat the above steps until all elements have been traversed.

Code

Solution one:
class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        if not matrix:
            return []

        m, n = len(matrix), len(matrix[0])
        result = []
        top, bottom, left, right = 0, m - 1, 0, n - 1

        while top <= bottom and left <= right:
            # 从左到右遍历上边界
            for j in range(left, right + 1):
                result.append(matrix[top][j])
            top += 1

            # 从上到下遍历右边界
            for i in range(top, bottom + 1):
                result.append(matrix[i][right])
            right -= 1

            # 检查是否需要继续遍历
            if top <= bottom:
                # 从右到左遍历下边界
                for j in range(right, left - 1, -1):
                    result.append(matrix[bottom][j])
                bottom -= 1

            if left <= right:
                # 从下到上遍历左边界
                for i in range(bottom, top - 1, -1):
                    result.append(matrix[i][left])
                left += 1

        return result
Solution 2
class Solution(object):
    def spiralOrder(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: List[int]
        """
        if not matrix or not matrix[0]: return []
        M, N = len(matrix), len(matrix[0])
        left, right, up, down = 0, N - 1, 0, M - 1
        res = []
        x, y = 0, 0
        dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)]
        cur_d = 0
        while len(res) != M * N:
            res.append(matrix[x][y])
            if cur_d == 0 and y == right:
                cur_d += 1
                up += 1
            elif cur_d == 1 and x == down:
                cur_d += 1
                right -= 1
            elif cur_d == 2 and y == left:
                cur_d += 1
                down -= 1
            elif cur_d == 3 and x == up:
                cur_d += 1
                left += 1
            cur_d %= 4
            x += dirs[cur_d][0]
            y += dirs[cur_d][1]
        return res

Please add image description

3. 0498. Diagonal traversal

3.1 General idea of ​​the question

Description : Given a size m × nm \times nm×n matrixmat matmat

Requirement : Return all elements in this matrix in an array in diagonal traversal order.

Description :

  • m = = m a t . l e n g t h m == mat.length m==mat.length
  • n = = m a t [ i ] . l e n g t h n == mat[i].length n==mat[i].length
  • 1 ≤ m, n ≤ 1 0 4 1 \le m, n \le 10^41m,n104
  • 1 ≤ m × n ≤ 1 0 4 1 \le m \times n \le 10^41m×n104
  • − 1 0 5 ≤ mat [i] [j] ≤ 1 0 5 -10^5 \mat[i][j] \le 10^5105mat[i][j]105

Example :

  • Example 1:

输入:mat = [[1,2,3],[4,5,6],[7,8,9]]
输出:[1,2,4,7,5,3,6,8,9]
  • Example 2:
输入:mat = [[1,2],[3,4]]
输出:[1,2,3,4]

Ideas

  1. Initialize an empty result array result to store the elements obtained by traversal.

  2. Traverse the diagonal elements of a matrix. There are two directions for diagonals: from top left to bottom right and from top right to bottom left. We can use a flag variable up to indicate the current direction of diagonal traversal. Initially, up is True, meaning from top left to bottom right.

  3. During diagonal traversal, the coordinates of the next element are determined based on the value of up. If up is True, the coordinates of the next element are (i-1, j+1). If up is False, the coordinates of the next element are (i+1, j-1), where (i, j) are the coordinates of the current element.

  4. During the traversal process, check whether the coordinates are out of bounds. If they are out of bounds, the coordinates need to be adjusted. When up is True, if i decreases to less than 0, it means that you need to move down one row and set up to False. When up is False, if j decreases to less than 0, it means that you need to move one column to the right and set up to True.

  5. At each step, the traversed elements are added to the result array.

  6. Continue traversing until all elements have been traversed.

Code

class Solution:
    def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]:
        m, n, ans = len(mat), len(mat[0]), []
        for k in range(m + n - 1):
            if not k % 2:
                ans += [mat[x][k-x] for x in range(min(m - 1, k), max(-1, k - n),-1)]
            else:
                ans += [mat[x][k-x] for x in range(max(0, k - n + 1), min(k + 1, m))]
        return ans

Please add image description

Solution two:

if not mat:
            return []

        m, n = len(mat), len(mat[0])
        result = []
        up = True  # 初始方向为从左上到右下
        i, j = 0, 0  # 初始位置为左上角

        while len(result) < m * n:
            result.append(mat[i][j])
            if up:
                # 向右上移动
                if i > 0 and j < n - 1:
                    i -= 1
                    j += 1
                else:
                    up = False
                    if j < n - 1:
                        j += 1
                    else:
                        i += 1
            else:
                # 向左下移动
                if i < m - 1 and j > 0:
                    i += 1
                    j -= 1
                else:
                    up = True
                    if i < m - 1:
                        i += 1
                    else:
                        j += 1

        return result

Please add image description

Guess you like

Origin blog.csdn.net/qq_42859625/article/details/132887937