【LeetCode数组相关】中心下标、旋转图像、零矩阵

LeetCode724.寻找数组的中心下标

给你一个整数数组 nums ,请计算数组的 中心下标 。

数组 中心下标 是数组的一个下标,其左侧所有元素相加的和等于右侧所有元素相加的和。

如果中心下标位于数组最左端,那么左侧数之和视为 0 ,因为在下标的左侧不存在元素。这一点对于中心下标位于数组最右端同样适用。

如果数组有多个中心下标,应该返回 最靠近左边 的那一个。如果数组不存在中心下标,返回 -1 。

示例 1:

输入:nums = [1, 7, 3, 6, 5, 6]
输出:3(我认为这里是6才对)
解释:
中心下标是 3 。
左侧数之和 sum = nums[0] + nums[1] + nums[2] = 1 + 7 + 3 = 11 ,
右侧数之和 sum = nums[4] + nums[5] = 5 + 6 = 11 ,二者相等。

最开始的思路:

1、将原始的数组翻转得到一个新数组,然后同时遍历两个数组,当相加结果相同时返回当前下标对应的数

问题:

显然,这种方法只适用于对称的数组,是特例

2、朴素的思想是双层for循环去遍历数组,相加之后比较得出结果

问题:

因为需要确认边界,所以慢,容易超时

解题思路:
使用前缀法

有这样的规律,

记数组全部元素之和为numSum,当遍历到第i个元素时,其左侧元素总和为leftSum,右侧则可以表示为全部元素之和减掉左侧元素之和再减掉当前第i个元素,即

rightSum = numSum - leftSum - nums[i]

如果左右元素之和相等则找到中心下标

代码实现:

class Solution:
    def pivotIndex(self, nums: List[int]) -> int:
        numSum = sum(nums) #求数组总和
        leftSum = 0
        for i in range(len(nums)):
            # 前缀法
            if numSum - leftSum - nums[i] == leftSum: 
                #左右和相等,则返回当前下标
                return i
            #左侧总和累加
            leftSum += nums[i]
        return -1

LeetCode48.旋转图像

给你一幅由 N × N 矩阵表示的图像,其中每个像素的大小为 4 字节。请你设计一种算法,将图像旋转 90 度。

不占用额外内存空间能否做到?

示例 1:

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

原地旋转输入矩阵,使其变为:
[
  [7,4,1],
  [8,5,2],
  [9,6,3]
]

示例 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]
]

解题思路:

需要找规律,如果用暴力法。确定每个数变化后的位置再一个一个修改,算法复杂度会比较高

翻转法是本题一个比较好的结题思路

先将目标矩阵镜像翻转

[                         
  [1,2,3],
  [4,5,6],   
  [7,8,9]
]
镜像↓
[
  [3,2,1],
  [6,5,4],     
  [9,8,7]
]

再沿主对角线对折即可

[
  [3,2,1],
  [6,5,4],     
  [9,8,7]
]
主对角线翻转↓
[
  [3,6,9],
  [2,5,8],     
  [1,4,7]
]
图像向左旋转了90°

如果是先主对角线翻转再镜像翻转的话,图像会向右旋转90°

因为题目没有规定方向,所以两种都可以

代码:

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        # 确定matrix长度
        m1= len(matrix)
        # 先用切片操作镜像翻转matrix
        # matrix[:]等于复制了一个一样的matrix
        # matrix[::-1]相当于将对象镜像翻转
        matrix[:] = matrix[::-1] #得到镜像翻转后的matrix
        # 沿主对角线翻转
        # 注意len不是从0开始的
        for i in range(m1):
            for j in range(i):
                matrix[j][i], matrix[i][j] = matrix[i][j], matrix[j][i]

ps:这里有个python的小技巧--切片操作

例如,

a = 'saiodhoia'
b = a[:]
c = a[::-1]
print(b)
-->saiodhoia
print(c)
-->aiohdoias

# 上述操作对list依然有效

LeetCode73.零矩阵

编写一种算法,若M × N矩阵中某个元素为0,则将其所在的行与列清零。

示例 1:

输入:
[
  [1,1,1],
  [1,0,1],
  [1,1,1]
]
输出:
[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]

示例 2:

输入:
[
  [0,1,2,0],
  [3,4,5,2],
  [1,3,1,5]
]
输出:
[
  [0,0,0,0],
  [0,4,5,0],
  [0,3,1,0]
]

解题思路:

很容易想到用遍历的方式去做。遇到0怎么处理是关键

一种朴素的解法是使用两次遍历

第一次遍历确定0的位置并保存下来,第二次根据第一次保存的位置信息修改矩阵中的值

代码:

class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        # 获取内外层数组长度
        m1, m2 = len(matrix), len(matrix[0])
        # 定义两个数组用于存放位置信息,1表示在原数组中该位置不为0
        row, column = [1]*m1, [1]*m2

        # 第一遍遍历,定位出0的位置
        for i in range(m1):
            for j in range(m2):
                if matrix[i][j] == 0:
                    # 找到0就标记一下
                    row[i] = 0
                    column[j] = 0
        
        # 第二遍遍历,按照位置信息修改矩阵
        for i in range(m1):
            for j in range(m2):
                if row[i] == 0 or column[j] == 0:
                    matrix[i][j] = 0

还有更优解,之后有空再优化

posted @ 2022-05-24 20:16  dayceng  阅读(58)  评论(0)    收藏  举报