python--双指针

 双指针yyds

双指针: 即用两个不同速度或不同方向的指针对列表进行访问,通过两个不同指针的碰撞从而达到特定的目的。

为节省时间和空间,利用单次遍历,判断指针碰撞实现问题的解。

根据双指针定义,可划分三类

    • 快慢双指针
    • 左右双指针
    • 滑动窗口

1、快慢双指针:前后双指针,以不同的移动速度遍历

  • 判断数组或链表的长度
  • 是否有环
  • 特定位置的值,比如列表的中间元素

案例:链表的中间结点--给定一个头结点为 head 的非空单链表,返回链表的中间结点。

输入:[1,2,3,4,5]

输出:此列表中的结点 3 (序列化形式:[3,4,5])

返回的结点值为 3 。

 

 def middleNode(self, head):
        """
        :type head: ListNode

        :rtype: ListNode

        """
        slow = fast = head

        while fast and fast.next:

            slow = slow.next

            fast = fast.next.next

        return slow

案例:删除有序数组中的重复项

给你一个 升序排列 的数组 nums ,请你 原地 删除重复出现的元素,使每个元素 只出现一次 ,返回删除后数组的新长度。元素的 相对顺序 应该保持 一致 。

输入:nums = [0,0,1,1,1,2,2,3,3,4]

输出:5, nums = [0,1,2,3,4]

解释:函数应该返回新的长度 5 并且原数组 nums 的前五个元素被修改为 0, 1, 2, 3, 4 。

def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        if len(nums)<=1:

            return len(nums)
        left=0
        right=1
        while right<len(nums) :

            if nums[left]==nums[right]:

                right +=1
            else:
                left +=1

                nums[left]=nums[right]

                right +=1  
        return left+1

 

2、左右双指针:左右指针分别从列表两端移动

  • 快速排序
  • 倒置

案例:给你一个字符串 s ,请你反转字符串中 单词 的顺序。

         单词 是由非空格字符组成的字符串。s 中使用至少一个空格将字符串中的 单词 分隔开。

输入:s = "  hello world  "

输出:"world hello"

解释:反转后的字符串中不能存在前导空格和尾随空格。

 

输入:s = "a good   example"

输出:"example good a"

解释:如果两个单词间有多余的空格,反转后的字符串需要将单词间的空格减少到仅有一个。

 

 

 

 

class Solution(object):

    def trimSpace(self,s):

        outPut = []

        outPut.append(" ")

        for i in range(len(s)):

            outPut.append(s[i])

        outPut.append(" ")

        return outPut

    def reverseAll(self,s):

        left = 0

        right = len(s) - 1

        while left < right:

            temp = s[left]

            s[left] = s[right]

            s[right] = temp

            left += 1

            right -= 1

        return s

    def reverseWords(self, s):

        """

        :type s: str

        :rtype: str

        """

        s=self.trimSpace(s)

        s=self.reverseAll(s)

        left = 0

        right = 0

        i=0

        n = len(s)

        t=[]

        while right < n:

            if s[right] == " ":

                res = self.reverseAll(s[left:right])

                t.extend(res)

                t.append(" ")

                right += 1

                left = right

                right += 1

            else:

                right += 1

        while t[0] == " ":

            del t[0]

        while t[-1]==" ":

            del t[-1]

        output = []

        i, j = 0, len(t) - 1

        while i <= j:

            if t[i] != ' ':

                output.append(t[i])

            elif output[-1] != ' ':

                output.append(t[i])

            i += 1

        return ''.join(output)

 

3、滑动窗口:有左右端点和长度,根据要求调整窗口

  • 无重复字符的最长子串

案例:无重复字符的最长子串

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

 

def lengthOfLongestSubstring(self, s):

        """

        :type s: str

        :rtype: int

        """

        left = 0

        maxSubset = 0

        subset = []

        right = 0

        while right < len(s):

            if s[right] not in subset:

                subset.append(s[right])

                right += 1

                maxSubset = max(maxSubset, len(subset))

            else:

                del subset[left]    #注意:因为每次删除的是头部,删除后还是定位在头部,就不需要处理left

        return maxSubset

 

 

            

          

 

 

 

 

 

posted @ 2022-11-26 23:43  壹米  阅读(727)  评论(0)    收藏  举报