【基本数据结构】python array数组 [easy] leetcode1,53,88,118,121,217,350,566

数组leetcode有关题目(easy) python

使用语言python,解法的时间复杂度和空间复杂度都在平均水平之上,个别有90%左右的,不做具体说明。但是可以提升效率的点会进行说明,用粗体标出。考点和简要的中文也都在文章中标注出来了。

通过leetcode上数组的简单题目我们知道,基本的需要我们掌握的基础的知识有:python中可以对数组进行的操作和通过算法设计得到结果并且让程序更快。下面分别来通过题目和代码说明下我的理解:

熟悉python中数组的操作

leetcode 217. Contains Duplicate 考集合使用

这一题就很简单了,只要数组里面有两个一样的,返回True,没有一样的返回False。因此直接遍历,并且把遍历过的元素放在一个集合里面,后面的如果在这个集合里面说明有重复的。

class Solution:
    def containsDuplicate(self, nums: List[int]) -> bool:
        s = set()
        for num in nums:
            if num in s:
                return True
            else:
                s.add(num)
        return False

leetcode 88. Merge Sorted Array 考切片使用

这个其实很简单了…直接放代码啦~

class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        if n == 0:
            return
        if m == 0:
            nums1[0:] = nums2
            return
        nums1[m : len(nums1)] = nums2
        nums1.sort()

提升效率: python数组可以一大坨直接赋值,效率比遍历快很多 nums1[m : len(nums1)] = nums2 (感觉这题的数据给的这么的奇怪就是为了这个知识点啊~~)切片整个赋值的用处!

算法

leetcode53. Maximum Subarray 找最大和

简单的来说,就是需要找到一串和最大的子串,下面先让我们通过下图看看一些可能的情况:
// 里面的MaxNow是现在为止最大的和,MoveOn是可能最大的和,根据图来解释下到底是什么意思。
(1)首先我们按照一般的思维从左到右加和,假设前面全部是负的,那么我们一定不要,因此我们假设全部是正的。这是第一个阶段,这个时候的MaxNow和MoveOn是一样的。
(2)第二个阶段的时候,出现了负数,因此有两个选择,要不继续加和,要不放弃前面所有的,因为是连续的子串。但是如左右两种情况,如果是左边,负数其实很少,那么左边可以稍微抵消一部分最后还是正的,遇到后面的正的时候,我们就知道不应该抛弃前面的。但是同时,也有可能负数很多,前面的不能抵消,因此我们也可能在后面找到最大的子串。
(3)因为这个原因,我们让MoveOn去继续的加和,只要不为小于0的数字就说明不会被抵消而保留,并且让MaxNow始终等于两个数字里面的最大值。
(4)假如MoveOn不幸的为负数了,我们只能抛弃前面的,让MoveOn归零并且继续往前加,再不断的比较MaxNow和MoveOn后来的值,看看需不需要改变MaxNow。
(5)根据以上的思路我们可以写出下面的代码。
在这里插入图片描述

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        MaxNow, MoveOn = nums[0],nums[0]
        for i in range(1,len(nums)):
            if MoveOn < 0 :
                MoveOn = nums[i]
            else:
                MoveOn += nums[i]
            MaxNow = max(MaxNow,MoveOn)
        return MaxNow

leetcode1. Two Sum 找给定和

这个就是找到数组里面相加之和等于给定的目标值的数字,并且给出两个数字的位置的索引,且根据题目,这样的解只有一个,就很简单了,思路是直接开始遍历,看看后面有没有,有的话先记下来第一个数字的索引,再在数组的后面的部分遍历,找到那个数字,记下索引,返回就可。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        index = []
        for i in range(len(nums)):
            if target - nums[i] in nums[i+1:]:
                index.append(i)
                break
        for j in range(i+1,len(nums)):
            if nums[j] == target - nums[i]:
                index.append(j)
                return index

leetcode350. Intersection of Two Arrays II 找相同

直接放代码~比较长度是因为我觉得这样会快一些,不过其实最后就是50%左右的水平 ~

class Solution:
    def intersect(self, nums1: List[int], nums2: List[int]) -> List[int]:
        len1, len2 = len(nums1),len(nums2)
        intersect = []
        if len1> len2:
            for i in nums2:
                if i in nums1:
                    nums1.remove(i)
                    intersect.append(i)
        else:
            for i in nums1:
                if i in nums2:
                    nums2.remove(i)
                    intersect.append(i) 
        return intersect

121. Best Time to Buy and Sell Stock 找顺序最大差值

