Leetcode刷题笔记-array

本文记录了作者在LeetCode上刷题的心得,主要涉及数组相关的题目,包括最大加号符号、樱桃采摘、糖果 crush、矩阵中最长连续 1 的线等。文章介绍了动态规划和分治法在解决此类问题中的应用,并提供了部分解题思路和代码实现。
摘要由CSDN通过智能技术生成

764. Largest Plus Sign

class Solution:
    def orderOfLargestPlusSign(self, n: int, mines: List[List[int]]) -> int:
        '''
        找最长的十字架
        Algorithms: For each position (i, j) of the grid matrix, we try to extend in each of the four directions (left, right, up, down) as long as possible, then take the minimum length of 1's out of the four directions as the order of the largest axis-aligned plus sign centered at position (i, j).

        Optimizations: Normally we would need a total of five matrices to make the above idea work -- one matrix for the grid itself and four more matrices for each of the four directions. However, these five matrices can be combined into one using two simple tricks:

        For each position (i, j), we are only concerned with the minimum length of 1's out of the four directions. This implies we may combine the four matrices into one by only keeping track of the minimum length.

        For each position (i, j), the order of the largest axis-aligned plus sign centered at it will be 0 if and only if grid[i][j] == 0. This implies we may further combine the grid matrix with the one obtained above.
        '''

        grid = [[n] * n for i in range(n)]
        for i, j in mines:
            grid[i][j] = 0

        for i in range(n):
            l = r = u = d = 0

            for j, k in zip(range(n), reversed(range(n))):
                l = l + 1 if grid[i][j] != 0 else 0
                grid[i][j] = min(l, grid[i][j])

                r = r + 1 if grid[i][k] != 0 else 0
                grid[i][k] = min(r, grid[i][k])

                u = u + 1 if grid[j][i] != 0 else 0
                grid[j][i] = min(u, grid[j][i])
                
                d = d + 1 if grid[k][i] != 0 else 0
                grid[k][i] = min(d, grid[k][i])
        

        res = 0
        for i in range(n):
            for j in range(n):
                res = max(res, grid[i][j])
 
        return res

741. Cherry Pickup

class Solution:
    def cherryPickup(self, grid: List[List[int]]) -> int:
        # dp[x1][y1][x2] to represent the largest ans we can get when first guy (marked as A) at(x1, y2) and second guy(marked as B) at (x2, x1 + y1 - x2)
        # because we can only go right and down, so we have x1 + y1 = x2 + y2 = total steps they go
        # https://leetcode.com/problems/cherry-pickup/discuss/165218/Java-O(N3)-DP-solution-w-specific-explanation
        #     2.  Induction: every time we calculate the maximum of :
        # * dp[x1 - 1][y1][x2] : A down, B right
        # * dp[x1][y1 - 1][x2] : A right, B right
        # * dp[x1 - 1][y1][x2 - 1]: A down, B down
        # * dp[x1][y1 - 1][x2 - 1]: A right, B down
        # if the Max of these values is negative, then we don't have a path to this point
        # else we have: dp[x1][y1][x2] = Max + grid[x1 - 1][y1 - 1] + grid[x2 - 1][y2 - 1](if x1 != x2 && y1 != y2) else we
        # only add once.
        dp = [[[-1 for _ in grid] for _ in grid] for _ in grid]
        dp[0][0][0] = grid[0][0]  # base case A and B all in 0 0 
        n = len(grid)
        for x1 in range(0, n):
            for y1 in range(0, n):
                for x2 in range(0, len(grid)):
                    y2 = x1 + y1 - x2
                    if x1 == y1 == x2 == 0 or y2 < 0 or y2 >= n or grid[x1][y1] == -1 or grid[x2][y2] == -1:
                        continue
                    
                    pre_max = max(dp[x1-1][y1][x2], dp[x1][y1-1][x2], dp[x1-1][y1][x2-1], dp[x1][y1-1][x2-1])
                    if pre_max < 0:
                        continue 
                        
                    dp[x1][y1][x2] = pre_max + grid[x1][y1]
                    if x1 != x2:
                        dp[x1][y1][x2] = dp[x1][y1][x2] + grid[x2][y2]  
                        
                    print(x1, y1, x2, y2, dp[x1][y1][x2])
        return max(0, dp[-1][-1][-1])

723. Candy Crush

