59.螺旋矩阵II
螺旋矩阵没有什么算法,就是一道单纯模拟转圈的一道题目,因为转圈的过程需要处理的边界条件很多,所以有难度
那只能从第二个节点开始处理;从第二个节点开始处理,把最后一个节点也处理了(第二条边的处理不包含第一个节点)………………如果处理每条边的时候节点规则都不一样,要考虑的边界条件太多,而且极其容易把自己绕进去……
正确思路:
之前在讲二分法的时候就讲到了循环不变量,那我们在做螺旋矩阵的时候同样要遵循循环不变量的原则。
循环是一圈一圈的循环,不变量则是我们对每条边的处理原则,要坚持一个规则来处理每一条边。
此处按照左闭右开的规则来遍历这一圈
在处理边的时候,只处理第一个节点,最后一个节点不处理;遍历下一条边时,也只处理一个节点,最后一个节点不处理;最后一个节点要留给下一条边来处理;下一条边也是处理第一个节点,往后一直遍历,遍历到倒数第二个节点,这就是左闭右开。
把最后一个节点留给下一条边,作为下一条边的起始位置,大家会发现我转一圈,其实是坚持一个原则,这都是左闭右开,这样我四条边的遍历规则就统一了,把规则统一之后,代码就很好写了。
思路:
#这个循环应该转几圈,应该转n/2这么多圈
#如果n是奇数,例如:3/2=1,也就是转了一圈,还剩下中间的位置如何处理? 只需要最后判断一下
#如果这个n是奇数计算(n%2)==1,如果是奇数,我们对所填充的数组进行单独赋值,将最后一个数字填进去
#进入循环后,每一圈的起始位置不可能是一个固定的数,可以定义一个 start x=0,再定义一个start y=0
#这样我们就定义了一个起起始位置是每一圈都要变的每一圈都要变的,所以我们定义了一个变量,专门来放起始位置。
#起始位置的定义[start x][ start y] =[i][j]
offset = 1
count = 1
while(n/2)
for (j= starty ;j<n-offset;j++){
nums[startx][j] = count++;}
#j小于终止位置,终止位置不包含最后一个元素。终止位置也是随着我们而改变的。所以还需要一个变量来定义它的终止位置。这样我们就遍历了第一行。然后对其他元素进行填充。Count是用来计数的,初始值也为一;
循环完毕之后j已经等于n减offset。此时j。已经指向第一行的最后一个元素,此时j的值是固定的。
到这里第一条横向边遍历完毕,开始遍历第二条(竖)边。这竖向条边的下标为j
坐标是(i,j)这么定义的。
for (i= startx ;i<n-offset;i++){
nums[i][j] = count++;}
然后遍历下方一条横向边。我们修改的又是j的值;这里j等于n减offset。此时j这个值不需要初始化,因为我们所遍历的这个坐标已经走到这个节点了。i和j都是矩阵中的最大值。此时需要知道j的终点在哪里?J>starty,因为我们不处理他的终点位置,坚持左闭右开的原则。
for (;j>starty;j--){
nums[i][j] = count++;}
最后这条边遍历的时候,i已经是最大值。i向上遍历应该大于Startx;这里的每一条边所坚持的原则都是只处理第一个节点,不处理最后一个节点。
for (;i>starty;i--){
nums[i][j] = count++;}
那么我们每转一圈,这个start x和starty,都应该加一;此时结束位置由n-1变为n-2。offset由1变为2。
startx++
starty++
offset++
if ((n%2)==1){
nums[i][j] = count
}
python代码
class Solution:
def generateMatrix(self, n: int) -> List[List[int]]:
startx,starty = 0,0
mid = n//2
count = 1
matrix = [[0]*n for _ in range(n)]
for offset in range(1,mid+1) :
for j in range(starty,n-offset):
matrix[startx][j] = count
count += 1
for i in range(startx,n-offset):
matrix[i][n-offset] = count
count += 1
for j in range(n-offset,starty,-1):
matrix[n-offset][j] = count
count += 1
for i in range(n-offset,startx,-1):
matrix[i][starty] = count
count += 1
starty += 1
startx += 1
if n%2 != 0:
matrix[mid][mid] = count
return matrix
python如何进行模计算?
在Python中,模计算(也称为取模运算或求余运算)是通过 % 操作符实现的。模计算通常用于求出一个数除以另一个数的余数。这里有一个基本的例子来展示如何在Python中进行模计算:
# 示例:计算10除以3的余数
result = 10 % 3
print(result) # 输出: 1
模计算经常用于判断一个数是否可以被另一个数整除(如果余数为0,则可以整除),以及循环索引的计算(如循环遍历数组时,将索引保持在数组长度内的操作)。
注意事项
当使用负数进行模计算时,Python的结果可能与其他编程语言不同。在Python中,结果的符号与被除数(左边的操作数)相同。
# 负数模计算的例子
print(-10 % 3) # 输出: -1,因为余数的符号与被除数相同
print(10 % -3) # 输出: 1,因为余数的符号与被除数相同
当你尝试用0作为除数进行模计算时,Python会抛出一个ZeroDivisionError。
nums = [[0] * n for _ in range(n)]
Python中的一个列表推导式(list comprehension),用于创建一个二维列表(或称为矩阵),其大小为n×n,并且初始时所有元素都被初始化为0。这里的n
是一个已经定义好的整数,表示矩阵的行数和列数
for _ in range(n)
: 这是一个循环,循环n次。这里的_
是一个常用的占位符,表示我们不关心循环的当前迭代值(索引)。range(n)
生成一个从0到n-1的序列,但由于我们不需要这个序列的具体值,所以使用_
来忽略它
[0] * n
: 这部分创建了一个长度为n的列表,其中包含n个0。这个列表是二维列表中的一行。[[0] * n for _ in range(n)]
: 将上述两部分结合起来,对于每一次外层循环(循环n次),都创建一个长度为n、所有元素为0的列表。这些列表(即矩阵的行)被收集到一个更大的列表中,形成了n×n的二维列表(矩阵)简单来说,这行代码就是创建了一个n行n列的二维列表,其中每个元素都被初始化为0。这种结构在编程中非常常见,特别是在需要处理二维空间数据(如图像、网格等)时。
列表生成式
列表生成式(List Comprehension)是Python中一种简洁高效创建列表的方式。它允许你通过一个表达式来生成列表,这个表达式可以是任何有效的Python表达式,并且可以包含循环、条件语句等。列表生成式的基本语法如下:
[expression for item in iterable if condition]
expression
:这是一个关于当前元素的表达式,用于生成列表中的新元素。for item in iterable
:这是一个for循环,遍历可迭代对象(如列表、元组、字符串、集合、字典等)中的每个元素。if condition
(可选):这是一个条件表达式,用于过滤掉那些不满足条件的元素。只有当条件为真时,当前元素才会被包含在结果列表中。squares = [x**2 for x in range(10)] print(squares) # 输出: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] even_squares = [x**2 for x in range(10) if x % 2 == 0] print(even_squares) # 输出: [0, 4, 16, 36, 64] keys = ['a', 'b', 'c'] values = [1, 2, 3] dict_comprehension = {k: v for k, v in zip(keys, values)} print(dict_comprehension) # 输出: {'a': 1, 'b': 2, 'c': 3} matrix = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] flattened = [num for row in matrix for num in row] print(flattened) # 输出: [1, 2, 3, 4, 5, 6, 7, 8, 9]
//运算符:
在Python中,//
运算符被称为整数除法(也称为地板除)运算符。它执行除法运算,但结果总是向下取整到最接近的整数,即使结果是一个负数。这与传统的除法(使用 /
运算符)不同,后者在Python 3中对于整数和浮点数都会返回一个浮点数结果。