python数据结构与算法——数组

1:最接近的三数之和
前提是一个排序数组
思路:固定一个(一次遍历),其他双指针。
最接近:与目标值之差

class Solution:
    def threeSumclose(self,nums,target):
        size=len(nums)
        res=float("inf")
        for i in range(size): #一次遍历
            
            if i>0 and nums[i]==nums[i-1]: #防止重复
                continue
            #寻找
            #双指针
            left=i+1
            right=size-1
            while left<right: 
                cur=nums[i]+nums[left]+nums[right]
                if cur==target: 
                    return target
                if abs(res-target)>abs(cur-target):#寻找最接近,更新结果
                    res=cur
                #指针移动
                if cur>target: 
                    right-=1
                else:
                    left+=1
        return res

if __name__=='__main__':
    nums=[1,2,3,4,5,6,10]
    target=16
    solution=Solution()
    result=solution.threeSumclose(nums,target)
    print(result)

2:盛水最多的容器

给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (i, ai) 。
在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (i, ai) 和 (i, 0)。
找出其中的两条线,使得它们与 x 轴共同构成的容器可以容纳最多的水。

说明:你不能倾斜容器,且 n 的值至少为 2。

 

图中垂直线代表输入数组 [1,8,6,2,5,4,8,3,7]。
在此情况下,容器能够容纳水(表示为蓝色部分)的最大值为 49。

思路:

双指针,移动原则为当前左边界和有边界相比较,小的就移动。

 

 

