초보자: 배열 및 문자열

표적

1. 배열과 동적 배열의 차이점을 이해합니다.

2. 배열 및 동적 배열의 기본 작업에 익숙합니다.

3. 다차원 배열을 이해하고 2차원 배열의 사용을 마스터할 수 있습니다.

4. 현의 개념과 현의 다양한 특성을 이해한다.

5. 실제 문제를 해결하기 위해 이중 포인터 기술을 사용할 수 있습니다.

배열 소개

数组를 기준으로 정렬하는 데 사용되는 기본 데이터 구조입니다 存储元素的集合. 그러나 배열의 각 요소는 索引배열로 식별할 수 있으므로 요소에 임의로 액세스할 수 있습니다.

배열은 하나 이상의 차원을 가질 수 있습니다. 여기서는 一维数组선형 배열이라고도 하는 로 시작합니다.

동적 배열 소개

배열에는 가 있으므로 固定的容量초기화 시 배열의 크기를 지정해야 합니다. 때로는 매우 불편하고 잠재적으로 낭비가 될 수 있습니다.

动态数组이와 같이 대부분의 프로그래밍 언어는 여전히 임의 액세스 목록 데이터 구조인 내장 를 제공하지만 大小是可变的.

배열의 중간 인덱스 찾기

정수 유형의 배열이 주어지면  배열의 "가운데 인덱스"를 반환하는 메서드를 nums작성합니다 .

우리는 다음과 같이 배열 중심 인덱스를 정의합니다 . 배열 중심 인덱스의 왼쪽에 있는 모든 요소의 합은 오른쪽에 있는 모든 요소의 합과 같습니다.

배열에 중앙 인덱스가 없으면 -1을 반환해야 합니다. 배열에 하나 이상의 중앙 인덱스가 있는 경우 왼쪽에 가장 가까운 인덱스를 반환해야 합니다.

예 1:

输入: 
nums = [1, 7, 3, 6, 5, 6]
输出: 3
解释: 
索引3 (nums[3] = 6) 的左侧数之和(1 + 7 + 3 = 11),与右侧数之和(5 + 6 = 11)相等。
同时, 3 也是第一个符合要求的中心索引。

예 2:

输入: 
nums = [1, 2, 3]
输出: -1
解释: 
数组中不存在满足此条件的中心索引。

설명하다:

  • nums 길이 범위는 입니다  [0, 10000].
  • 둘 중 하나는  범위의 정수 nums[i] 입니다  .[-1000, 1000]
class Solution:
    def pivotIndex(self, nums: List[int]) -> int:
        if len(nums) < 3:
            return -1
        for i in range(len(nums)):
            if sum(nums[:i]) == sum(nums[i+1:]):
                return i
        return -1
        

다른 데이터의 2배 이상인 가장 큰 숫자

주어진 배열에는 nums항상 최대 요소가 있습니다.

배열에서 가장 큰 요소가 배열의 다른 숫자마다 적어도 두 배인지 찾습니다.

그렇다면 가장 큰 요소의 인덱스를 반환하고 그렇지 않으면 -1을 반환합니다.

예 1:

输入: nums = [3, 6, 1, 0]
输出: 1
解释: 6是最大的整数, 对于数组中的其他整数,
6大于数组中其他元素的两倍。6的索引是1, 所以我们返回1.

 

예 2:

输入: nums = [1, 2, 3, 4]
输出: -1
解释: 4没有超过3的两倍大, 所以我们返回 -1.

 

힌트:

  1. nums 길이 범위는 입니다 [1, 50].
  2. 각  nums[i] 정수의 범위는  [0, 100].
class Solution:
    def dominantIndex(self, nums: List[int]) -> int:
        nums_max = max(nums)
        ind = nums.index(nums_max)
        tmp = []
        for item in nums:
            if nums_max >= 2 * item or item == nums_max:
                tmp.append(item)
        if len(tmp) == len(nums) :
            return ind
        else:
            return -1

하나 추가

비어 있지 않은 정수 배열로 표현되는 음수가 아닌 정수가 주어 지면 숫자 에 1을 더합니다 .

