python3-算法刷题-数组-遍历技巧-更新中

参考:https://labuladong.github.io/algo/2/20/26/

【中等】151. 反转字符串中的单词

https://leetcode.cn/problems/reverse-words-in-a-string/
给你一个字符串 s ,请你反转字符串中 单词 的顺序。
单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。
返回 单词 顺序颠倒且 单词 之间用单个空格连接的结果字符串。
注意:输入字符串 s中可能会存在前导空格、尾随空格或者单词间的多个空格。返回的结果字符串中,单词间应当仅用单个空格分隔,且不包含任何额外的空格。

思路:常规的思路是先strip去掉前后空格,再split分割成word数组,然后倒序," ".join()即可。另一种思路则是先反转整个字符串,然后反转每个word。

class Solution:
    def reverseWords(self, s: str) -> str:
        t = []
        i = 0
        while i < len(s):
            # 非空格则直接加入
            if s[i] != ' ':
                t.append(s[i])
                i += 1
            else:
                # 寻找空格的停止之处
                while i < len(s) and s[i] == ' ':
                    i += 1
                # 不要开头和结尾处的空格,只加入中间的空格
                if len(t) != 0 and i < len(s):
                    t.append(' ')
        length = len(t)
        # 先反转整个字符串
        self.reverse(t, 0, length - 1)
        i = 0
        while i < length:
            j = i
            while j < length:
                # 找单词
                if j + 1 == length or t[j + 1] == ' ' :
                    self.reverse(t, i, j)
                    i = j + 2
                    break
                j += 1  

        return "".join(t)

    def reverse(self, s:list, i:int, j:int):
        while i < j:
            s[i], s[j] = s[j], s[i]
            i += 1
            j -= 1
        

【中等】48. 旋转图像

https://leetcode.cn/problems/rotate-image
给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。
你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。
在这里插入图片描述
思路:先按对角线反转,将行变成列,然后左右反转。而左右反转实际是一维数组的反转。
如果是逆时针旋转90°,就是按另一条对角线反转(i→n-1-j ,j→n-1-i),再左右。

class Solution:
    # 反转一维数组
    def reverse(self, arr:List[int], i:int, j:int) -> None:
        while i < j:
            arr[i], arr[j] = arr[j], arr[i]
            i += 1
            j -= 1

    def rotate(self, matrix: List[List[int]]) -> None:
        m = len(matrix)
        n = len(matrix[0])
        for i in range(m):
            # 注意这里是i开始
            for j in range(i, n):
                matrix[i][j], matrix[j][i] = matrix[j][i], matrix[i][j]
        for i in range(m):
            self.reverse(matrix[i], 0, n-1)

思路: (感觉这种更好记忆)每次都是[x,y]→[y][n-x]
[i, j] → [n-j, i]
[n-j, i] → [n-i, n-j]
[n-i, n-j] → [j, n-i]
[j, n-i] → [i, j]

