datawhale组队学习笔记(1)数组

这篇博客探讨了如何使用双指针法解决数组去重和移除元素的问题,包括有序数组去重以及在不使用额外存储空间的情况下的解决方案。同时,还介绍了在三数之和问题中应用双指针法的错误示例和正确解法,强调了排序和集合数据类型的限制。此外,提供了排序加双指针的高效解法。
摘要由CSDN通过智能技术生成

关于本次数组的练习题,主要包含了去除重复元素、去除特定元素的两个子问题(esp.去重)。对于该问题,可以根据是否使用额外存储空间分为两类:

1.使用额外存储空间

① 可以使用set()辅助去重,但要注意,集合中元素的数据类型虽然可以不同,但必须都是不可变类型,不能是列表、元组、集合、字典等(见第三题中的第一种错法);

②可以将需要删去的(即在上一步检测出重复的地方)序号存储到一个列表里,将列表去重并反转(或反向排序),再迭代删去(反转非常重要,因为如果不反转则会在删除的过程中出现序号的改变,从而导致溢出)

2.不使用额外存储空间

①不可以排序后直接迭代删除,因为这样会导致溢出(大家也有在群里探讨过);

②使用排序+双指针方法,通常是fast和slow指针(其根本在于在数组内原地修改,因此我对于第二题使用的那种解法也是对此进行了一定程度借鉴的。)

T1.删除有序数组中的重复项

在这里插入图片描述

#(排序+)双指针
class Solution(object):
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        
        if not nums:
            return 0
        
        fast=slow=1
        while fast<len(nums):
            if nums[fast]!=nums[fast-1]:
                nums[slow]=nums[fast]
                slow+=1
            fast+=1
        nums=nums[:slow]
        return len(nums)
T2.移除元素

在这里插入图片描述

#排序式原地修改
class Solution(object):
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        if not nums:
            return 0
        m=max(nums)+1
        count=0
        for i in range(len(nums)):
            if nums[i]==val:
                nums[i]=m
                count+=1
        nums.sort()
        nums=nums[:len(nums)-count]
        return len(nums)

对于此题,也可以使用排序+双指针的常规方法。

T3.三数之和

在这里插入图片描述

#TypeError: unhashable type: 'list'
#集合中元素的数据类型虽然可以不同,但必须都是不可变类型,不能是列表、元组、集合、字典等
class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        
        b=[]
        l=len(nums)
        for i in range(l):
            for j in range(i,l):
                for k in range(j,l):
                    if nums[i]+nums[j]+nums[k]==0:
                        a=[nums[i]]
                        a.append(nums[j])
                        a.append(nums[k])
                        b.append(a)
        the_set=set(b)
        c=list(the_set)
        return c
#忘记了双指针前必须排序,而这种数据类型无法排序,因此行不通
class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        
        b=[]
        l=len(nums)
        for i in range(l):
            for j in range(i,l):
                for k in range(j,l):
                    if nums[i]+nums[j]+nums[k]==0:
                        a=[nums[i]]
                        a.append(nums[j])
                        a.append(nums[k])
                        b.append(a)
        fast=slow=1 
        while fast<len(b):
            if set(b[fast])!=set(b[fast-1]): #不过这里想法其实还挺正确的
                b[slow]=b[fast]
                slow+=1 
            fast+=1 
        b=b[:slow]
        return b
#暴力解法(不过超时了)
class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        
        b=[]
        l=len(nums)
        for i in range(l):
            for j in range(i+1,l):
                for k in range(j+1,l):
                    if nums[i]+nums[j]+nums[k]==0:
                        a=[nums[i]]
                        a.append(nums[j])
                        a.append(nums[k])
                        b.append(a)
        
        c=[]
        for x in range(len(b)):
            for y in range(x+1,len(b)):
                if set(b[x])==set(b[y]):
                    c.append(x)
        #这两部用来解决前面几句代码的不完善之处,将列表去重并反转(或反向排序),再迭代删去(反转非常重要,因为如果不反转则会在删除的过程中出现序号的改变,从而导致溢出)
        c=list(set(c))
        c.sort(reverse=True) #避免栈溢出
        
        if c!=[]:
            for m in c:
                del b[m]
        return b
#排序+双指针
class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        
        ans=list()
        nums.sort()
        l=len(nums)
        
        for first in range(l):
            if first>0 and nums[first]==nums[first-1]:
                continue
            target=-nums[first]
            third=l-1
            for second in range(first+1,l):
                if second>first+1 and nums[second]==nums[second-1]:
                    continue
                while second<third and nums[second]+nums[third]>target:
                    third-=1 
                if second==third:
                    break
                if nums[second]+nums[third]==target:
                    ans.append([nums[first],nums[second],nums[third]])
        return ans

末尾mark一篇讲解双指针的博客:https://blog.csdn.net/thekingspath/article/details/110572143?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522164493965116781685342606%2522%252C%2522scm%2522%253A%252220140713.130102334…%2522%257D&request_id=164493965116781685342606&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2allsobaiduend~default-2-110572143.pc_search_result_positive&utm_term=python%E5%8F%8C%E6%8C%87%E9%92%88&spm=1018.2226.3001.4187

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值