가장 높은 숫자는 배열의 맨 앞에 저장되며 배열의 각 요소는 단일 숫자만 저장합니다.

이 정수는 정수 0이 아닌 다른 0으로 시작하지 않는다고 가정할 수 있습니다.

예 1:

输入: [1,2,3]
输出: [1,2,4]
解释: 输入数组表示数字 123。

예 2:

输入: [4,3,2,1]
输出: [4,3,2,2]
解释: 输入数组表示数字 4321。
class Solution:
    def plusOne(self, digits: List[int]) -> List[int]:
        n=len(digits)
        for i in range(n-1,-1,-1):
            if digits[i]<9:
                digits[i]+=1
                return digits
            else:
                digits[i]=0
        return [1]+digits

검색 캐럿 위치

정렬된 배열과 대상 값이 주어지면 배열에서 대상 값을 찾고 해당 인덱스를 반환합니다. 대상 값이 배열에 없으면 순서대로 삽입할 위치를 반환합니다. 배열에 중복 요소가 없다고 가정할 수 있습니다.

예 1:

输入: [1,3,5,6], 5
输出: 2
class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        for i in range(0, len(nums)):
            if nums[i] >= target:
                return i
            elif i == len(nums) - 1:
                return len(nums)

병합 간격

일련의 간격이 주어지면 겹치는 모든 간격을 병합합니다.

예 1:

输入: [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6].
class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        res = []
        intervals.sort()
        for i in intervals:
            if not res or res[-1][1]<i[0]:
                res.append(i)
            else:
                res[-1][1] = max(res[-1][1],i[1])
        return res

2D 데이터 소개

다차원 배열은 테이블이나 행렬과 같은 복잡한 구조에 더 적합합니다.

학습 목표:

1. 2차원 배열은 어떻게 메모리에 저장되는가?

2. 2차원 배열을 사용하여 문제를 해결하는 방법

회전 행렬

N × N 각 픽셀의 크기가 4바이트인 행렬로 표현되는 이미지가 제공됩니다  . 이미지를 90도 회전하는 알고리즘을 설계하십시오.

추가 메모리 공간을 차지하지 않고 수행할 수 있습니까?

예 1:

给定 matrix = 
[
  [1,2,3],
  [4,5,6],
  [7,8,9]
],