size = len(matrix)
        n = size - 1
        for i in range(size // 2):
            for j in range((size + 1) // 2):
                matrix[i][j], matrix[n - j][i], matrix[n - i][n - j], matrix[j][n - i] \
                    = matrix[n-j][i], matrix[n - i][n - j], matrix[j][n - i], matrix[i][j]
        return matrix

1886. 判断矩阵经轮转后是否一致

https://leetcode.cn/problems/determine-whether-matrix-can-be-obtained-by-rotation

给你两个大小为 n x n 的二进制矩阵 mat 和 target 。现 以 90 度顺时针轮转 矩阵 mat 中的元素 若干次 ,如果能够使 mat 与 target 一致,返回 true ;否则,返回 false 。
在这里插入图片描述
思路: 跟上一题完全一致,只不过可能旋转4次罢了。

class Solution:
    def findRotation(self, mat: List[List[int]], target: List[List[int]]) -> bool:
        size = len(mat)
        n = size - 1
        for k in range(4):
            for i in range(size // 2):
                for j in range((size + 1) // 2):
                    mat[i][j], mat[n-j][i], mat[n-i][n-j], mat[j][n-i] \
                    = mat[n-j][i], mat[n-i][n-j], mat[j][n-i], mat[i][j]
            if mat == target:
                return True
        return False

【中等】54. 螺旋矩阵

https://leetcode.cn/problems/spiral-matrix/
给你一个 m 行 n 列的矩阵 matrix ,请按照 顺时针螺旋顺序 ,返回矩阵中的所有元素。
在这里插入图片描述
思路:直接模拟行进方向,按顺序。注意,每次遍历完要修改的边界,是当前块需要判断的条件。

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        ans = []
        left = 0 # 左边界
        right = len(matrix[0]) - 1 # 右边界
        up = 0 # 上边界
        down = len(matrix) - 1# 下边界
        size = len(matrix) * len(matrix[0])
        while len(ans) < size:
            # 顶部从左往右
            if up <= down:
                for i in range(left, right + 1):
                    ans.append(matrix[up][i])
                # 上边界要改
                up += 1
            # 右侧从上到下
            if left <= right:
                for i in range(up, down + 1):
                    ans.append(matrix[i][right])
                right -= 1
            # 底部从右往左
            if up <= down:
                for i in range(right, left-1, -1):
                    ans.append(matrix[down][i])
                down -= 1
            # 左侧从下往上
            if left <= right:
                for i in range(down, up-1, -1):
                    ans.append(matrix[i][left])
                left += 1
        return ans

【简单】剑指 Offer 29. 顺时针打印矩阵

https://leetcode.cn/problems/shun-shi-zhen-da-yin-ju-zhen-lcof/
与上一题完全一致,只是用例中含[],因此需要加一条判断:if len(matrix) == 0: return ans

【中等】59. 螺旋矩阵 II

https://leetcode.cn/problems/spiral-matrix-ii/
给你一个正整数 n ,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的 n x n 正方形矩阵 matrix 。
输入:n = 3
输出:[[1,2,3],[8,9,4],[7,6,5]]
思路:与54.螺旋矩阵是一样的。需要改的只有引用每个ans[i][j]时。

class Solution:
    def generateMatrix(self, n: int) -> List[List[int]]:
        left = 0 # 左边界
        right = n - 1 # 右边界
        up = 0 # 上边界
        down = n - 1# 下边界
        size = n * n
        # 初始化全0数组
        ans = [[0 for i in range(n)] for j in range(n)]
        num = 1
        while num <= size:
            # 顶部从左往右
            if up <= down:
                for i in range(left, right + 1):
                    ans[up][i] = num
                    num += 1 
                # 上边界要改
                up += 1
            # 右侧从上到下
            if left <= right:
                for i in range(up, down + 1):
                    ans[i][right] = num
                    num += 1
                right -= 1
            # 底部从右往左
            if up <= down:
                for i in range(right, left-1, -1):
                    ans[down][i] = num
                    num += 1
                down -= 1
            # 左侧从下往上
            if left <= right:
                for i in range(down, up-1, -1):
                    ans[i][left] = num
                    num += 1
                left += 1
        return ans

1572. 矩阵对角线元素的和

https://leetcode.cn/problems/matrix-diagonal-sum/
在这里插入图片描述
思路:
双指针吧。如果是奇数边长,加一个中心值。

class Solution:
    def diagonalSum(self, mat: List[List[int]]) -> int:
        s = 0
        left = 0
        size = len(mat)
        right = size - 1
        r = 0
        while left < right:
            s += mat[r][left] + mat[r][right] + mat[size - 1 - r][left] + mat[size - 1 - r][right]
            r += 1
            left += 1
            right -= 1
        if left == right:
            s += mat[size // 2][left]
        return s

448. 找到所有数组中消失的数字

https://leetcode.cn/problems/find-all-numbers-disappeared-in-an-array
给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

示例 1:
输入:nums = [4,3,2,7,8,2,3,1]
输出:[5,6]
示例 2:
输入:nums = [1,1]
输出:[2]

进阶:你能在不使用额外空间且时间复杂度为 O(n) 的情况下解决这个问题吗? 你可以假定返回的数组不算在额外空间内。

思路:
可以通过符号确认某个位置是否访问过。需要注意的是,python中负数index有意义。

class Solution:
    def findDisappearedNumbers(self, nums: List[int]) -> List[int]:
        for i in range(len(nums)):
            if nums[i] > 0:
                a = nums[i] - 1
            else:
                a = -1 * nums[i] - 1
            if nums[a] > 0:
                nums[a] *= -1

        ans = []
        for i in range(len(nums)):
            if nums[i] > 0:
                ans.append(i + 1)
        return ans

类似的题目是:

442. 数组中重复的数据

https://leetcode.cn/problems/find-all-duplicates-in-an-array

给你一个长度为 n 的整数数组 nums ,其中 nums 的所有整数都在范围 [1, n] 内,且每个整数出现 一次 或 两次 。请你找出所有出现 两次 的整数,并以数组形式返回。

你必须设计并实现一个时间复杂度为 O(n) 且仅使用常量额外空间的算法解决此问题。

示例 1:
输入:nums = [4,3,2,7,8,2,3,1]
输出:[2,3]

思路: 这里只需要记录当前访问位置是负数时候的index。因为表示这个Index+1的值已经访问过了。

class Solution:
    def findDuplicates(self, nums: List[int]) -> List[int]:
        ans = []
        for i in range(len(nums)):
            if nums[i] > 0:
                a = nums[i] - 1
            else:
                a = -1 * nums[i] - 1
            if nums[a] < 0:
                ans.append( a + 1)
            nums[a] *= -1
        #print(nums)
        return ans

896. 单调数列

https://leetcode.cn/problems/monotonic-array/

如果数组是单调递增或单调递减的,那么它是 单调 的。
如果对于所有 i <= j,nums[i] <= nums[j],那么数组 nums 是单调递增的。 如果对于所有 i <= j,nums[i]> = nums[j],那么数组 nums 是单调递减的。
当给定的数组 nums 是单调数组时返回 true,否则返回 false。

思路: 用两个bool记录递增或递减。如果两个bool都是False,那么就是不单调了。

class Solution:
    def isMonotonic(self, nums: List[int]) -> bool:
        inc = desc = True
        for i in range(len(nums) - 1):
            if nums[i] < nums[i+1]:
                desc = False
            elif nums[i] > nums[i+1]:
                inc = False
        return inc or desc

1539. 第 k 个缺失的正整数

https://leetcode.cn/problems/kth-missing-positive-number

给你一个 严格升序排列 的正整数数组 arr 和一个整数 k 。

请你找到这个数组里第 k 个缺失的正整数。

示例 1:
输入:arr = [2,3,4,7,11], k = 5
输出:9
解释:缺失的正整数包括 [1,5,6,8,9,10,12,13,…] 。第 5 个缺失的正整数为 9 。

思路: k+1表示当前的正整数存在,所以往后一位,推迟。

class Solution:
    def findKthPositive(self, arr: List[int], k: int) -> int:
        for i in arr:
            if i <= k:
                k += 1
        return k

1608. 特殊数组的特征值

https://leetcode.cn/problems/special-array-with-x-elements-greater-than-or-equal-x

给你一个非负整数数组 nums 。如果存在一个数 x ,使得 nums 中恰好有 x 个元素 大于或者等于 x ,那么就称 nums 是一个 特殊数组 ,而 x 是该数组的 特征值 。

注意: x 不必 是 nums 的中的元素。

如果数组 nums 是一个 特殊数组 ,请返回它的特征值 x 。否则,返回 -1 。可以证明的是,如果 nums 是特殊数组,那么其特征值 x 是 唯一的 。

示例 1:
输入:nums = [3,5]
输出:2
解释:有 2 个元素(3 和 5)大于或等于 2 。

思路: 先降序排序,如果存在x,那么[0, x-1]一定都是大于等于x的,而或者x已在数组外,或者[x]一定是小于x的。

class Solution:
    def specialArray(self, nums: List[int]) -> int:
        nums.sort(reverse=True)
        s = len(nums)
        for i in range(1, s+1):
            if nums[i - 1] >= i and (i == s or nums[i] < i):
                return i
        return -1
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值