class Solution(object):
    def candyCrush(self, board):
        # 只有横着或者竖着连续3个才可以消去。
        # 把满足消去的设置为负数,比如2设置为-2,最后再一起消去
        r, c = len(board), len(board[0])
        found = True
        while found:
            found = False
            for i in xrange(r):
                for j in xrange(c):
                    val = abs(board[i][j])
                    if val == 0: continue
                    # check row
                    if i + 2 < r and abs(board[i+1][j]) == abs(board[i+2][j]) == val:
                        found = True
                        ii = i  # 用ii 避免 下面的 i被修改了
                        while 0 <= ii < r and abs(board[ii][j]) == val:  # 这里注意是ii
                            board[ii][j] = -val
                            ii += 1
                    # check col
                    if j + 2 < c and abs(board[i][j+1]) == abs(board[i][j+2]) == val:
                        found = True
                        while 0 <= j < c and abs(board[i][j]) == val:
                            board[i][j] = -val
                            j += 1
            # 消去
            if found:
                for j in xrange(c):
                    emptyRow = r - 1
                    for i in xrange(r-1, -1, -1):
                        if board[i][j] > 0:
                            board[emptyRow][j] = board[i][j]
                            emptyRow -= 1
                    
                    for i in xrange(emptyRow, -1, -1):
                        board[i][j] = 0
        return board

562. Longest Line of Consecutive One in Matrix

class Solution(object):
    def longestLine(self, M):
        maxlen = 0
        currlen = collections.defaultdict(int)
        for i, row in enumerate(M):
            for j, a in enumerate(row):
                for key in i, j+.1, i+j+.2, i-j+.3:  # j 是列相同的, i+j是anti-diagonals, i-j是diagonals
                    currlen[key] = (currlen[key] + 1) * a
                    # currlen[key] += 1*a 是错误的,如果不连续的要断开
                    maxlen = max(maxlen, currlen[key])
        return maxlen

755. Pour Water

class Solution(object):
    def pourWater(self, heights, V, K):
        for _ in xrange(V):
            idx = -1
            # check left
            for i in xrange(K-1, -1, -1):
                if heights[i] > heights[i+1]:
                    break
                elif heights[i] < heights[i+1]:
                    idx = i
            
            if idx != -1:
                heights[idx] += 1
                continue
            
            # check right
            for i in xrange(K+1, len(heights)):
                if heights[i] > heights[i-1]:
                    break
                elif heights[i] < heights[i-1]:
                    idx = i
            
            if idx != -1:
                heights[idx] += 1
            else:
                heights[K] += 1
        return heights

LeetCode - The World's Leading Online Programming Learning Platform

918. Maximum Sum Circular Subarray

class Solution(object):
    def maxSubarraySumCircular(self, A):
        total = curMax = curMin = 0
        maxSum = float('-inf')
        minSum = float('inf')
        for n in A:
            total += n
            curMax = max(n, curMax+n)
            maxSum = max(maxSum, curMax)
            curMin = min(n, curMin+n)
            minSum = min(minSum, curMin)
        return max(maxSum, total - minSum) if maxSum > 0 else maxSum
            

825. Friends Of Appropriate Ages

class Solution(object):
    def numFriendRequests(self, ages):
        A = [0] * 121
        re = 0
        for age in ages:
            A[age] += 1
        
        # A < B <= 0.5A + 7, A < 0.5A + 7  A < 15 can not make friend request
        for a in xrange(15, 121):
            for b in xrange(int(0.5*a)+7+1, a+1):
                re += A[a] * A[b] if a != b else A[a] * (A[b]-1)
        
        return re

243. Shortest Word Distance

class Solution(object):
    def shortestDistance(self, words, word1, word2):
    
        i1 = i2 = -1
        re = 5000
        for idx, w in enumerate(words):
            if w == word1:
                i1 = idx
            if w == word2:
                i2 = idx
            if i1 != -1 and i2 != -1:
                re = min(re, abs(i1-i2))
        return re

406. Queue Reconstruction by Height

class Solution(object):
    def reconstructQueue(self, people):
        d = {}
        for h, k in people:
            if h not in d:
                d[h] = [[h, k]]
            else:
                d[h].append([h, k])
        
        re = []
        for h in sorted(d.keys(), reverse=True):
            group = sorted(d[h])
            if not re:
                re += group
            else:
                for h, k in group:
                    re.insert(k, [h, k])
                    
        return re

128. Longest Consecutive Sequence

class Solution(object):
    def longestConsecutive(self, nums):

        d = {}
        res = 0
        
        for n in nums:
            if n in d:
                continue 
            
            left = d.get(n-1, 0)  
            right = d.get(n+1, 0)
            Sum = left + right + 1
            res = max(res, Sum)
            d[n] = Sum
            d[n-left] = Sum  # 边缘的2个更新Sum就可以了,中间连续的不需要
            d[n+right] = Sum
            
        return res

718. Maximum Length of Repeated Subarray

DP解法

Given two integer arrays A and B, return the maximum length of an subarray that appears in both arrays.

Example 1:

Input:
A: [1,2,3,2,1]
B: [3,2,1,4,7]
Output: 3
Explanation: 
The repeated subarray with maximum length is [3, 2, 1].

