这里的题是根据 CS-Notes里的顺序来一步步复习。

双指针

165两数之和 II - 输入有序数组

题目描述

给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。

函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。

说明:

返回的下标值(index1 和 index2)不是从零开始的。

你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。

示例:

输入: numbers = [2, 7, 11, 15], target = 9
输出: [1,2]
解释: 2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。

题解(python)

class Solution(object):
def twoSum(self, numbers, target):
"""
:type numbers: List[int]
:type target: int
:rtype: List[int]
"""
if (numbers == None):
return None
i = 0
j = len(numbers)-1
while(i<j):
s = numbers[i] + numbers[j]
if ( s == target):
return [i+1,j+1]
elif(s < target):
i = i + 1
else:
j = j - 1
return [-1,-1]

1 两数之和 (这道不是双指针,一遍哈希表)

题目描述

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

给定 nums = [2, 7, 11, 15], target = 9

因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

题解

# 用一遍哈希表,也就是python里的字典
# 将每个数先存进去,相同的key,会因为hash_map[n]=i这句而覆盖掉,边存便判断hash_map里是否存在满足条件的key
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hash_map = {}
for i,n in enumerate(nums):
if (target-n) in hash_map.keys():
return [hash_map[target-n], i]
hash_map[n] = i
return [-1,-1]

633平方数之和

题目描述

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

示例1:

输入: 5
输出: True
解释: 1 * 1 + 2 * 2 = 5

示例2:

输入: 3
输出: False

题解

class Solution:
def judgeSquareSum(self, c: int) -> bool:
i = 0
j = int(math.sqrt(c)) while(i<=j):
s = i*i + j*j
if(s == c):
return True
elif(s > c):
j = j - 1
else:
i = i + 1 return False

680验证回文字符串 Ⅱ

题目描述

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

示例 1:

输入: "aba"
输出: True

示例 2:

输入: "abca"
输出: True

解释: 你可以删除c字符。

注意:

字符串只包含从 a-z 的小写字母。字符串的最大长度是50000。

题解

解法一

class Solution:
def validPalindrome(self, s: str) -> bool:
if(s[::-1] == s):
return True
else:
n = len(s)
i,j = 0,n-1
while(i<j):
if(s[i]==s[j]):
i += 1
j -= 1
continue
else:
a = s[i+1:j+1]
b = s[i:j]
return a[::-1]==a or b[::-1] == b

解法二

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, j = i+1, j-1
else:
a = s[i+1: j+1]
b = s[i: j]
return a == a[::-1] or b == b[::-1]

python里判断回文很简单a == a[::-1]就行,而这里我发现a[::-1] == a比 a == a[::-1]要耗时更多。

这道题关键就是删去一个字符

88合并两个有序数组

题目描述

给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。

说明:

初始化 nums1 和 nums2 的元素数量分别为 m 和 n。

你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。

示例:

输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6], n = 3 输出: [1,2,2,3,5,6]

