力扣-初级算法-数组

1.Python内置列表函数和方法

列表创建和操作

  • list(): 创建一个空列表或将可迭代对象转换为列表。
    
  • append(x): 在列表末尾添加一个元素x。   
    
  • extend(iterable): 通过添加iterable中的所有元素来扩展列表。 
    
  • insert(i, x): 在指定位置i插入元素x。
    
  • remove(x): 移除列表中值为x的第一个元素。 
    
  • pop([i]): 移除并返回列表中指定位置i的元素,若不指定则移除并返回最后一个元素。
    
  • clear(): 移除列表中的所有元素。
    
  • index(x,[start[,end]]): 返回列表中第一个值为x的元素的索引。
    
  • count(x): 返回列表中值为x的元素数量。   
    
  • sort(key=None, reverse=False): 对列表中的元素就地排序。     
    
  • reverse(): 反转列表中的元素。   
    
  • copy(): 返回列表的浅拷贝。
    
  • [expression for item in iterable]: 使用列表综合生成新列表。
    

2.算法题

2.1 删除排序数组中的重复项(双指针)

题目

给你一个 非严格递增排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。然后返回 nums 中唯一元素的个数。

考虑 nums 的唯一元素的数量为 k ,你需要做以下事情确保你的题解可以被通过:

更改数组 nums ,使 nums 的前 k 个元素包含唯一元素,并按照它们最初在 nums 中出现的顺序排列。nums 的其余元素与 nums 的大小不重要。
返回 k 。

示例

输入:nums = [0,0,1,1,1,2,2,3,3,4]
输出:5, nums = [0,1,2,3,4]
解释:函数应该返回新的长度 5 , 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。不需要考虑数组中超出新长度后面的元素。

双指针解法
class Solution(object):
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if not nums:
            return 0
        slow=0
        for i in range(1,len(nums)):
            if nums[i] != nums[slow]:
                slow+=1
                nums[slow] = nums[i]
                
        return slow+1
分析
  • 时间复杂度:利用双指针,一次遍历即可去重,时间复杂度为O(n)
  • 空间复杂度:不使用任何与输入大小成比例的额外空间,空间复杂度为O(1)

2.2 买卖股票的最佳时机 II

题目

给你一个整数数组 prices ,其中 prices[i] 表示某支股票第 i 天的价格。

在每一天,你可以决定是否购买和/或出售股票。你在任何时候 最多 只能持有 一股 股票。你也可以先购买,然后在 同一天 出售。

返回 你能获得的 最大 利润 。

示例

输入:prices = [7,1,5,3,6,4]
输出:7
解释:在第 2 天(股票价格 = 1)的时候买入,在第 3 天(股票价格 = 5)的时候卖出, 这笔交易所能获得利润 = 5 - 1 = 4。
随后,在第 4 天(股票价格 = 3)的时候买入,在第 5 天(股票价格 = 6)的时候卖出, 这笔交易所能获得利润 = 6 - 3 = 3。
最大总利润为 4 + 3 = 7 。

解法
class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        if len(prices)<=1:
            return 0
        count=0
        for i in range(1,len(prices)):
            if prices[i]>prices[i-1]:
                count+=prices[i]-prices[i-1]
        return count
分析
  • 时间复杂度:循环时间复杂度为O(n),条件判断和累加时间复杂度为O(1),综合,时间复杂度为O(n)。
  • 空间复杂度:算法使用的额外空间是常数,不随输入规模增长,故空间复杂度为O(1)。

2.3 旋转数组

题目

给定一个整数数组 nums,将数组中的元素向右轮转 k 个位置,其中 k 是非负数。

示例

输入: nums = [1,2,3,4,5,6,7], k = 3
输出: [5,6,7,1,2,3,4]

解法1
class Solution(object):
    def rotate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        k = k % len(nums)

        tmp = nums[:len(nums)-k]
        nums[:k] = nums[len(nums)-k:]
        nums[k:] = tmp
分析
  • 时间复杂度:O(n)
  • 空间复杂度:O(n)
解法2
class Solution(object):
    def rotate(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        k = k % len(nums)
        nums[:] = nums[len(nums)-k:] + nums[:len(nums)-k] 
分析
  • 时间复杂度:O(n),遍历整个列表
  • 空间复杂度:O(n),因为创建了新的切片
解法3
在这里插入代码片

2.4 只出现一次的数字

题目

给你一个 非空 整数数组 nums ,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

你必须设计并实现线性时间复杂度的算法来解决此问题,且该算法只使用常量额外空间。

示例

输入:nums = [2,2,1]
输出:1

解法
class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        res = 0
        for i in range(len(nums)):
            res = res^nums[i]
        return res
分析

异或运算,相异为真,相同为假,所以a^ a =0,0^a = a
因为异或运算 满足交换律所以数组经过异或运算,单独的值就剩下了

  • 时间复杂度:O(N)
  • 空间复杂度:O(1)

2.5 两个数组的交集 II

题目

给你两个整数数组 nums1 和 nums2 ,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。

示例

输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4]
输出:[4,9]

