代码随想录算法训练营第九天 | 双指针法系列

文章展示了使用双指针法解决一系列编程问题,包括移除元素、删除有序数组中的重复项、移动0、比较含退格的字符串、有序数组的平方、反转字符串、替换空格、反转字符串里的单词、删除链表的倒数第N个节点、链表相交、环形链表II、三数之和及四数之和等。代码涵盖了数组操作和链表操作,涉及元素移动、去重、比较、反转等多种算法思想。
摘要由CSDN通过智能技术生成

27 移除元素

理清楚,在本题中,快慢指针代表的意义是什么。

我的代码

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        slow = 0
        n = len(nums)
        for fast in range(n):
            if nums[fast] != val:
                nums[slow] = nums[fast]
                slow += 1
        return slow

26 删除有序数组中的重复项

我的代码

弄清楚slow和fast指针的含义,最后别忘记给slow加一。

class Solution:
    def removeDuplicates(self, nums: List[int]) -> int:
        slow = 0 
        n = len(nums)
        if n == 1 :
           return 1
        for fast in range(1,n):
           if nums[fast] != nums[slow] :
               slow += 1
               nums[slow] = nums[fast]
        return slow+1

283 移动0

想太多,已知移动0,那就是把0剔除+末尾赋值。

我的代码

class Solution:
    def moveZeroes(self, nums: List[int]) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        slow = 0
        n = len(nums)
        for fast in range(n):
            if nums[fast] != 0 :
                nums[slow] =  nums[fast]
                slow = slow + 1
        if slow < n :
            for i in range(slow,n):
                nums[i] = 0
        return nums

844 比较含退格的字符串

我的代码

加一个多重退格判断。

class Solution:
    def backspaceCompare(self, s: str, t: str) -> bool:
        s = list(s)
        t = list(t)
        s_slow = 0
        n = len(s)
        for fast in range(n):
            if s[fast] != '#' :
                s[s_slow] = s[fast]
                s_slow = s_slow + 1
            else:
                if s_slow > 0 :
                    s_slow = s_slow - 1
        t_slow = 0
        n = len(t)
        for fast in range(n):
            if t[fast] != '#' :
                t[t_slow] =  t[fast]
                t_slow = t_slow + 1
            else:
                if t_slow > 0 :
                    t_slow = t_slow - 1
        if s[0:s_slow] == t[0:t_slow]:
            return True
        else:
            return False

977 有序数组的平方

已经掌握了,两个指针加和判断绝对值大小,申请新数组作为返回值。

我的代码

class Solution:
    def sortedSquares(self, nums: List[int]) -> List[int]:
        first = 0
        end = len(nums)-1
        res = nums.copy()
        index = end
        while first <= end :
            if nums[first] + nums[end] < 0 :
                res[index] = nums[first] * nums[first]
                first += 1
            else :
                res[index] = nums[end] * nums[end]
                end -= 1
            index -= 1
        return res

344 反转字符串

小意思,双指针,以后如果再需要反转,直接调内置函数吧。

我的代码

class Solution:
    def reverseString(self, s: List[str]) -> None:
        """
        Do not return anything, modify s in-place instead.
        """
        start = 0
        end = len(s)-1
        while start < end:
            
            s[end] , s[start] = s[start] , s[end]  
            start += 1
            end -= 1

剑指offer 05–替换空格

思路1:申请额外空间+遍历
思路2:代码随想录的思路,只申请一块需要替换的额外空间,在原数组上操作。

这里试一下思路2。

我的代码

在编写过程中,已经可以完全理清思路2的做法,但由于Python编程语言的特性:str为不可更改类型,所以强硬写出来并不美观,不如直接替换。

class Solution:
    def replaceSpace(self, s: str) -> str:
        
        s = list(s)
        n = len(s)
        
        for i in range(n-1,-1,-1):
            if s[i]==' ':
                s[i] = '%20'
        
        return ''.join(s)
class Solution:
    def replaceSpace(self, s: str) -> str:
        
        res = ''
        for i in s:
            if i != ' ':
                res += i
            else :
                res += '%20'
        return res

151 反转字符串里的单词

这题较难,此次复习并未做出此题。整体思路不难:即先反转整个字符串,再反转每个单词。

没想到的是如何处理空格,只能想到了很复杂的方法,先处理前后,再处理中间,实则运用双指针法就可以去除所有空格。

移除空格的思想,运用前面编写的过的移除元素的思想。

我的代码

看了代码随想录的解答之后,自己试图进行独立的代码编写。

失败,去除空格的逻辑理不清。

代码随想录的代码

class Solution:
    def reverseWords(self, s: str) -> str:
        # 将字符串拆分为单词,即转换成列表类型
        words = s.split()

        # 反转单词
        left, right = 0, len(words) - 1
        while left < right:
            words[left], words[right] = words[right], words[left]
            left += 1
            right -= 1

        # 将列表转换成字符串
        return " ".join(words)

重写代码随想录的代码

我觉得给出的代码不好,怪不得第一遍写完后,印象非常浅薄,原因就是Python的内置函数太方便了,一个split就把空格全部去掉,并且完成了单词的切割,这不好。

下面的代码是,完全按照代码随想录给出的思路进行的复现。

