LeetCode--数组(1)

这篇博客主要讲解了LeetCode中关于数组的几道经典题目,包括两数之和、无重复字符的最长子串、盛最多水的容器、三数之和、下一个排列以及在排序数组中查找元素的第一个和最后一个位置。通过实例展示了如何利用字典、双指针等方法解决这些问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1、两数之和(Two Sum)
题目描述:
  给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
 你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9 

因为 nums[0] + nums[1] = 2 + 7 = 9 所以返回 [0, 1]

代码:

 class Solution(object):
        def twoSum(self,nums,target):
            if len(nums)<=1:
                return Flase
            else:
                dict={}
                for i in range(len(nums)):
                    if nums[i] in dict:
                        return[dict[nums[i]],i]
                    else:
                        dict[target-nums[i]]=i#  target-nums[i]为key

解析: 利用一个字典,它的key是当前遍历的值与target相差多少,value是当前值得索引。在遍历数组时候,每当遍历到一个值时就查看与target的差值在不在字典中,如果在就返回当前索引,不在就把[差值,索引]记录。

3、无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 :

输入: "abcabcbb"
输出: 3 
解释: 因为无重复字符的最长子串是
"abc",所以其
长度为 3。

代码:

思路:用hash表来做,判断一个字母是否在表里面,不在ans就加1,在就让指针i指向最后一个出现的相同字母。维护ans的值

class Solution:
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        st={}
        i,ans=0,0
        for j in range(len(s)):
            if s[j] in st:
                i=max(st[s[j]],i)
            ans=max(ans,j-i+1)
            st[s[j]]=j+1
        return ans

11、盛最多水的容器

给定 n 个非负整数 a1,a2,...,an,每个数代表坐标中的一个点 (iai) 。在坐标内画 n 条垂直线,垂直线 i 的两个端点分别为 (iai) 和 (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

代码:

思路:这道题我们用双指针,面积取决于短边,如果左指针是短边,h就是左指针,并向右移,如果右指针是短边,就用左移动。并不断维护最大值。扫一遍就够o(n)

class Solution(object):
    def maxArea(self,height):
        '''
        :type height:List[int]
        :rtype : int
        '''
        left=0
        right=len(height)-1
        maxarea=0
        while left<right:
            b=right-left
            if height[left]<height[right]:
                h=height[left]
                left+=1
            else:
                h=height[right]
                right-=1
            area=h*b
            if maxarea<area:
                maxarea=area
        return maxarea

15. 三数之和

给定一个包含 n 个整数的数组 nums,判断 nums 中是否存在三个元素 a,b,c ,使得 a + b + c = 0 ?找出所有满足条件且不重复的三元组。

注意:答案中不可以包含重复的三元组。

例如, 给定数组 nums = [-1, 0, 1, 2, -1, -4],

满足要求的三元组集合为:
[
  [-1, 0, 1],
  [-1, -1, 2]
]

代码:

        用left,right两边向中间搜索的方法,要注意去除重复答案。

class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        leng=len(nums)
        nums.sort()
        ans=[]
        for i in range(leng-2):
            if i==0 or nums[i-1]<nums[i]:
                l=i+1
                r=leng-1
                while l<r:
                    three_sum=nums[i]+nums[l]+nums[r]
                    if three_sum==0:
                        ans.append([nums[i],nums[l],nums[r]])
                        l+=1
                        r-=1
                        while l<r and nums[l]==nums[l-1]:
                            l+=1
                        while l<r and nums[r]==nums[r+1]:
                            r-=1
                    elif three_sum<0:
                        l+=1
                    else:
                        r-=1
        return ans

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

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

与 target 最接近的三个数的和为 2. (-1 + 2 + 1 = 2).
紧接着上一题三数之和,用相同的思路
代码如下

class Solution:
    def threeSumClosest(self, nums, target):
        """
        :type nums: List[int]
        :type target: int
        :rtype: int
        """
        nums.sort()
        res = sum(nums[:3])
        m = abs(res - target)
        for i in range(len(nums)):
            l = i+1
            r = len(nums)-1
            while l < r:
                temp = nums[i] + nums[l] +nums[r]
                if abs(res - target) > abs(temp-target):
                    res = temp
                elif target < temp:
                    r -=1
                else :
                    l +=1
        return res

31、下一个排列

实现获取下一个排列的函数,算法需要将给定数字序列重新排列成字典序中下一个更大的排列。

如果不存在下一个更大的排列,则将数字重新排列成最小的排列(即升序排列)。

必须原地修改,只允许使用额外常数空间。

以下是一些例子,输入位于左侧列,其相应输出位于右侧列。
1,2,3 → 1,3,2
3,2,1 → 1,2,3
1,1,5 → 1,5,1

翻译过来:

先找出最大的索引 k 满足 nums[k] < nums[k+1],如果不存在,就翻转整个数组;
再找出另一个最大索引 l 满足 nums[l] > nums[k];
交换 nums[l] 和 nums[k];
最后翻转 nums[k+1:]。
举个例子:

比如 nums = [1,2,7,4,3,1],下一个排列是什么?

我们找到第一个最大索引是 nums[1] = 2

再找到第二个最大索引是 nums[5] = 3

交换,nums = [1,3,7,4,2,1];

翻转,nums = [1,3,1,2,4,7]

class Solution:
    def nextPermutation(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        firstIndex = -1
        n = len(nums)
        def reverse(nums, i, j):
            while i < j:
                nums[i],nums[j] = nums[j], nums[i]
                i += 1
                j -= 1
        for i in range(n-2, -1, -1):
            if nums[i] < nums[i+1]:
                firstIndex = i
                break
        #print(firstIndex)
        if firstIndex == -1:
            reverse(nums, 0, n-1)
            return 
        secondIndex = -1
        for i in range(n-1, firstIndex, -1):
            if nums[i] > nums[firstIndex]:
                secondIndex = i
                break
        nums[firstIndex],nums[secondIndex] = nums[secondIndex], nums[firstIndex]
        reverse(nums, firstIndex+1, n-1)

32、在排序数组中查找元素的第一个和最后一个位置

描述:

给定一个按照升序排列的整数数组 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]

# 通过二分法找到第一个等于 target 的值, 然后以该值向左向右查找边界
    def searchRange(self, nums: List[int], target: int) -> List[int]:
        if not nums: return [-1, -1]
        left = 0
        right = len(nums) - 1
        while left <= right:
            mid = left + (right - left) // 2
            if target < nums[mid]:
                right = mid - 1
            elif target > nums[mid]:
                left = mid + 1
            else:
                left = mid
                right = mid
                while left - 1 >= 0 and nums[left - 1] == target:
                    left -= 1
                while right + 1 < len(nums) and nums[right + 1] == target:
                    right += 1
                return [left, right]
        return [-1, -1]

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值