dp[i][j] 的i,j是指的A,B的长度,而不是A,B的下标。比如dp[1][0]是指的长度为1的A 和长度为0的B的位置的比较。当i或者j为0时候,因为长度为0所以重复0,则dp为0.      遍历所有子串,记录重复的长度。

class Solution(object):
    def findLength(self, A, B):
        """
        :type A: List[int]
        :type B: List[int]
        :rtype: int
        """
        dp = [[0]*(len(B)+1) for i in xrange(len(A)+1)]
        
        maxLen = 0
        for i in xrange(1, len(A)+1):
            for j in xrange(1, len(B)+1):
                if A[i-1] == B[j-1]:
                    dp[i][j] = dp[i-1][j-1]+1
                    maxLen = max(maxLen, dp[i][j])
                else:
                    dp[i][j] = 0
                    
        return maxLen
        

795. Number of Subarrays with Bounded Maximum

DP

Suppose dp[i] denotes the max number of valid sub-array ending with A[i]. We use following example to illustrate the idea:

A = [2, 1, 4, 2, 3], L = 2, R = 3

  1. if A[i] < L

For example, i = 1. We can only append A[i] to a valid sub-array ending with A[i-1] to create new sub-array. So we have dp[i] = dp[i-1] (for i > 0)

  1. if A[i] > R:

For example, i = 2. No valid sub-array ending with A[i] exist. So we have dp[i] = 0.
We also record the position of the invalid number 4 here as prev.

  1. if L <= A[i] <= R

For example, i = 4. In this case any sub-array starts after the previous invalid number to A[i] (A[prev+1..i], A[prev+2..i]) is a new valid sub-array. So dp[i] += i - prev

Finally the sum of the dp array is the solution. Meanwhile, notice dp[i] only relies on dp[i-1] (and also prev), we can reduce the space complexity to O(1)

class Solution(object):
    def numSubarrayBoundedMax(self, A, L, R):
        """
        :type A: List[int]
        :type L: int
        :type R: int
        :rtype: int
        """
        dp = 0
        prev = -1
        res = 0
        for i in xrange(len(A)):
            if L<= A[i] <= R:
                dp = i - prev
                res += dp
            elif A[i] < L:
                res += dp
            else:
                dp = 0
                prev = i
        return res

分治法,第K小的数 O(n)

873. Length of Longest Fibonacci Subsequence

A sequence X_1, X_2, ..., X_n is fibonacci-like if:

  • n >= 3
  • X_i + X_{i+1} = X_{i+2} for all i + 2 <= n

Given a strictly increasing array A of positive integers forming a sequence, find the length of the longest fibonacci-like subsequence of A.  If one does not exist, return 0.

(Recall that a subsequence is derived from another sequence A by deleting any number of elements (including none) from A, without changing the order of the remaining elements.  For example, [3, 5, 8] is a subsequence of [3, 4, 5, 6, 7, 8].)

Example 1:

Input: [1,2,3,4,5,6,7,8]
Output: 5
Explanation:
The longest subsequence that is fibonacci-like: [1,2,3,5,8].

Example 2:

Input: [1,3,7,11,12,14,18]
Output: 3
Explanation:
The longest subsequence that is fibonacci-like:
[1,11,12], [3,11,14] or [7,11,18].

dp[i][j] 表示以A[i] 和A[j]结尾的Fib序列的长度。则dp[i][j] = 以 A[j] 和 A[i]-A[j] 结尾的序列。所以要判断A[i]-A[j]是否在A中,并且,A【i】-A[j]要小于A【j】

第一次尝试,通过了23次时,时间超过限制:

class Solution(object):
    def lenLongestFibSubseq(self, A):
        """
        :type A: List[int]
        :rtype: int
        """
        dp = [[2]*i for i in A]
        maxLen = 0
        for i in xrange(len(A)):
            for j in xrange(i):
                if A[i] - A[j] < A[j] and (A[i]-A[j]) in A:
                    dp[i][j] = dp[j][A.index(A[i]-A[j])] + 1
                    maxLen = max(maxLen, dp[i][j])
        return maxLen

改进后:

class Solution(object):
    def lenLongestFibSubseq(self, A):
        """
        :type A: List[int]
        :rtype: int
        """
        dp = collections.defaultdict(int)
        maxLen = 0
        
        s = set(A)


        for i in xrange(len(A)):
            for j in xrange(i):
                if A[i] - A[j] < A[j] and (A[i]-A[j]) in s:
                    dp[A[i], A[j]] = dp.get((A[j], A[i]-A[j]), 2) + 1
                    maxLen = max(maxLen, dp[A[i], A[j]])
        return maxLen

560. Subarray Sum Equals K

第一个解法,时间超过限制,但是简单易懂:
class Solution(object):
    def subarraySum(self, nums, k):
        
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值