这一题在评论区有个哥们讲的很清楚,比我表达的还清楚,根据他的说法,我本来在两个分支都写了right+=1,后来改出来if循环了,结果快了一些

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        if len(prices) == 1:
            return 0 
        left = 0
        right = 1
        max_profit = 0
        while right <= len(prices)-1:
            if prices[right]-prices[left]<0:
                left = right
            else:
                max_profit = max(max_profit,prices[right]-prices[left])
            right+=1
        return max_profit

最后的时间复杂度还行,空间复杂度还是均值
在这里插入图片描述

566. Reshape the Matrix

这一题感觉只要知道矩阵是一行行写怎么计算就可以
(我最开始的时候import numpy写的居然也可以,但是效率太低了哈哈哈…不过实际中,大家都会用numpy吧?)

class Solution:
    def matrixReshape(self, mat: List[List[int]], r: int, c: int) -> List[List[int]]:
        row = len(mat)
        col = len(mat[0])
        if r*c != row*col:
            return mat
        reshapeMatrix = [[0]*c for i in range(r)]
        m,n = 0,0
        for i in range(r*c):
            reshapeMatrix[m][n] = mat[i//col][i%col]
            if n<c-1: n+= 1
            else: 
                m+=1
                n = 0
        return reshapeMatrix

这一题我最后做到runtime是95.08%,memory是81.87%。但是其实我写了三版,这一版最快。主要是矩阵的赋值的地方不一样。但是原因很奇怪,因为这样手动计算复杂度没区别啊!
我放在下面:
在这里插入图片描述

118. Pascal’s Triangle

这个只要索引能够对上就很简单啦!这个的runtime做到了95.6%
在这里插入图片描述

class Solution:
    def generate(self, numRows: int) -> List[List[int]]:
        pascal = [[0]*(i+1) for i in range(numRows)]
        count = 1
        for i in range(numRows*(numRows+1)//2):
            index = i - (count-1)*count//2  # positionin the row
            if index > count-1:
                count+=1
                index = i - (count-1)*count//2  # positionin the row
            if index == 0 or index == count-1:
                pascal[count-1][index] = 1
            else:
                pascal[count-1][index] = pascal[count-2][index-1]+pascal[count-2][index]
        return pascal
        

算法结合数据结构

leetcode36. Valid Sudoku

这题的思路其实非常的简单,即需要分别判断,行有没有重复,列有没有重复,以及每一个小的sub方阵有没有重复。关键的是怎么写可以效率更高。一开始我是这样写的,使用了列表解析,后面的小方阵的判断是直接写了坐标。

class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        for i in board:
            extract = [j for j in i if j!='.']
            if len(extract)!= len(set(extract)):
                return False
        for i in range(9):
            extract = [j[i] for j in board if j[i]!='.']
            if len(extract)!= len(set(extract)):
                return False
        location = [(0,0),(3,0),(6,0),
                    (0,3),(3,3),(6,3),
                    (0,6),(3,6),(6,6)]
        loc_box = [(0,0), (0,1), (0,2),
                   (1,0), (1,1), (1,2),
                   (2,0), (2,1), (2,2)]
        for k in location:
            i = k[0]
            j = k[1]
            extract = [board[m+i][n+j] for m,n in loc_box if board[m+i][n+j]!='.']
            if len(extract)!= len(set(extract)):return False
        return True

后来看见评论区里面更快的方式是:

class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        
        def init_mapper():
            return {i: {} for i in range(9)}
        
        mapper_row = init_mapper()
        mapper_col = init_mapper()
        mapper_box = init_mapper()
        pos_box = {(0,0): 0, (0,1): 1, (0,2): 2,
                   (1,0): 3, (1,1): 4, (1,2): 5,
				   (2,0): 6, (2,1): 7, (2,2): 8,}
        
        for r, row in enumerate(board):
            for c, item in enumerate(row):
                if item == ".":
                    continue
                b = pos_box[(r // 3, c // 3)]
                if mapper_row[r].get(item, False) or mapper_col[c].get(item, False) or mapper_box[b].get(item, False):
                    # repeated item
                    return False
                else:
                    mapper_row[r][item] = True
                    mapper_col[c][item] = True
                    mapper_box[b][item] = True
                
        return True

这个里面很巧妙的使用了 enumerate,这样相当于可以把所有的信息利用坐标的方式进行存储
于是可以一次遍历直接得到结果,而不用遍历三次,效率很低。这个字典的使用是很值得学习的。(查找判断很方便)

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值