双指针法系列
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