leetcode--数组(Medium1)

2019.08.05


3.无重复字符的最长字串

  • 基本思想:双指针哈希表
  • 实现:
    1. 使用 head 指向无重复子串的头,ind 指向当前位置(即当前无重复子串的尾),len_max记录当前无重复字串的最长长度,使用字典的 key 存储串 s 的字符,value 存储字符在串中的位置。
    2. 当 k(当前字符)不在字典中时,表明 k 是当前无重复子串的尾元素,故当前无重复字符的子串长度为( ind - head + 1 ),与最大长度进行比较看是否更新,然后将此 k 放入字典中;
    3. 当 k 已经存在于字典中时,还需判断 字典中的这个 k 的 value(即在串中的位置)是否大于等于 head,(因为 head 是当前无重复子串的首位置)如果小于 head 则认为这个已经存在的 k 早已废弃(与当前无重复子串无关),与 k 不在字典中时的情况一致处理,k 的 value 大于等于 head 则认为遇到了重复元素,k 之前的无重复子串的长度为 ( ind - head ),与最大长度进行比较看是否需要更新,然后 head 跟新为 被重复了的元素 k~ 的下一个位置,这样从 k~ 的下一个位置到当前 k 的位置的子串又是另一个无重复子串,同时更新 k 的 value 值,最后返回依次遍历过程中的最大长度。
    def lengthOfLongestSubstring(self, s: str) -> int:
        head = 0
        len_max = 0
        _dict = {}
        for ind, k  in enumerate(s):
            if k in _dict and _dict.get(k) >= head:
                len_max = (ind - head) if (ind - head) > len_max else len_max
                head = _dict.get(k) + 1
                _dict[k] = ind
            else:
                len_max = (ind - head + 1) if (ind - head + 1) > len_max else len_max
                _dict[k] = ind
        
        return len_max

15.三数之和

  • 基本思想:双指针回溯
  • 实现:
    1. 找组合思路:固定三个数字中最左数字的指针 a,遍历数组找到每个 a 对应的所有满足nums[a] + nums[b] + nums[c] == 0 的 b,c 组合:
    2. 当 nums[a] > 0 时直接跳出,因为 c > b > a,即三个数字都大于 0,在此k之后不可能找到组合了
    3. 当 a > 0 且 nums[a] == nums[a - 1] 时跳过此数字,因为 nums[a - 1] 的所有组合已经被加入到结果中,本次搜索只会搜索到重复组合。
    4. b,c 分设在数组 [a+1, len(nums)-1] 两端,根据 sum 与 0 的大小关系交替向中间逼近,如果遇到等于 0 的组合则加入 arr 中,需要注意:移动 i,j 需要跳过所有重复值,以避免重复答案被计入 arr。
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums.sort()
        arr = []
        for a in range(len(nums)-2):
            if nums[a] > 0:break
            # 剪枝操作
            if a > 0 and nums[a] == nums[a-1]:continue
            
            b = a + 1
            c = len(nums) - 1
            while b < c:
                if  nums[a] + nums[b] + nums[c] == 0:
                    arr.append([nums[a], nums[b], nums[c]])
                    b += 1
                    c -= 1
                    while b < c and nums[b] == nums[b-1]:
                        b += 1
                    while b < c and nums[c] == nums[c+1]:
                        c -= 1
                elif  nums[a] + nums[b] + nums[c] > 0:
                    c -= 1
                    while b < c and nums[c] == nums[c+1]:
                        c -= 1
                else:
                    b += 1
                    while b < c and nums[b] == nums[b-1]:
                        b += 1
                        
        return arr

2019.08.06


18.四数之和

  • 基本思想:双指针回溯
  • 实现:可以在三数之和的基础上做,或者找出所有符合条件的四数,再去重。
      def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
            nums.sort()
            ans=set()  #去重
        
            for i in range(len(nums)-3):  #固定第一个数
                if i > 0 and nums[i] == nums[i-1]:continue  # 剪枝
                for j in range(i+1,len(nums)-2): #固定第二个数
                    if j > i+1 and nums[j] == nums[j-1]:continue # 剪枝
                    left=j+1 #左指针
                    right=len(nums)-1 #右指针
                    while(right>left):
                        temp=nums[i]+nums[j]+nums[left]+nums[right]
                        if temp==target:
                            ans.add((nums[i],nums[j],nums[left],nums[right]))
                            left+=1
                            right-=1
                        if temp>target:right-=1 #太大了,右指针左移
                        if temp<target:left+=1 #反之
           
            res=[]  #修改返回格式
            for i in ans:
                res.append(list(i))
            return res

2019.08.09


16.最接近的三数之和

  • 基本思想:双指针回溯
  • 实现:在三数之和的基础上设置最小差值,每次出现新的组合时更新最小差值,并保留最小差值时的三数之和。
    def threeSumClosest(self, nums: List[int], target: int) -> int:
        nums.sort()
        min_t = sys.maxsize
        for i in range(len(nums) - 2):
            #剪枝操作
            if i > 0 and nums[i] == nums[i-1]:continue
                
            left = i + 1
            right = len(nums) - 1
            while(left < right):
                sum_t = nums[i] + nums[right] + nums[left]
                
                if abs(sum_t - target) < min_t:
                        min_t = abs(sum_t - target) 
                        res = sum_t
                        
                if sum_t > target:
                    right -= 1
                elif sum_t < target:
                    left += 1
                else:
                    return sum_t
        return res
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值