Leetcode日练笔记22 #66 #498 Plus One & Diagonal Traverse

#66 Plus One

You are given a large integer represented as an integer array digits, where each digits[i] is the ith 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 leading 0'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 matrix mat, 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=0DnG0Kc9M2Eicon-default.png?t=M4ADhttps://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之差也是一样的。这个规律以后可以用上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值