双指针

2020/12/31

167. 两数之和 II - 输入有序数组

头尾指针 开始迭代

class Solution:
    def twoSum(self, numbers: List[int], target: int) -> List[int]:
        if(numbers==None or len(numbers)<2):
            return None
        left=0
        right=len(numbers)-1
        while(left<right):
            twoSum=numbers[left]+numbers[right]
            if(twoSum==target):
                return [left+1,right+1]
            elif(twoSum>target):
                right-=1
            else:
                left+=1
        return None
633. 平方数之和

直接用left right表示元素来比 不用先构建数组 用left right当下标

class Solution:
    def judgeSquareSum(self, c: int) -> bool:
        #  双指针找两个
        left=0
        right=int(c**0.5)
        while(left<=right):# 因为可以取相同的数 所以加=
            towSum=left**2+right**2
            if(towSum==c):
                return True
            elif(towSum>c):
                right-=1
            else:
                left+=1
        return False
345. 反转字符串中的元音字母
  • 头尾指针
  • 注意第一个循环left<right 但是循环内又加了个循环left+1 那么left有可能>right
class Solution:
    def reverseVowels(self, s: str) -> str:
        s=list(s)
        strYuan='aoeiuAOEIU'
        left=0
        right=len(s)-1
        while(left<right):
            # 先找left元音
            while(left<right and s[left] not in strYuan):#注意要加上left<right的约束 不加的话 后面也得判断left right关系
                left+=1
            # 找right元音
            while(left<right and s[right] not in strYuan):
                right-=1
            if(s[left] in strYuan and s[right] in strYuan):
                s[left],s[right]=s[right],s[left]
                left+=1
                right-=1
                
        return ''.join(s)

2020/1/1

680. 验证回文字符串 Ⅱ

遇到不相等的情况
返回 s[left+1,right+1] or s[left,right] 的结果

class Solution:
    def validPalindrome(self, s: str) -> bool:
        if(len(s)==1):
            return True
        left=0
        right=len(s)-1
        while(left<right):
            if(s[left]!=s[right]):
                return self.validPalindromeTrue(s[left:right]) or self.validPalindromeTrue(s[left+1:right+1])
            left+=1
            right-=1
        return True
        
    def validPalindromeTrue(self,s):
        if(len(s)==1):
            return True
        left=0
        right=len(s)-1
        while(left<right):
            if(s[left]!=s[right]):
                return False
            left+=1
            right-=1
        return True
88. 合并两个有序数组

第一思路是从前往后插,但是空间复杂度是 o(m+n);从后往前插,空间复杂度o(1)

class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        # 从nums1后面往前 逐步插入最大元素
        i=m-1
        j=n-1
        for index in range(m+n-1,-1,-1):
            # 数组1遍历完
            if(i<0):
                nums1[index]=nums2[j]
                j-=1
            # 数组2遍历完
            elif(j<0):
                nums1[index]=nums1[i]
                i-=1
            # 数组1和数组2都没遍历完 选最大的
            else:
                if(nums1[i]>nums2[j]):
                    nums1[index]=nums1[i]
                    i-=1
                else:
                    nums1[index]=nums2[j]
                    j-=1

还是官方写的简洁

  • 注意不用考虑p1剩下的情况(本身就是nums1)
  • 只考虑p2可能剩下就好了
class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        # 从nums1后面往前 逐步插入最大元素
        p1=m-1
        p2=n-1
        p=m+n-1
        # p1和p2还都有元素
        while(p1>=0 and p2>=0):
            if(nums1[p1]>nums2[p2]):
                nums1[p]=nums1[p1]
                p1-=1
            else:
                nums1[p]=nums2[p2]
                p2-=1
            p-=1

        # p2可能还有元素(p1如果还有的话就直接在p1里了)
        nums1[:p2+1]=nums2[:p2+1]
141. 环形链表
  • 存在环:fast和slow相遇

  • 不存在环:fast到none了

  • 当链表中不存在环时,快指针将先于慢指针到达链表尾部,链表中每个节点至多被访问两次。

  • 当链表中存在环时,每一轮移动后,快慢指针的距离将减小一。而初始距离为环的长度,因此至多移动 N轮??

low=head fast=head

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        if(head==None):
            return False
        low=head
        fast=head
        while(fast!=None):
            if(fast.next==None):
                return False
            else:
                fast=fast.next.next
                low=low.next
                if(fast==low):
                    return True

low=head fast=head.next

class Solution:
    def hasCycle(self, head: ListNode) -> bool:
        if(head==None or head.next==None):
            return False
        low=head
        fast=head.next
        # 相等的时候 相遇 存在环
        while(low!=fast):
            if(fast!=None and fast.next!=None):
                fast=fast.next.next
                low=low.next
            else:
                #fast遇到none了
                return False 
        return True

还可以用哈希表存储遍历过的节点 如果遍历中发现当前节点在哈希表中 就有环

2021/1/3

524. 通过删除字母匹配到字典里最长单词
  • 将给定的list按长度、字典顺序排序
  • 判定每个字符串是不是子序列
class Solution:
    def findLongestWord(self, s: str, d: List[str]) -> str:
        # 先按字符串长度降序排列
        #d.sort(key=lambda x:len(x),reverse=True) #按照自己的理解 返回长度最长且list的index顺序最小
        d.sort(key=lambda x:(-len(x),x)) # 真正的题意 返回长度最长且字典顺序最小
        res=''
        # 判断每个字符串是不是子序列
        for sstr in d:
            if(len(sstr)<=len(res)):
                continue
            i=0 # s的index
            j=0 # sstr的index
            while(i<len(s) and j<len(sstr)):
                # 用s的元素不等于sstr的 s+=1
                if(s[i]!=sstr[j]):
                    i+=1
                # s的元素等于sstr的 s+=1 sstr+=1
                else:
                    # 匹配到sstr的最后一个char 成功
                    if(j==len(sstr)-1):
                        res=sstr
                        break
                    else:
                        i+=1
                        j+=1
        return res

拆成两个函数 更简洁一些

class Solution:
    def findLongestWord(self, s: str, d: List[str]) -> str:
        # 先按字符串长度降序排列
        #d.sort(key=lambda x:len(x),reverse=True) #按照自己的理解 返回长度最长且list的index顺序最小
        d.sort(key=lambda x:(-len(x),x)) # 真正的题意 返回长度最长且字典顺序最小
        res=''
        # 判断每个字符串是不是子序列
        for sstr in d:
            if(len(sstr)<=len(res)):
                continue
            if(self.isSubstr(s,sstr)):
                res=sstr
        return res
    
    # 判断y是不是x的子串
    def isSubstr(self,s,target):
        if(len(target)>len(s)):
            return False
        i=0 # s
        j=0 # target
        while(i<len(s) and j<len(target)):
            if(s[i]!=target[j]):
                i+=1
            else:
                i+=1
                j+=1
        return j==len(target)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值