解法1 (字典)
class Solution(object):
    def intersect(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        dict1 = dict(Counter(nums1))
        dict2 = dict(Counter(nums2))
        dict3 = {}
        list = []
        for key in dict1:
            if key in dict2:
                dict3[key]=min(dict1[key],dict2[key])

        for key,count in dict3.items():
            list.extend([key]*count)
        return list
解法2 (双指针)
class Solution(object):
    def intersect(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        p1,p2=0,0
        res=[]
        nums1 = sorted(nums1)
        nums2 = sorted(nums2)
        while p1<len(nums1) and p2<len(nums2):
            if nums1[p1]==nums2[p2]:
                res.append(nums1[p1])
                p1+=1
                p2+=1
            elif nums1[p1]<nums2[p2]:
                p1+=1
            else:
                p2+=1
        return res

2.6 加一

题目

给定一个由 整数 组成的 非空 数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

示例

输入:digits = [1,2,3]
输出:[1,2,4]
解释:输入数组表示数字 123。

解法
class Solution(object):
    def plusOne(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
    
        s = ''.join([str(d) for d in digits])
        sd = int(s)+1
        digits = [int(d) for d in str(sd)]
        return digits
分析
  • 时间复杂度:O(N)
  • 空间复杂度:O(N)

2.7 移动零

题目

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

请注意 ,必须在不复制数组的情况下原地对数组进行操作。

示例

输入: nums = [0,1,0,3,12]
输出: [1,3,12,0,0]

解法1
class Solution(object):
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        
        for i in range(len(nums)-1,-1,-1):
            if nums[i]==0:
                del nums[i]
                nums.append(0)
分析
  • 时间复杂度:O(N²),因为删除nums[i]最差需要O(N)时间
  • 空间复杂度:O(1)
解法2
class Solution(object):
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        p=0
        for i in range(len(nums)):
            if nums[i]!=0:
                nums[p]=nums[i]
                p+=1
        for i in range(p,len(nums)):
            nums[i]=0
分析
  • 时间复杂度:O(N)
  • 空间复杂度:O(1)

2.8 两数之和

题目

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案

示例

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

解法
class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        d = {}
        
        for i in range(len(nums)):
            if target-nums[i] in d:
                return [d[target-nums[i]],i]
            else:
                d[nums[i]]=i
分析
  • 时间复杂度:O(N)
  • 空间复杂度:O(N)

2.9 有效的数独

题目

请你判断一个 9 x 9 的数独是否有效。只需要 根据以下规则 ,验证已经填入的数字是否有效即可。

数字 1-9 在每一行只能出现一次。
数字 1-9 在每一列只能出现一次。
数字 1-9 在每一个以粗实线分隔的 3x3 宫内只能出现一次。(请参考示例图)

注意:

一个有效的数独(部分已被填充)不一定是可解的。
只需要根据以上规则,验证已经填入的数字是否有效即可。
空白格用 '.' 表示。
示例

输入:board =
[[“5”,“3”,“.”,“.”,“7”,“.”,“.”,“.”,“.”]
,[“6”,“.”,“.”,“1”,“9”,“5”,“.”,“.”,“.”]
,[“.”,“9”,“8”,“.”,“.”,“.”,“.”,“6”,“.”]
,[“8”,“.”,“.”,“.”,“6”,“.”,“.”,“.”,“3”]
,[“4”,“.”,“.”,“8”,“.”,“3”,“.”,“.”,“1”]
,[“7”,“.”,“.”,“.”,“2”,“.”,“.”,“.”,“6”]
,[“.”,“6”,“.”,“.”,“.”,“.”,“2”,“8”,“.”]
,[“.”,“.”,“.”,“4”,“1”,“9”,“.”,“.”,“5”]
,[“.”,“.”,“.”,“.”,“8”,“.”,“.”,“7”,“9”]]
输出:true

解法
class Solution:
    def isValidSudoku(self, board: List[List[str]]) -> bool:
        a = [[0]*9 for _ in range(9)]
        b = [[0]*9 for _ in range(9)]
        c = [[0]*9 for _ in range(9)]
        for i in range(9):
            for j in range(9):
                if board[i][j] != '.':
                    num=int(board[i][j]) - 1
                    n = i//3+(j//3)*3
                    if a[i][num]==1 or b[j][num]==1 or c[n][num]==1:
                        return False
                    else:
                        a[i][num]=1
                        b[j][num]=1
                        c[n][num]=1
        return True

2.10 旋转图像

题目

给定一个 n × n 的二维矩阵 matrix 表示一个图像。请你将图像顺时针旋转 90 度。

你必须在 原地 旋转图像,这意味着你需要直接修改输入的二维矩阵。请不要 使用另一个矩阵来旋转图像。

示例

输入:matrix = [[1,2,3],[4,5,6],[7,8,9]]
输出:[[7,4,1],[8,5,2],[9,6,3]]

解法
class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        n = len(matrix)
        tmp = [[0]*n for _ in range(n)]
        
        for i in range(n):
            for j in range(n):
                tmp[i][j] = matrix[n-1-j][i]
        matrix[:]=tmp
分析
  • 时间复杂度:O(N²)
  • 空间复杂度:O(N²)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值