#66 Plus One
You are given a large integer represented as an integer array
digits
, where eachdigits[i]
is theith
digit of the integer. The digits are ordered from most significant to least significant in left-to-right order. The large integer does not contain any leading0
's.Increment the large integer by one and return the resulting array of digits.
解题思路:
指针指向最后一位。
1.指针所指不是9的话,直接改成+1后输出
2.所指是9的话,改成0后指针往前移,然后再继续重复1,2步骤。
3.直到指针遇到非9或移出数列。移出后,用insert在队列头加1,然后输出。
class Solution:
def plusOne(self, digits: List[int]) -> List[int]:
last_idx = len(digits) - 1
while last_idx > -1:
if digits[last_idx] == 9:
digits[last_idx] = 0
last_idx -= 1
else:
digits[last_idx] += 1
return digits
digits.insert(0, 1)
return digits
runtime:
想不到可以优化的地方了。看一下forum:
这个本来是我一开始想到的方法,但是最后输出的时候又要拆回每个数位我觉得很麻烦(当时没有想到用st()的方法表达每个数位)就没有用这种思路了。不过没想到runtime确实是快了一半。暂时无法理解。
重新写了下:
class Solution:
def plusOne(self, digits: List[int]) -> List[int]:
num = 0
for i in range(len(digits)):
num += digits[i]*(10**(len(digits)-1-i))
return [int(i) for i in str(num+1)]
runtime是44ms,51.48%。还是比pow(10, len(digits) - 1 - i)要慢一点(38ms,71.66%)。
还可以不用指针,直接idx从后往前用for循环。
再凭理解重写:
class Solution:
def plusOne(self, digits: List[int]) -> List[int]:
for i in range(len(digits)-1, -1, -1):
if digits[i] != 9:
digits[i] += 1
return digits
else:
digits[i] = 0
return [1] + digits
runtime还是差不多,48ms。 就这样吧。下一题。
#498 Diagonal Traverse
Given an
m x n
matrixmat
, return an array of all the elements of the array in a diagonal order.
解题思路:
第一眼看懵了。不知道啥规律。后来发现:
如果把input看成一个矩阵row * column的话,那么起点一定是位于第一行第一列的数,这里一定是1。斜对角移动读取数值,只有两种方向,一个是横-1,竖+1;另外一个是横+1,竖-1。
当横或竖的数值超出了矩阵之外之后,比如说row < 0 或 row >= 给定值m,column同理,那么超出的项退回矩阵内。退回的办法分为两种,一种是如果出界位置处于矩阵的右上方,那么row 上下移;如果出界位置处于矩阵的左下方,则column左右移。然后读取方向调转。
退回之后,有两种可能,一种是回到了矩阵里,那么直接读取数值,然后继续斜对角移动;
要么就还是矩阵外(只有pointer走到了左下角和右上角才会出现这种情况),就先斜对角移动,然后读取数值,然后再斜对角移动。
for循环(m*n)次。每次循环一定会完成一次有效值的读取。以及斜对角移动一次。
class Solution:
def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]:
result = []
r = len(mat)
c = len(mat[0])
row = column = 0
direction = 1
if r*c == 1:
return [1]
def within(row, column): # to see whether the pointer is within the matrix
if -1 < row < r and -1 < column < c:
return True
return False
def move_diagonally(row, column, direction): # move the pointer diagonally
row -= direction
column += direction
return row, column
for i in range(r*c):
if not within(row, column):
if row < 0 or column >= c: # pointer is above or on the right
row += direction # move downward or upward
elif row >= r or column < 0: # pointer is on the left or below
column -= direction # move rightward or leftward
direction *= -1 # change direction
if not within(row, column):
row, column = move_diagonally(row, column, direction)
result.append(mat[row][column])
row, column = move_diagonally(row, column, direction)
return result
runtime:
哭了😭 看一下哪里还可以优化的。不行,这个实在是太难了,还是参考一下油管https://www.youtube.com/watch?v=0DnG0Kc9M2Ehttps://www.youtube.com/watch?v=0DnG0Kc9M2E的解法:
这位大哥是把矩阵切割成了多个对角线list,对角线的个数 = 行数 + 列数 - 1。
然后每个对角线的数值的行和列的idx之和是相等的。以此填充对角线list的数值。
如果对角线的序号是奇数,那么是倒序提取放入最后的结果list中。
如果对角线的序号是偶数,那么是从小到大提取放入最后结果list中。
试着重写一下:
class Solution:
def findDiagonalOrder(self, mat: List[List[int]]) -> List[int]:
if not mat or not mat[0]:
return []
result = []
r, c = len(mat), len(mat[0])
diagonals = [[] for i in range(r + c - 1)]
for i in range(r):
for j in range(c):
diagonals[i+j].append(mat[i][j])
for x in range(r+c-1):
if x % 2 == 0:
result.extend(diagonals[x][::-1])
else:
result.extend(diagonals[x])
return result
runtime:
emmm, 只是快了一点点?再看一下有没有更快的办法……
暂时没找到其他解法了,前面看189ms的也是同样的思路。
不过一个有意思的发现是,如果遍历矩阵是左下右上的话,那么同个level的idx之和是一样的。
如果遍历矩阵是左上右下的话,那么同个level的idx之差也是一样的。这个规律以后可以用上。