【刷体日记】双指针问题

leecode 680 回文串

给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。

示例 1:
输入: “aba”
输出: True
示例 2:
输入: “abca”
输出: True
解释: 你可以删除c字符。
注意:
字符串只包含从 a-z 的小写字母。字符串的最大长度是50000。

思路

判断回文 --> 双指针 i , j i ,j i,j
以"abdda"为例,
i i i指向’b’, j j j指向’d’,此时不对,
但是有一次删除的机会,
那么子串范围为( i + 1 , j i+1, j i+1,j)或( i , j − 1 i, j-1 i,j1)的俩子串只要有任意一个是回文串,则结果就是回文串,否则就不是。

hint:

  1. python可以很简洁的反转一个字符串 s[::-1]
  2. python的字符串 s[a:b] 表示 的字符串包含a索引,但不包含b索引,即(a, b-1)
代码
class Solution:
    def validPalindrome(self, s: str) -> bool:
    	if s == s[::-1]:
    		return True
    	i, j = 0, len(s)-1
    	while i<j:
    		if s[i] == s[j]:
    			i+=1
    			j-=1
    		else:
    			s1 = s[i+1:j+1] #删除s[i]
    			s2 = s[i:j] # 删除s[j]
    		return s1 == s1[::-1] or s2==s2[::-1] # 判断两个字符串是否有回文串
    	

leecode 633 平方和

给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a 2 + b 2 = c a^2+b^2=c a2+b2=c

思路
  1. 双指针i,j
  2. i=0开始,j 从 ( c ) \sqrt(c) ( c) 向下取整的数开始
  3. python开根号需要import math
代码
class Solution:
    import math
    def judgeSquareSum(self, c: int) -> bool:
    	i ,j = 0 ,int(math.sqrt(c))
    	while i<=j:
    		res = i*i+j*j #
    		if res > c:
    			j -= 1
    		elif res < c:
    			i+=1
    		else:
    			return True
    	return False

leetcode 524

给你一个字符串 s 和一个字符串数组 dictionary 作为字典,找出并返回字典中最长的字符串,该字符串可以通过删除 s 中的某些字符得到。
如果答案不止一个,返回长度最长且字典序(不是给定字典中的顺序,是字典序)最小的字符串。如果答案不存在,则返回空字符串。
示例 1:
输入:s = “abpcplea”, dictionary = [“ale”,“apple”,“monkey”,“plea”]
输出:“apple”
示例 2:
输入:s = “abpcplea”, dictionary = [“a”,“b”,“c”]
输出:“a”

思路
  1. 暴力搜索,先确定字典中的字符串是否是子串,然后根据字符串长度和字典序更新返回值
  2. 先对字典排序:排序关键字:字符串长度降序和字典序升序(sort 和lambda搭配),然后判断是否是子串(find()函数),返回第一个子串

hint:
(1)sort()函数用lambda指定排序关键字
(2)s.find(str, beg, end),在s中找str连续子串,返回strs中起始index,如果str是s中的不连续子串,那么需要对str逐个字符在s中循环查找,因为有重复字符的存在,要注意指定beg不在找过的部分再找:for ch in str : index = s.find(ch, index)+1
找不到的时候find函数返回值是-1

(3)for-else语句:如果for循环执行中没有遇到break,即正常结束了,循环else后语句正常执行。
因此for-else可以根据结束循环的原因:自然结束还是break跳出决定循环完成后的语句是否继续执行

代码
#思路1
class Solution:
    def findLongestWord(self, s: str, d: List[str]) -> str:
        ans = '' # 储存返回值
        for word in d: # 遍历字典
            i,j=0,0 # 两个指针分别遍历s和word
            while i<len(s) and j<len(word):
                #如果两个指针指向的字符相同,两个指针分别+1
                if s[i] == word[j]:
                    i+=1
                    j+=1
                # 如果指向字符不同,指向s的指针+1(从s串的下一个字符继续匹配)
                else:
                    i+=1
            # 遍历完s或者word以后,检查当前word是否符合返回要求,根据更新规则更新返回答案
            if j == len(word): # 说明遍历完了word,那么word是s的子串
                # 如果当前word长度大于已有返回答案字符串长度,则更新ans
                if j > len(ans):
                    ans = word
                # 如果当前word长度=已有答案长度,但是字典序更靠前,也更新ans
                elif j == len(ans) and word < ans:
                    ans = word
        return word

# 思路2
class Solution:
    def findLongestWord(self, s: str, d: List[str]) -> str:
            # 字典排序:长度降序,字典序升序
            d.sort(key =lambda word : (-len(word),word))

            # 遍历字典
            for word in d:
                index = 0 # 初始搜索起点
                # 在s中找word的每个字符ch:
                for ch in word:
                    index = s.find(ch,index) + 1 # 因为有重复字符,注意更新搜索起点
                    # 如果find返回-1, index=0:说明没找到,这个word不是子串
                    if not index : 
                        break
                # 如果ch匹配循环顺利结束,则该字符串就是要返回的字符串
                else:
                    return word
            return ''
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值