题解

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.
"""
i,j,k = m-1, n-1, m+n-1
while i>=0 or j>=0:
if i<0:
nums1[k] = nums2[j]
k -= 1
j -= 1
elif j<0:
nums1[k] = nums1[i]
k -= 1
i -= 1
elif nums1[i] > nums2[j]:
nums1[k] = nums1[i]
k -= 1
i -= 1
else:
nums1[k] = nums2[j]
k -= 1
j -= 1
# 另一种32 ms
class Solution:
def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
p1=m-1
p2=n-1
p=m+n-1
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
print(p2)
if p2>=0:
nums1[:p2+1]=nums2[:p2+1]

难点在于从后开始往前扫。这个32ms的例子的思想在于:p每移动一格,p1或p2肯定会移动一格去替换掉p处的值,当p1或者p2变成-1移到末尾时,分两种情况:

  • p1 为 -1, 这时将nums2剩下元素填入即nums1[:p2+1] = nums2[:p2+1]
  • p2 为 -1, 这时nums1剩下元素基本不用动。
  • 或者考虑两种极端情况:nums1 = [1,2,3,0,0,0] nums2= [4,5,6]; nums1 = [4,5,6,0,0,0] nums2 = [1,2,3]也是如此

141环形链表

题目描述

给定一个链表,判断链表中是否有环。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:true
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0
输出:true
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1
输出:false
解释:链表中没有环。

题解

# 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:
# 问题在于NoneType没有next这个attribute
if head == None:
return False l,r = head, head.next
while r!=None and r.next!=None:
if l==r:
return True
else:
l = l.next
r = r.next.next
return False

使用双指针,快慢指针。一个指针每次移动一个节点,一个指针每次移动两个节点,如果存在环,那么这两个指针一定会相遇。

一开始l,r分别初始化为head和head.next,l走得慢,r走得快。如果在前走的快的r还与l相遇了,那么肯定存在环。

这里的r只需要判断r和r.next不为None就可以了。判断r的目的是为了r.next不报错不然r.next直接报错。

需注意,一开始给l,r赋值之前要判断下head是否为None,不然head.next直接报错。

*142环形链表 II(附加题,熟悉下链表)

给定一个链表,返回链表开始入环的第一个节点。 如果链表无环,则返回 null。

为了表示给定链表中的环,我们使用整数 pos 来表示链表尾连接到链表中的位置(索引从 0 开始)。 如果 pos 是 -1,则在该链表中没有环。

说明:不允许修改给定的链表。

示例 1:

输入:head = [3,2,0,-4], pos = 1
输出:tail connects to node index 1
解释:链表中有一个环,其尾部连接到第二个节点。

示例 2:

输入:head = [1,2], pos = 0
输出:tail connects to node index 0
解释:链表中有一个环,其尾部连接到第一个节点。

示例 3:

输入:head = [1], pos = -1
输出:no cycle
解释:链表中没有环。

题解

一开始没想出来,参考讨论区里的解法

解题思路:

  • 这类链表题目一般都是使用双指针法解决的,例如寻找距离尾部第K个节点、寻找环入口、寻找公共尾部入口等。

算法流程:

  1. 双指针第一次相遇: 设两指针 fast,slow 指向链表头部 head,fast 每轮走 22 步,slow 每轮走 11 步;

    1. 第一种结果: fast 指针走过链表末端,说明链表无环,直接返回 null;

      • TIPS: 若有环,两指针一定会相遇。因为每走 1 轮,fast 与 slow 的间距 +1,fast 终会追上 slow;
    2. 第二种结果: 当fast == slow时, 两指针在环中 第一次相遇 。下面分析此时fast 与 slow走过的 步数关系 :
      • 设链表共有 a+b 个节点,其中 链表头部到链表入口 有 a个节点(不计链表入口节点), 链表环 有 b 个节点(这里需要注意,a 和 b 是未知数,例如图解上链表 a=4,b=5b=5);设两

        指针分别走了 ff,ss 步,则有:
      1. fast 走的步数是slow步数的 2 倍,即 f = 2s;(解析: fast 每轮走 2 步)
      2. fast 比 slow多走了 n 个环的长度,即 f = s + nb;( 解析: 双指针都走过 a 步,然后在环内绕圈直到重合,重合时 fast 比 slow 多走环的长度整数倍 );
      • 以上两式相减得:f = 2nb,s = nb,即fast和slow 指针分别走了 2n,n 个 环的周长 (注意: n 是未知数,不同链表的情况不同)。
  2. 目前情况分析::

    • 如果让指针从链表头部一直向前走并统计步数k,那么所有 走到链表入口节点时的步数 是:k=a+nb(先走 a 步到入口节点,之后每绕 1 圈环( b 步)都会再次到入口节点)。
    • 而目前,slow 指针走过的步数为 nb 步。因此,我们只要想办法让 slow 再走 a 步停下来,就可以到环的入口。
    • 但是我们不知道 a 的值,该怎么办?依然是使用双指针法。我们构建一个指针,此指针需要有以下性质:此指针和slow 一起向前走 a 步后,两者在入口节点重合。那么从哪里走到入口节点需

      要 a 步?答案是链表头部head。
  3. 双指针第二次相遇:

    • slow指针 位置不变 ,将fast指针重新 指向链表头部节点 ;slow和fast同时每轮向前走 11 步;

      • TIPS:此时 f = 0f=0,s = nbs=nb ;
    • 当 fast 指针走到f = af=a 步时,slow 指针走到步s = a+nbs=a+nb,此时 两指针重合,并同时指向链表环入口 。
  4. 返回slow指针指向的节点。

复杂度分析:

时间复杂度 O(N):第二次相遇中,慢指针须走步数 a < a + b;第一次相遇中,慢指针须走步数 a + b - x < a + b,其中 x 为双指针重合点与环入口距离;因此总体为线性复杂度;
空间复杂度 O(1):双指针使用常数大小的额外空间。

当走了a+nb时,位置为入口处;而第一次相遇后慢指针走的距离为nb,注意这两个n不相等,但nb再走a步就到了入口处,这时我们可以另设一个指针从head处走,每次一步,那么他就会与慢指针在入口处相遇。

题解

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
fast, slow = head, head
while True:
if not(fast and fast.next):
return
fast, slow = fast.next.next, slow.next
if fast == slow:
break
fast = head
while fast!=slow:
fast = fast.next
slow = slow.next
return slow

这里我之前在while里判断fast != None and fast.next != None,这样造成的问题就是判断为False时,我的返回一个空说明没环,不好写。所以判断最好还是在if里,循环用while True。

# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None class Solution:
def detectCycle(self, head: ListNode) -> ListNode:
if head == None:
return None
fast, slow = head, head
if fast.next!=None:
fast = fast.next.next
slow = slow.next
while fast != None and fast.next != None:
if fast!=slow:
fast = fast.next.next
slow = slow.next
else:
fast = head
while fast!=slow:
fast = fast.next
slow = slow.next
return slow return None

524通过删除字母匹配到字典里最长单词

题目描述

给定一个字符串和一个字符串字典,找到字典里面最长的字符串,该字符串可以通过删除给定字符串的某些字符来得到。如果答案不止一个,返回长度最长且字典顺序最小的字符串。如果答案不存在,则返回空字符串。

示例 1:

输入:
s = "abpcplea", d = ["ale","apple","monkey","plea"] 输出:
"apple"

示例 2:

输入:
s = "abpcplea", d = ["a","b","c"] 输出:
"a"

说明:

  1. 所有输入的字符串只包含小写字母。
  2. 字典的大小不会超过 1000。
  3. 所有输入的字符串长度不会超过 1000。

题解

def isSubStr(s:str, t:str):
#第一种,双指针
# l1,l2 = len(s), len(t)
# if l1 < l2:
# return False
# i,j = 0,0
# while (i<l1 and j<l2):
# if (s[i] != t[j]):
# i += 1
# else:
# i += 1
# j += 1 # return j == l2
#第二种
for i in t:
if i in s:
s = s[s.index(i)+1:]
else:
return False return True class Solution:
def findLongestWord(self, s: str, d: List[str]) -> str:
d.sort()
res = ''
if d:
for i in d:
if (len(i) < len(res) or (len(i)==len(res) and res < i)):
continue
else:
if (isSubStr(s, i)):
res = i return res

另外一种方法,先将d进行按照len进行降序排序,每一个元素那么最长的排最前面,短的后面~同样长的,就按照字典顺序:a<b<c<d这种排列。所以它不需要遍历d种所有元素

leetcode刷题-- 1. 双指针的更多相关文章

  1. LeetCode刷题总结-双指针、位运算和分治法篇

    本文总结LeetCode上有关双指针.位运算和分治法的算法题,推荐刷题总数14道.具体考点分析如下图: 一.双指针 1.字符串和数组问题 题号:424. 替换后的最长重复字符,难度中等 题号:828. ...

  2. Leetcode刷题笔记(双指针)

    1.何为双指针 双指针主要用来遍历数组,两个指针指向不同的元素,从而协同完成任务.我们也可以类比这个概念,推广到多个数组的多个指针. 若两个指针指向同一数组,遍历方向相同且不会相交,可以称之为滑动窗口 ...

  3. C#LeetCode刷题-双指针

    双指针篇 # 题名 刷题 通过率 难度 3 无重复字符的最长子串   24.5% 中等 11 盛最多水的容器   43.5% 中等 15 三数之和   16.1% 中等 16 最接近的三数之和   3 ...

  4. LeetCode刷题总结之双指针法

    Leetcode刷题总结 目前已经刷了50道题,从零开始刷题学到了很多精妙的解法和深刻的思想,因此想按方法对写过的题做一个总结 双指针法 双指针法有时也叫快慢指针,在数组里是用两个整型值代表下标,在链 ...

  5. LeetCode刷题总结-数组篇(上)

    数组是算法中最常用的一种数据结构,也是面试中最常考的考点.在LeetCode题库中,标记为数组类型的习题到目前为止,已累计到了202题.然而,这202道习题并不是每道题只标记为数组一个考点,大部分习题 ...

  6. LeetCode刷题总结-数组篇(下)

    本期讲O(n)类型问题,共14题.3道简单题,9道中等题,2道困难题.数组篇共归纳总结了50题,本篇是数组篇的最后一篇.其他三个篇章可参考: LeetCode刷题总结-数组篇(上),子数组问题(共17 ...

  7. LeetCode刷题的一点个人建议和心得

    目录 1.    为什么我们要刷LeetCode? 2.    LeetCode的现状和问题 3.    本文的初衷 4.    LeetCode刷题建议 4.1入门数据结构,打基础阶段 4.2 建立 ...

  8. 看完互联网大佬的「LeetCode 刷题手册」, 手撕了 400 道 Leetcode 算法题

    大家好,我是 程序员小熊 ,来自 大厂 的程序猿.相信绝大部分程序猿都有一个进大厂的梦想,但相较于以前,目前大厂的面试,只要是研发相关岗位,算法题基本少不了,所以现在很多人都会去刷 Leetcode ...

  9. LeetCode刷题模板(1):《我要打10个》之二分法

    Author       :  叨陪鲤 Email         : vip_13031075266@163.com Date          : 2021.01.23 Copyright : 未 ...

随机推荐

  1. 小杨排队(dp)

    链接:https://ac.nowcoder.com/acm/contest/3667/J 题目描述 小阳想要买个东西,然后就去了商店,发现进商店需要排队(生意太火爆!),然后就开始漫长的等待,他觉得 ...

  2. PHP 站内消息的表结构设计

    1)添加全站通知:信息存入到 tb_message 2)用户点开信息或者设置信息为已阅读:插入记录到 tb_message_readlog 如何设计存储的表?求最佳方案 CREATE TABLE `m ...

  3. MySQL基本查询

    1.查询某数据库中表的总数 select count(*) from information_schema.tables where table_schema='dbname'; 2.仅占一列显示某数 ...

  4. 关于强化神兽(圣兽)DBC参数详解

    狗的攻击类型是114,名称.攻击类型.攻击图像.怪物样子.怪物等级.不死系.破隐身.经验值.生命值.魔法值.防御.魔防.最小攻击.最大攻击.魔法力.道术力.敏捷.准确.行走速度.一步几格.行走等待.攻 ...

  5. 微信+QQ跳转

    加到对应页面的</body> 上面,或者<head> </head>之间 <script type="text/javascript"&g ...

  6. SSIS 从oracle 转数据回MS SQL

    SSIS 从oracle 转数据回MS SQL,转每月的销售记录,大概15000以内,在开发机器上没问题,部署到生产环境出现各种状况“ SSIS 无法从连接伺服器的OLE DB提供者BULK 提取资料 ...

  7. 解决游览器安装Vue.js devtools插件无效的问题

    一: 打开自己写的一个vue.js网页,发现这个图标并没有亮起来,还是灰色 解决方案:  1.我们先看看Vue.js devtools是否生效,打开Bilibili(https://www.bilib ...

  8. 吴裕雄 PYTHON 神经网络——TENSORFLOW 滑动平均模型

    import tensorflow as tf v1 = tf.Variable(0, dtype=tf.float32) step = tf.Variable(0, trainable=False) ...

  9. Mobility Express部署外部镜像服务器

    1.当我们部署完ME的时候,发现有一些AP虽然显示已经加入了WLC(ME),但是它其实并没有正常的工作,显示不可用: (Cisco Controller) >show ap su Number ...

  10. Ext插件中控件的xtype和类的对应关系总结

    xtype Class ------------- ------------------ box Ext.BoxComponent button Ext.Button buttongroup Ext. ...