class Solution(object):
    def maxArea(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        size=len(height)
        left=0
        right=size-1
        res=0
        while left<right:
            cur=(right-left)*min(height[right],height[left])
            if cur>res:
                res=cur
            if height[left]<height[right]:
                left+=1
            else:
                right-=1
        return res

3:求最大子数组之和

思路: 贪心算法:在每一步求解的步骤中,要求选择最佳操作(局部最优解)
并希望通过一系列的最优选择产生一个全局的最优解

贪心算满足条件:满足问题的约束条件;局部最优;一旦做出选择,后面步骤不可改变

class Solution:
    def maxArraySum(self,nums):
        
        max_res=0 #局部最优解
        cur_res=0 #当前解
        size=len(nums)
        
        for i in range(size):
            
            cur_res=cur_res+nums[i]#求解
            
            if cur_res>=max_res:#局部最优
                max_res=cur_res
            if cur_res<0:#约束条件,做出选择不可改
                cur_res=0
            
        return max_res

4:移除元素

思路:双指针,将与target值相等的元素放在数组的末尾 

需要两个指针分别从头扫描,从尾部扫描。

class Solution:
    def removeElement(self,nums,val):
        size=len(nums)
        
        left=0
        right=size-1
        
        while left<right:
            #移动
            while left<right and nums[left]!=val: #一直移动left,直到找到val
                left+=1
            while left<right and nums[right]==val: #一直移动right,直到不是val,由于right所指元素是用来交换的
                right-=1
            #交换
            nums[left],nums[right]=nums[right],nums[left]
        
        #计算长度
        res=0    
        for i in range(size):
            if nums[i]==val:
                return i
            res+=1
        return res

if __name__=='__main__':
	nums=[4,4,34,21,123,4,1,2,123]
	val=4
	solution=Solution()
	result=solution.removeElement(nums,val)
	print(result)

5:寻找峰值

寻找峰值
峰值元素是指其值大于左右相邻值的元素。

给定一个输入数组 nums,其中 nums[i] ≠ nums[i+1],找到峰值元素并返回其索引。

数组可能包含多个峰值,在这种情况下,返回任何一个峰值所在位置即可。

你可以假设 nums[-1] = nums[n] = -∞。

示例 1:

输入: nums = [1,2,3,1]
输出: 2
解释: 3 是峰值元素,你的函数应该返回其索引 2。

示例 2:

输入: nums = [1,2,1,3,5,6,4]
输出: 1 或 5 
解释: 你的函数可以返回索引 1,其峰值元

class Solution(object):
    def findPeakElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        left = 0
        right = len(nums) - 1
        while left < right:
            mid = left + (right - left) // 2
            if nums[mid] < nums[mid + 1]:
                
                left = mid + 1 
            else:
                right = mid
        return left
    
if __name__=='__main__':
    nums=[1,2,3,1]
    solution=Solution()
    result=solution.findPeakElement(nums)
    print(result) 

6:旋转数组

旋转图像

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

说明:

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

示例 1:

给定 matrix = 
[
  [1,2,3],
  [4,5,6],
  [7,8,9]
],

原地旋转输入矩阵,使其变为:
[
  [7,4,1],
  [8,5,2],
  [9,6,3]
]

思路:
先对矩阵求转置,之后翻转每一列

#python中二维矩阵的转置用:两层循环,之后a[i][j],a[j][i]=a[j][i],a[i][j]
#翻转每一行,a.reverse(),返回a自己

class Solution(object):
    def rotate(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: None Do not return anything, modify matrix in-place instead.
        """
        m=len(matrix) #行数
        n=len(matrix[0]) #列数
        #转置
        for i in range(m):
            for j in range(i,n): #注意,这里是从i开始
                matrix[i][j],matrix[j][i]=matrix[j][i],matrix[i][j]
        #翻转
        for i in range(m):
            matrix[i].reverse()
        return matrix
    
if __name__=='__main__':
    matrix=[
  [1,2,3],
  [4,5,6],
  [7,8,9]
]
    solution=Solution()
    result=solution.rotate(matrix)
    print(result)

7: 

搜索旋转排序数字组II

假设按照升序排序的数组在预先未知的某个点上进行了旋转。

( 例如,数组 [0,0,1,2,2,5,6] 可能变为 [2,5,6,0,0,1,2] )。

编写一个函数来判断给定的目标值是否存在于数组中。若存在返回 true,否则返回 false。

示例 1:

输入: nums = [2,5,6,0,0,1,2], target = 0
输出: true


示例 2:

输入: nums = 

class Solution(object):
    def search(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: bool
        """
        size=len(nums)
        left=0
        right=size-1
        while left<=right:
            mid=left+(right-left)//2
            if nums[mid]==target:
                return True          
            else:                
                if nums[left]<nums[mid]:#mid左边为正常
                    if nums[mid]>target>=nums[left]:                        
                        right=mid-1
                    else:
                        left=mid+1
                else:
                    if nums[mid]<target<=nums[right]:
                        left=mid+1
                    else:
                        right=mid-1
                        
        return False
    
if __name__=='__main__':
	nums = [2,5,6,0,0,1,2]
	target=3
	solution=Solution()
	result=solution.search(nums,target)
	print(result

8:搜索二维矩阵

class Solution(object):
    def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        if not matrix:
            return False
        m=len(matrix)
        n=len(matrix[0])
        for i in range(m):
            for j in range(n):
                if matrix[i][j]<target:
                    pass
                elif matrix[i][j]==target:
                    return True
                else:
                    return False

9:数组合并

区间合并

给出一个区间的集合,请合并所有重叠的区间。
输入: [[1,3],[2,6],[8,10],[15,18]]
输出: [[1,6],[8,10],[15,18]]
解释: 区间 [1,3] 和 [2,6] 重叠, 将它们合并为 [1,6]

先按首位置进行排序;
接下来,如何判断两个区间是否重叠呢?比如 a = [1,3],b = [2,6]
当 a[1] >= b[0] 说明两个区间有重叠.
但是如何把这个区间找出来呢?
左边位置一定是确定,就是 a[0],而右边位置是 max(a[1], b[1])
所以,我们就能找出整个区间为:[1,4]

 

class Solution(object):
    def merge(self, intervals):
        """
        :type intervals: List[List[int]]
        :rtype: List[List[int]]
        """
        intervals=sorted(intervals)
        size=len(intervals)
        res=[intervals[0]]
        i=1
        while i<size:
            if res[-1][1]>=intervals[i][0]:   
                temp=[res[-1][0],max(res[-1][1],intervals[i][1])]
                res[-1]=temp             
            else:
                res.append(intervals[i])
            i+=1
        return res
    
if __name__=='__main__':
	intervals= [[1,3],[2,6],[8,10],[15,18]]
	solution=Solution()
	result=solution.merge(intervals)
	print(result)   
                

10:三数之和

思路:先排序(前提),再用左右指针法

class Solution:
    def F1(self,a):
        l=len(a)
        if l<3:
            return False
        if l==3:
            if sum(a)==0:
                return a
            else:
                return 0
        sorted(a) #数组排序,注意不很关键啊,要不左右之指针没法用啊
        result=[]
        for i in range(l-2):
            if i > 0 and a[i] == a[i - 1]: #作用避免重复
                continue
            left=i+1 #左指针
            right=l-1 #右指针            
            while left<right: #之所以用这个作为循环结束标志,保证了不重复的指针运动
                if a[left]+a[right]==-a[i]:
                    result.append(([a[i],a[left],a[right]])) 
                    left+=1
                if a[left]+a[right]<-a[i]: #往大的方向走
                    left+=1
                if a[left]+a[right]>-a[i]: #往小的方向走
                    right-=1  
                if left==i:
                    left+=1
        return result                 
a=Solution()
print(a.F1([-5,-1,-2,-3,0,1,2,3,4])) 

11.螺旋矩阵

 

给定一个正整数 n,生成一个包含 1 到 n2 所有元素,且元素按顺时针顺序螺旋排列的正方形矩阵。

示例:

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

思路:模拟旋转过程
确定上下左右四个边界

class Solution(object):
    def generateMatrix(self, n):
        """
        :type n: int
        :rtype: List[List[int]]
        """
        left=0
        right=n-1
        top=0
        bottom=n-1
        
        stop=n*n
        
        matrix=[[0 for i in range(n)] for i in range(n)]
        
        i=1
        while i<=stop:
            
            for k in range(left,right+1):
                matrix[top][k]=i
                i+=1
            top+=1
            
            
            for k in range(top,bottom+1):
                matrix[k][right]=i
                i+=1
            right-=1
            
            
            for k in range(right,left-1,-1):
                matrix[bottom][k]=i
                i+=1
            bottom-=1
            
            for k in range(bottom,top-1,-1):
                matrix[k][left]=i
                i+=1
            left+=1 
            
        return matrix

if __name__=='__main__':
    n=3
    solution=Solution()
    result=solution.generateMatrix(n)
    print(result)    

12:两个数组的交集

定两个数组,编写一个函数来计算它们的交集。

示例 1:

输入: nums1 = [1,2,2,1], nums2 = [2,2]
输出: [2,2]

示例 2:

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

class Solution(object):
    def intersect(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        res=[]
        i=0
        size1=len(nums1)
        size2=len(nums2)
        
        if size1<size2:
            num=nums1
            numm=nums2
        else:
            num=nums2
            numm=nums1
            
            
        for i in range(len(num)):
            if num[i] in numm :
                res.append(num[i])
                numm.pop(numm.index(num[i]))
        
        return res

13:除自身以外的乘积

 

给定长度为 n 的整数数组 nums,其中 n > 1,返回输出数组 output ,其中 output[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积。

示例:

输入: [1,2,3,4]
输出: [24,12,8,6]

说明: 请不要使用除法,且在 O(n) 时间复杂度内完成此题。


思路:入手点,由于题目要求是O(n),所以可能是线性的一层循环遍历。
由于除自身,所以该位置上的乘积为该点左边的乘积*右边的乘积

"""
class Solution(object):
    def productExceptSelf(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        size=len(nums)
        
        #求解i位置上的左乘积
        res_left=[1] 
        cur=1
        for i in range(1,size):
            cur=cur*nums[i-1]
            res_left.append(cur)
            

        #求解i位置上的右乘积
        res_right=[1]
        cur=1
        for i in range(0,size-1)[::-1]:
            cur=cur*nums[i+1]
            res_right.append(cur)
        res_right.reverse()
        
        #左*右
        res=[]
        for i in range(size):
            res.append(res_left[i]*res_right[i])
        
        return res
    
if __name__=='__main__':
	nums=[1,2,3,4]
	solution=Solution()
	result=solution.productExceptSelf(nums)
	print(result)

14:找出目标元素在数组中的开始位置和结束位置

给定一个按照升序排列的整数数组 nums,和一个目标值 target。找出给定目标值在数组中的开始位置和结束位置。

你的算法时间复杂度必须是 O(log n) 级别。

如果数组中不存在目标值,返回 [-1, -1]。

示例 1:

输入: nums = [5,7,7,8,8,10], target = 8
输出: [3,4]

示例 2:

输入: nums = [5,7,7,8,8,10], target = 6
输出: [-1,-1]

 

class Solution(object):
    def searchRange(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: List[int]
        """
        n=len(nums)
        left=0
        right=n
        res=[]
        if not nums:
            return [-1,-1]
        #二分查找
        while left<=right: #注意等号
            mid=left+(right-left)//2
            k=mid
            while k<n and nums[k]==target:#循环遍历右边数组,找出重复元素
                res.append(k)
                k+=1                
            if mid<n and nums[mid]>=target:
                right=mid-1
            else:
                left=mid+1
        if not res:
             return [-1,-1]
        return [min(res),max(res)]
    
if __name__=='__main__':
    nums=[2,2]
    target=3
    solution=Solution()
    result=solution.searchRange(nums,target)
    print(result)

15:求众数

求众数
给定一个大小为 n 的数组,找到其中的众数。众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素。

你可以假设数组是非空的,并且给定的数组总是存在众数。

示例 1:

输入: [3,2,3]
输出: 3

示例 2:

输入: [2,2,1,1,1,2,2]

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        size=len(nums)
        k=size//2
        res=[]
        dict1={}
        
        for i in range(size):
            
            if nums[i] not in dict1 or not dict1:
                dict1[nums[i]]=1
            else:
                dict1[nums[i]]+=1
                
        for i in dict1.keys():
            if dict1[i]>k:
                res.append(i)
                
        return max(res)d

16:矩阵置0

矩阵置0
给定一个 m x n 的矩阵,如果一个元素为 0,则将其所在行和列的所有元素都设为 0。请使用原地算法。

示例 1:

输入: 
[
  [1,1,1],
  [1,0,1],
  [1,1,1]
]
输出: 
[
  [1,0,1],
  [0,0,0],
  [1,0,1]
]

class Solution(object):
    def setZeroes(self, matrix):
        """
        :type matrix: List[List[int]]
        :rtype: None Do not return anything, modify matrix in-place instead.
        """
        m=len(matrix)
        n=len(matrix[0])
        
        row=set()
        col=set()
        #找出0元素所在的行,列
        for i in range(m):
            for j in range(n):
                if matrix[i][j]==0:
                    
                    row.add(i)
                    col.add(j)
        #元素置0
        for i in range(m):
            for j in range(n):
                if i in row or j in col:
                    matrix[i][j]==0
                    
        return matrix
    

17:下个队列

#输入:nums = [1,2,3]

#输出:[1,3,2]

#思路 1: 先找num[i]: 从后往前升序,遇到降序的第一个元素 num[j]: 从后往前遇到的第一个比num[i]大的 两者交换 保证下一个队列大的在前面

# 2: 之后left = i + 1; right = len - 1; [left, right]这个降序序列做双指针反转吧,变为升序

class Solution:
    def nextPermutation(self, nums: List[int]) -> None:
        i = len(nums) - 2
        while i >= 0 and nums[i] >= nums[i + 1]:
            i -= 1
        if i >= 0:
            j = len(nums) - 1
            while j >= 0 and nums[i] >= nums[j]:
                j -= 1
            nums[i], nums[j] = nums[j], nums[i]

        left, right = i + 1, len(nums) - 1
        while left < right:
            nums[left], nums[right] = nums[right], nums[left]
            left += 1
            right -= 1


if __name__ == '__main__':
    n = 3
    solution = Solution()
    print(solution.generateParenthesis(n))

18:搜索旋转排序数组

#序排列的整数数组 nums 在预先未知的某个点上进行了旋转(例如, [0,1,2,4,5,6,7] 经旋转后可能变为 [4,5,6,7,0,1,2] )。
#请你在数组中搜索 target ,如果数组中存在这个目标值,则返回它的索引,否则返回 -1 。
#示例 1:

# 输入:nums = [4,5,6,7,0,1,2], target = 0
# 输出:4
#思路:由于要求复杂度为log(n),因此需要用到二分法。二分法前提是排序数组。对于旋转之后额数组,各一半的排序,因此也可以用。
# mid = right + len //2    nums[0] 和 nums[mid]进行比较确定一定升序的范围 之后 target做比较 移动左右指针
class Solution:
    def search(self, nums, target):
        if not nums:
            return -1
        l, r = 0, len(nums) - 1
        while l <= r:
            mid = (l + r) // 2
            if nums[mid] == target:
                return mid
            if nums[0] <= nums[mid]:
                if nums[0] <= target < nums[mid]:
                    r = mid - 1
                else:
                    l = mid + 1
            else:
                if nums[mid] < target <= nums[len(nums) - 1]:
                    l = mid + 1
                else:
                    r = mid - 1
        return -1

if __name__ == '__main__':
    nums = [4,5,6,7,0,1,2]
    target = 0
    a = Solution()
    c = a.search(nums, target)
    print(c)

19:下一个更大元素

输入: [1,2,1]
输出: [2,-1,2]
解释: 第一个 1 的下一个更大的数是 2;
数字 2 找不到下一个更大的数; 
第二个 1 的下一个最大的数需要循环搜索,结果也是 2。

思路:单调栈, 两次循环。 保证栈一定是个单调递减的, 这里栈中追加的是idx

class Solution:
    def nextGreaterElements(self, nums: List[int]) -> List[int]:
        stack, res = [], [-1] * len(nums)
        for idx, num in enumerate(nums):
            while stack and nums[stack[-1]] < num:
                res[stack.pop()]  = num
            stack.append(idx)
        for idx, num in enumerate(nums):
            while stack and nums[stack[-1]] < num:
                res[stack.pop()]  = num
        return res

20: 每日温度

请根据每日 气温 列表,重新生成一个列表。对应位置的输出为:要想观测到更高的气温,至少需要等待的天数。如果气温在这之后都不会升高,请在该位置用 0 来代替。

例如,给定一个列表 temperatures = [73, 74, 75, 71, 69, 72, 76, 73],你的输出应该是 [1, 1, 4, 2, 1, 1, 0, 0]。

提示:气温 列表长度的范围是 [1, 30000]。每个气温的值的均为华氏度,都是在 [30, 100] 范围内的整数。

思路: 单调栈, 一次for+while循环,i - pre_index 为结果元素, 堆栈放的idx

class Solution(object):
    def dailyTemperatures(self, T):
        """
        :type T: List[int]
        :rtype: List[int]
        """
        l = len(T)
        stack = []
        result = [0 for i in range(l)]
        for i in range(l):
            while stack and T[i] > T[stack[-1]]:
                pre_index = stack.pop()
                result[pre_index] = i - pre_index
            stack.append(i)
        return result


if __name__ == '__main__':
    nums = [73, 74, 75, 71, 69, 72, 76, 73]
    a = Solution()
    c = a.dailyTemperatures(nums)
    print(c)
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值