class Solution:

    def reverseWords(self, s: str) -> str:
        s = list(s)
        s = self.remove_space(s)
       
        s = s[::-1] # 反转函数,直接调内部,前面写过了
       
        n = len(s)
        slow = 0
        for i in range(n):
            if s[i] == ' ':
                temp = s[slow:i]
                temp = temp[::-1]
                s[slow:i] = temp
                slow = i+1
            if i == n-1 :
                temp = s[slow:i+1]
                temp = temp[::-1]
                s[slow:i+1] = temp
        return ''.join(s)
            


    def remove_space(self,s):
        slow = 0
        n = len(s)
        i = 0
        while i < n:
            if s[i]!=' ':
                if slow != 0:
                    
                    s[slow] = ' '
                    slow += 1
                while i < n and s[i]!=' ':
                    s[slow] = s[i]
                    i += 1
                    slow += 1
            i+=1
        return s[:slow]


206 反转链表

学习递归写法,一直没去看这方面!!!

我的代码

写复杂了。

class ListNode:
    def __init__(self,val=0,next=None):
        self.val = val
        self.next = next


class Solution:
    def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if head == None or head.next==None:
            return head
        
        slow = head
        fast = head.next
        head.next = None
        
        while fast != None :
            temp = fast.next
            fast.next = slow
            slow = fast
            fast = temp
        return slow

代码随想录的代码

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        cur = head   
        pre = None
        while cur:
            temp = cur.next # 保存一下 cur的下一个节点,因为接下来要改变cur->next
            cur.next = pre #反 转
            #更新pre、cur指针
            pre = cur
            cur = temp
        return pre

递归写法

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        return self.reverse(head, None)
    def reverse(self, cur: ListNode, pre: ListNode) -> ListNode:
        if cur == None:
            return pre
        temp = cur.next
        cur.next = pre
        return self.reverse(temp, cur)

19 删除链表的倒数第 N 个结点

双指针,让fast先走N步。

我的代码

class Solution:
    def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
        virtual = ListNode(0,head)
        slow = virtual
        fast = virtual
        for i in range(n):
            fast = fast.next
        while fast.next :
            slow = slow.next
            fast = fast.next
        slow.next = slow.next.next
        return virtual.next

面试题0207–链表相交

没啥好说的,先求两个长度,然后让长的先走n1-n2步。

我的代码

class ListNode:
    def __init__(self,val=0,next=None):
        self.val = val
        self.next = next

class Solution:
    def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
        virtualA = ListNode(0,headA)
        virtualB = ListNode(0,headB)
        curA = virtualA
        curB = virtualB
        countA = countB = 0
        
        while virtualA.next:
            countA = countA + 1
            virtualA = virtualA.next
        while virtualB.next:
            countB = countB + 1
            virtualB = virtualB.next
        if countA >= countB:
            diff = countA - countB
            for i in range(diff):
                curA = curA.next
            while curA:
                if curB==curA:
                    return curA
                else:
                    curB = curB.next
                    curA = curA.next
            
            else:
                return None
                
        
        else:
            diff = countB - countA
            for i in range(diff):
                curB = curB.next
            while curA:
                if curB==curA:
                    return curA
                else:
                    curB = curB.next
                    curA = curA.next
            
            else:
                return None

142 环形链表II

分两步:判断是否有环,fast若和slow相遇,即为有环。判断相遇结点。

我的代码

class Solution:
    def detectCycle(self, head: Optional[ListNode]) -> Optional[ListNode]:
        slow = head
        fast = head
        
        while fast and fast.next:
            slow = slow.next
            fast = fast.next.next
            
            # If there is a cycle, the slow and fast pointers will eventually meet
            if slow == fast:
                # Move one of the pointers back to the start of the list
                slow = head
                while slow != fast:
                    slow = slow.next
                    fast = fast.next
                return slow
        # If there is no cycle, return None
        return None

15 三数之和

重点在去重逻辑的思考,并未掌握。

代码随想录的代码

看了视频后,自己写出来的,注意:最后的else的最后,要移动left和right,不然就会陷入循环。

class Solution:
    def threeSum(self, nums: List[int]) -> List[List[int]]:
        nums = sorted(nums)
        res = []
        n = len(nums)
        for i in range(n):
            if nums[i] > 0 :
                break
            if i > 0 and nums[i]==nums[i-1]:  # a去重
                continue
            left = i+1
            right = n-1
            while left < right:
                if nums[i]+nums[left]+nums[right] < 0:
                    left+=1
                elif nums[i]+nums[left]+nums[right] > 0:
                    right -= 1
                else :
                    res.append([nums[i],nums[left],nums[right]])
                   
                    while left < right and nums[right] == nums[right-1]:
                        right -= 1
                    while left < right and nums[left] == nums[left+1]:
                        left += 1
                    left+=1
                    right -= 1
        return res

18 四数之和

重点在去重逻辑的思考,并未掌握。

代码随想录的代码

看了视频后,自己写出来的,掌握了三数之和后,四数之和就比较直观了。

class Solution:
    def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
        nums = sorted(nums)
        n = len(nums)
        res = []
        for k in range(n):
            if nums[k] > 0 and target > 0 and nums[k] > target :
                break
            if k > 0 and nums[k]==nums[k-1]:
                continue
            for i in range(k+1,n):
                if nums[k]+nums[i] > 0 and target > 0 and nums[k]+nums[i] > target :
                    break
                if i > k+1 and nums[i]==nums[i-1]:
                    continue
                left = i+1
                right = n-1
                while left < right :
                    if nums[k]+nums[i]+nums[left]+nums[right] < target:
                        left += 1
                    elif nums[k]+nums[i]+nums[left]+nums[right] > target:
                        right -= 1
                    else:
                        res.append([nums[k],nums[i],nums[left],nums[right]])
                        while left < right and nums[left] == nums[left+1]:
                            left += 1
                        while left < right and nums[right] == nums[right-1]:
                            right -= 1
                        left += 1
                        right -=1
        return res

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值