leetcode刷题--数组系列

注:所有的题目阶来自于leetcode

转载请注明出处:https://www.cnblogs.com/bethansy/

1.盛水最多的容器

(1)题目要求

给你 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。

 示例:

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

(2)解题思路

1.普通解法
看到这个题目首先想到的第一种解题思路就是两两柱子之间进行计算判断,将两点之间的面积、索引存入共享变量中。若后面两点的面积大于前面两个点的面积,就更新面积,点1的索引,点2的索引。时间复杂度太大超出规定运行时间

class Solution(object):
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""
are=0
for i in range(len(height)):
    for j in range(i,len(height)):
        new_are=min(height[i],height[j])*(j-i)
        if new_are>are:
            are=new_are
return are                    

  

2.优化算法

看到大部分网友的题解都是双指针法,其实就是在两边的边缘安房指针,采用内缩的方式进行靠近,这样的操作方法减少了暴力解法中不必要的计算,时间复杂度O(N)

class Solution(object):
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""

if len(height)<=2:
  return min(height)
else:
  i,j,area=0,len(height)-1,0
  while i<j:
    if height[i]<height[j]: 
      area_new=height[i]*(j-i)
      area=max(area,area_new)
      i+=1
    else:
      area_new=height[j]*(j-i)
      area=max(area,area_new)
      j-=1
  return area

 初看时认为会漏掉很多解,后发现漏掉的解都不大于当前解,所以可以直接继续收缩

2.最接近的三数之和

(1)题目要求

    给定一个包括 n 个整数的数组 nums 和 一个目标值 target。找出 nums 中的三个整数,使得它们的和与 target 最接近。返回这三个数的和。假定每组输入只存在唯一答案。

例如,给定数组 nums = [-1,2,1,-4], 和 target = 1.

与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2). 

(2)思路

   穷举法Cn3 复杂度过高,仍旧可以采用一个固定值,另外两个点采用双指针走法,复杂度O(n2),代码如下,结果仍旧是超出时间限制

 

 

 

class Solution(object):
    def threeSumClosest(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """  
        if len(nums)<3:
            return []
        nums.sort()
        res=nums[0]+nums[1]+nums[2]
        for i in range(len(nums)):
            start,end=i+1,len(nums)-1
            while start<end:
                sum_= nums[i]+nums[start]+nums[end]
                if abs(sum_-target)<=abs(res-target):
                    res=sum_
                if sum_<target:
                    start+=1
                elif sum_>target:
                    end-=1
                elif sum_==target:
                    return res
        return res

  

3.旋转矩阵

(1)题目要求

给你一幅由 N × N 矩阵表示的图像,其中每个像素的大小为 4 字节。请你设计一种算法,将图像旋转 90 度。不占用额外内存空间能否做到?

示例1

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

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

(2)思路

思路1:逐层进行分解

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        # 先转置
        lens =len(matrix)
        for i in range(lens):
            for j in range(i):
                matrix[i][j],matrix[j][i]=matrix[j][i],matrix[i][j]
        # 再左右转
        for i in range(lens):
            for j in range(int(lens//2)):
                matrix[i][j],matrix[i][lens-j-1]=matrix[i][lens-j-1],matrix[i][j]
        return matrix

 

4.主要元素

(1)题目要求

如果数组中多一半的数都是同一个,则称之为主要元素。给定一个整数数组,找到它的主要元素。若没有,返回-1。

示例 1:

输入:[1,2,5,9,5,9,5,5,5]
输出:5

(2)思路

这道题主要有一个限制降低了难度,就是数组中多一半都是同一个数,解题思路主要是取到数组中的中位数,再遍历一遍找到中位数出现的次数,若大于一半则输出这个中位数。

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums.sort()
        med=len(nums)//2
        med = nums[med] 
        count=0
        for i in range(len(nums)):
            if nums[i]==med:
                count+=1
        if count>=len(nums)//2:
            return med
        else:
            return -1

  

如果只是找这个数组中的主要元素,即出现次数最多的那个数,又该如何展开?

答:先排序,然后前后做差,变成数组,求连续为0的个数。

 

4.0~n-1中缺失的元素

(1)题目要求

一个长度为n-1的递增排序数组中的所有数字都是唯一的,并且每个数字都在范围0~n-1之内。在范围0~n-1内的n个数字中有且只有一个数字不在该数组中,请找出这个数字。

 

示例 1:

输入: [0,1,3]
输出: 2
示例 2:

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

 

(2)解题思路

二分查找

class Solution(object):
    def missingNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        nums.sort()
        n =len(nums)-1
        begin=0
        end=n
        while begin<=end:
            if nums[(begin+end)//2]==(begin+end)//2:
                begin= begin+1              
            else:
                  end =end-1
        return begin

  

5.对称二叉树

(1)题目要求

给定一个二叉树,检查它是否是镜像对称的。
 
例如,二叉树 [1,2,2,3,4,4,3] 是对称的。
    1
   / \
  2   2
 / \ / \
3  4 4  3

 
但是下面这个 [1,2,2,null,3,null,3] 则不是镜像对称的:
    1
   / \
  2   2
   \   \
   3    3
 

(2)解题思路

class Solution:
def isSymmetric(self, root: TreeNode) -> bool:
def recur(L, R):
if not L and not R: return True
if not L or not R or L.val != R.val: return False
return recur(L.left, R.right) and recur(L.right, R.left)

return recur(root.left, root.right) if root else True

  

posted @ 2020-04-12 22:27  bethansy  阅读(253)  评论(0编辑  收藏  举报