原地旋转输入矩阵,使其变为:
[
  [7,4,1],
  [8,5,2],
  [9,6,3]
]
class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        n = len(matrix)
        # 先上下镜面翻转
        for i in range(n // 2):
            for j in range(n):
                matrix[i][j], matrix[n - 1 - i][j] = matrix[n - 1 - i][j], matrix[i][j]
        
        # 再主对角线翻转
        for i in range(n):
            for j in range(i):
                matrix[j][i], matrix[i][j] = matrix[i][j], matrix[j][i]

제로 매트릭스

M × N 행렬의 요소가 0인 행과 열을 지우는 알고리즘을 작성하세요.

예 1:

입력:
[
  [1,1,1],
  [1,0,1],
  [1,1,1]
]
출력:
[
  [1,0,1],
  [0,0,0],
  [1,0 ,1]
]

class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        rownum = len(matrix)
        colnum = len(matrix[0])
        row = [False for i in range(rownum)]
        col = [False for i in range(colnum)]
        for i in range(rownum):
            for j in range(colnum):
                if matrix[i][j] == 0:
                    row[i] = True
                    col[j] = True
        for i in range(rownum):
            for j in range(colnum):
                if row[i] or col[j]:
                    matrix[i][j] = 0

대각선 순회

M x N 요소(M 행, N 열)가 있는 행렬이 주어지면 아래 그림과 같이 대각선 순회 순서로 이 행렬의 모든 요소를 ​​반환하십시오.

 

예:

입력:
[
 [ 1, 2, 3 ],
 [ 4, 5, 6 ],
 [ 7, 8, 9 ]
]

출력: [1,2,4,7,5,3,6,8,9]

설명하다:


저자: LeetCode
링크: https://leetcode-cn.com/leetbook/read/array-and-string/cuxq3/
출처: LeetCode
저작권은 저자에게 있습니다. 상업용 전재의 경우 저자에게 승인을 요청하고 비상업적 전재의 경우 출처를 표시하십시오.

class Solution:
    def findDiagonalOrder(self, matrix: List[List[int]]) -> List[int]:
        m = len(matrix)
        if not m:
            return []
        n = len(matrix[0])
        if not n:
            return []
        matrix_num = m*n
 
        count = 0
        x = y = 0
        li = []
        direction = "up"
        while count < matrix_num:
            count += 1
            li.append(matrix[x][y])
            # 右上方向
            if direction == "up":
                # 无需调换方向的条件(1.x>0 碰到上壁前, 2.y<n-1碰到右壁前)
                if x > 0 and y < n-1:
                     x -= 1
                     y += 1
                     continue
                else:
                    direction = "down"
                    # 碰到上壁 x=0
                    if x == 0 and y < n-1:
                        y += 1
                    # 碰到右壁
                    elif y == n-1:
                        x += 1
            # 左下方向
            else:
                # 无需调换方向的条件(1.x<m 碰到下壁前, 2.y>0 碰到右壁前)
                if x < m-1 and y > 0:
                    x += 1
                    y -= 1
                    continue
                else:
                    direction = "up"
                    if x == m-1:
                        y += 1
                    elif y == 0 and x < m-1:
                        x += 1
        return li

문자열 소개

문자열은 문자의 배열입니다.

학습 목표:

1. 문자열의 기본 연산, 특히 배열에서 사용할 수 없는 고유한 연산에 익숙함
2. 서로 다른 비교 함수 간의 차이점 이해
3. 문자열이 변경 가능하고 연결 프로세스에서 문제를 일으키는지 이해
4. 유능함 정렬, 하위 문자열, 문자열 일치 등과 같은 문자열과 관련된 기본 문제를 해결합니다.

가장 긴 공통 접두사

문자열 배열에서 가장 긴 공통 접두사를 찾는 함수를 작성하십시오.

공통 접두사가 없으면 빈 문자열 ""을 반환합니다.

예 1:

입력: ["꽃","흐름","비행"]
출력: "fl"
예 2:

입력: ["dog","racecar","car"]
출력: ""
설명: 입력에 대한 공통 접두어가 없습니다.
설명하다:

모든 입력에는 소문자 az만 포함됩니다.

저자: LeetCode
링크: https://leetcode-cn.com/leetbook/read/array-and-string/ceda1/
출처: LeetCode
저작권은 저자에게 있습니다. 상업용 전재의 경우 저자에게 승인을 요청하고 비상업적 전재의 경우 출처를 표시하십시오.

class Solution:
    def longestCommonPrefix(self, strs: List[str]) -> str:
        import os
        return os.path.commonprefix(strs)

가장 긴 회문 부분 문자열

문자열 s가 주어지면 s에서 가장 긴 회문 부분 문자열을 찾습니다. s의 최대 길이는 1000이라고 가정할 수 있습니다.

예 1:

입력: "babad"
출력: "bab"
참고: "aba"도 유효한 대답입니다.
예 2:

입력: "cbbd"
출력: "bb"

작성자: LeetCode
링크: https://leetcode-cn.com/leetbook/read/array-and-string/conm7/
출처: LeetCode
저작권은 작성자에게 있습니다. 상업용 전재의 경우 저자에게 승인을 요청하고 비상업적 전재의 경우 출처를 표시하십시오.

class Solution:
    def longestPalindrome(self, s: str) -> str:
        max_length = 0
        start = 0
        for i in range(len(s)):
            if i - max_length >= 1 and s[i-max_length-1: i+1] == s[i-max_length-1: i+1][::-1]:
                start = i - max_length - 1
                max_length +=2
                continue
            if i - max_length >= 0 and s[i-max_length: i+1] == s[i-max_length: i+1][::-1]:
                start = i - max_length
                max_length += 1
        return s[start: start+max_length]

문자열의 단어 뒤집기

문자열이 주어지면 문자열의 각 단어를 하나씩 뒤집습니다.

 

예 1:

입력: " the sky is blue"
 출력:  " blue is sky the"
class Solution:
    def reverseWords(self, s: str) -> str:
        li = s.split(" ")
        str = ""
        for i in range(len(li)-1, -1, -1):
            if li[i]:
                str = str + li[i] + " "
        # 因为最后一个单词多加了一个空格符“ ”          
        return str[:-1] 

문자열 일치 알고리즘: KMP

KMP(Knuth–Morris–Pratt) 알고리즘은 개선된 문자열 매칭 알고리즘으로, 핵심은 매칭 실패 후 정보를 사용하여 패턴 문자열과 기본 문자열 간의 일치 횟수를 최소화하여 빠른 매칭의 목적을 달성하는 것입니다. 시간 복잡도는 O(m+n)O(m+n)O(m+n)입니다.

int match (char* P, char* S){ // KMP 算法
    int* next = buildNext(P); // 构造 next 表
    int m = (int) strlen (S), i = 0; // 文本串指针
    int n = (int) strlen(P), j = 0; //模式串指针
    while (j < n && i < m) // 自左向右逐个比对字符
        if (0 > j || S[i] == P[j]) // 若匹配,或 P 已移除最左侧
            {i++; j++} // 则转到下一字符
        else
            j = next[j]; // 模式串右移(注意:文本串不用回退)
    delete [] next; // 释放 next 表
    return i - j;
}

strStr() 구현

strStr() 함수를 구현합니다.

건초 더미 문자열과 바늘 문자열이 주어지면 건초 더미 문자열에서 바늘 문자열의 첫 번째 위치(0부터 시작)를 찾습니다. 존재하지 않는 경우 -1을 반환합니다.

예 1:

입력: haystack = "hello", needle = "ll"
출력: 2
예 2:

입력: haystack = "aaaaa", needle = "bba"
출력: -1
설명:

needle이 빈 문자열일 때 무엇을 반환해야 합니까? 이것은 인터뷰에서 물어볼 좋은 질문입니다.

이 질문의 경우 needle이 빈 문자열이면 0을 반환해야 합니다. 이는 C의 strstr() 정의와 Java의 indexOf() 정의와 일치합니다.

저자: LeetCode
링크: https://leetcode-cn.com/leetbook/read/array-and-string/cm5e2/
출처: LeetCode
저작권은 저자에게 있습니다. 상업용 전재의 경우 저자에게 승인을 요청하고 비상업적 전재의 경우 출처를 표시하십시오.

class Solution:
    def strStr(self, haystack: str, needle: str) -> int:
        for i in range(0, len(haystack) - len(needle) + 1):
            if haystack[i: i + len(needle)] == needle:
                return i
        return -1

2점슛 기술

투 포인터 기술 시나리오 1

배열의 요소를 뒤집습니다. 예를 들어 배열은 ['l', 'e', ​​'e', ​​'t', 'c', 'o', 'd', 'e'], 반전 후 ['e ', 'd', 'o', 'c', 't', 'e', ​​'e', ​​'l'].

def reverseString(self, s):
        i, j = 0, len(s) - 1
        while i < j:
            s[i], s[j] = s[j], s[i]
            i += 1
            j -= 1

역 문자열

입력 문자열을 반전시키는 함수를 작성하십시오. 입력 문자열은 문자의 char[] 배열로 제공됩니다.

다른 배열에 추가 공간을 할당하지 마십시오. 이 문제를 해결하려면 O(1) 추가 공간을 사용하여 입력 배열을 제자리에서 수정해야 합니다.

배열의 모든 문자는 ASCII 코드 테이블에서 인쇄 가능한 문자라고 가정할 수 있습니다.

 

예 1:

입력: ["h","e","l","l","o"]
출력: ["o","l","l","e","h"]
예 2:

输入:["H","a","n","n","a","h"]
输出:["h","a","n","n","a", "시간"]

저자: LeetCode
링크: https://leetcode-cn.com/leetbook/read/array-and-string/cacxi/
출처: LeetCode
저작권은 저자에게 있습니다. 상업용 전재의 경우 저자에게 승인을 요청하고 비상업적 전재의 경우 출처를 표시하십시오.

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        j=-1
        for i in range(0,len(s)//2):
            t=s[i]
            s[i]=s[j]
            s[j]=t
            j-=1

이중 포인터 기술 시나리오 2

두 개의 비동기 포인터를 사용하여 빠른 포인터와 느린 포인터 문제를 해결하십시오.


고전적인 문제부터 시작하겠습니다.

배열  nums 과 값이  주어지면 제자리에 있는  값과 동일한 모든 요소를 ​​제거   하고 제거된 배열의 새 길이를 반환 val해야 합니다  .val

 

def removeElement(self, nums: List[int], val: int) -> int:
    slow = 0
    n = len(nums)
    for fast in range(n):
        if nums[fast] != val:
            nums[slow] = nums[fast]
            slow += 1
    return slow

요소 제거

배열 nums 및 값 val이 주어지면 값이 val과 동일한 모든 요소를 ​​제자리에서 제거하고 제거된 배열의 새 길이를 반환해야 합니다.

추가 배열 공간을 사용하지 마십시오. O(1) 추가 공간만 사용하고 입력 배열을 제자리에서 수정해야 합니다.

요소의 순서를 변경할 수 있습니다. 새 길이를 초과하는 배열의 요소를 고려할 필요가 없습니다.

 

예 1:

주어진 숫자 = [3,2,2,3], 값 = 3,

함수는 새로운 길이 2를 반환해야 하며 nums의 처음 두 요소는 모두 2입니다.

새 길이를 초과하는 배열의 요소를 고려할 필요가 없습니다.

설명하다:

반환된 값이 정수인데 출력 결과가 배열인 이유는 무엇입니까?

입력 배열은 "참조에 의해" 전달됩니다. 즉, 함수 내의 입력 배열에 대한 수정 사항이 호출자에게 표시됩니다.

다음과 같이 내부 작업을 상상할 수 있습니다.

// 숫자는 "참조"로 전달됩니다. 즉, 실제 매개변수의 사본을 만들지 마십시오.
int len ​​= removeElement(nums, val);

// 함수의 입력 배열에 대한 수정 사항은 호출자에게 표시됩니다.
// 함수가 반환한 길이에 따라 해당 길이 내에서 배열의 모든 요소를 ​​출력합니다.
for (int i = 0; i < len; i++) {     print(nums[i]); }

저자: LeetCode
링크: https://leetcode-cn.com/leetbook/read/array-and-string/cwuyj/
출처: LeetCode
저작권은 저자에게 있습니다. 상업용 전재의 경우 저자에게 승인을 요청하고 비상업적 전재의 경우 출처를 표시하십시오.

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        while val in nums:
            nums.remove(val)
        return len(nums)

요약

어레이 관련 기술

1, 여기에 몇 가지 다른 배열과 같은 데이터 구조가 있지만 몇 가지 다른 속성이 있습니다.

String
Hash Table
Linked List
Queue
Stack
2에서 언급했듯이 내장 함수를 호출하여 배열을 정렬할 수 있습니다. 그러나 널리 사용되는 일부 정렬 알고리즘의 원리와 그 복잡성을 이해하는 것이 유용합니다.

3. 이진 검색은 정렬된 배열에서 특정 요소를 검색하는 중요한 기술이기도 합니다.

4. 이 장에서는 이중 포인터 기술을 소개했습니다. 이 기술을 유연하게 사용하는 것은 쉽지 않습니다. 이 트릭은 다음을 해결하는 데에도 사용할 수 있습니다.

연결 리스트에서 느린 포인터와 빠른 포인터의 문제
슬라이딩 윈도우 문제
5, 이중 포인터 기술은 때때로 포인터의 이동 전략을 설계하는 데 도움이 되는 그리디 알고리즘과 관련이 있습니다. 

추천

출처blog.csdn.net/weixin_42748604/article/details/106097306