1. 两数之和
1.暴力搜索
1
2
3
4
5
6
7
8
9
10
11
|
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
for i in range(len(nums)):
for j in range(i+1,len(nums)):
if nums[i] + nums[j] == target:
return i,j
|
2.哈希表
理论基础 (摘自https://www.programmercarl.com/)
首先什么是 哈希表,哈希表(英文名字为Hash table,国内也有一些算法书籍翻译为散列表,大家看到这两个名称知道都是指hash table就可以了)。
1
2
3
4
5
6
7
8
|
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
hashtable = dict()
for i, num in enumerate(nums):
if target - num in hashtable:
return [hashtable[target - num], i]
hashtable[nums[i]] = i
return []
|
2. 两数相加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
|
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
new_node = ListNode(0)
new_node_bak = new_node
carr = 0
tmp_val1 ,tmp_val2 = 0,0
while(l1 or l2):
tmp_val1 = l1.val if l1 else 0
tmp_val2 = l2.val if l2 else 0
tmp_val = tmp_val1 + tmp_val2 + carr
new_node.val = tmp_val % 10
carr = tmp_val // 10
l1 = l1.next if l1 else 0
l2 = l2.next if l2 else 0
if carr:
new_node.next = ListNode(carr)
# 如果没有进位 判断next是否有值如果有值就创建节点 ,没有就什么也不干
elif l1 or l2:
new_node.next = ListNode(0)
new_node = new_node.next
return new_node_bak
|
递归解法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def addTwoNumbers(self, l1: Optional[ListNode], l2: Optional[ListNode]) -> Optional[ListNode]:
# 如果l1不存在返回l2,如果l2不存在返回l1
if not l1:
return l2
if not l2:
return l1
# 将l2 和l1相加
l1.val += l2.val
# 判断和是否大于等于10
if l1.val >= 10:
# 如果大于等于10 则将进位和v1.next进行相加,然后正常进行相加
l1.next = self.addTwoNumbers(ListNode(l1.val // 10),l1.next)
# 将当前位置的值改为个位
l1.val = l1.val % 10
# 如果不大于十则进行正常的相加
l1.next = self.addTwoNumbers(l1.next,l2.next)
return l1
|
3. 无重复字符
建立一个哈希表 然后采用双指针的方法来去除重复字符,最后得到最大长度
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
# 建立一个集合
s1 = set()
# 记录当前长度
now_len = 0
# 记录最大长度
max_len = 0
# 记录左指针index
j = 0
for i in range(len(s)):
now_len += 1
# 如果碰到了相同的字符 则移除左指针指向的内容知道没有相同的字符
while s[i] in s1:
s1.remove(s[j])
j += 1
now_len -= 1
if now_len > max_len: max_len = now_len
s1.add(s[i])
return max_len
|
704 二分查找
注意为了防止溢出 middle需要写为left + (right - left) // 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class Solution:
def search(self, nums: List[int], target: int) -> int:
right = len(nums) - 1
left = 0
middle = 0
while(left <= right):
middle = left + (right - left) // 2 # (right + left) // 2
if(nums[middle] > target):
right = middle - 1
elif(nums[middle] < target):
left = middle + 1
else:
return middle
return -1
|
35. 搜索插入位置
当没有target的时候,二分法的right < target的index
例如[1,3,5]找4,最终right == 1 left == 3所以插入位置即1 + 1 == 2 即3的后面
例如[1,4,5]找2,最终right == 0 left == 1所以插入位置即 0 + 1 ==1 即1的后面
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
left = 0
right = len(nums) - 1
middle = 0
#找到了返回
while(left <= right):
middle = left + (right - left) // 2
if(nums[middle] > target):
right = middle - 1
elif(nums[middle] < target):
left = middle + 1
else:
return middle
# 说明没有找到
return right + 1
|
34.在排序数组中查找元素的第一个和最后一个位置
数是连续的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
def get_middle():
left = 0
right = len(nums) - 1
middle = 0
while(left <= right):
middle = left + (right - left) // 2
if nums[middle] > target:
right = middle - 1
elif nums[middle] < target:
left = middle + 1
else:
return middle
return -1
idx = get_middle()
print(idx)
if idx == -1: return [-1,-1]
else:
left,right = idx,idx
while( left - 1 >= 0 and nums[left - 1] == target ):
left -= 1
while( right + 1 < len(nums) and nums[right + 1] == target):
right += 1
return [left,right]
|
69. x 的平方根
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
class Solution:
def mySqrt(self, x: int) -> int:
# nums = [m for m in range(x + 1)]
# left = 0
# right = len(nums) - 1
# middle = 0
# while(left <= right):
# middle = left + (right - left) // 2
# # print(middle)
# if nums[middle] * nums[middle] == x:
# return nums[middle]
# elif nums[middle] * nums[middle] < x:
# left = middle + 1
# else:
# right = middle - 1
# return nums[right]
left,right,middle = 0,x,0
while(left <= right):
middle = left + (right - left) // 2
if middle * middle < x:
left = middle + 1
elif middle * middle > x:
right = middle - 1
else:
return middle
return right
|
367.有效的完全平方数
1
2
3
4
5
6
7
8
9
10
11
12
|
class Solution:
def isPerfectSquare(self, num: int) -> bool:
right,left,middle = num,0,0
while(left <= right):
middle = left + (right - left) // 2
if(middle * middle == num):
return True
elif middle * middle < num:
left = middle + 1
elif middle * middle > num:
right = middle -1
return False
|
633. 平方数之和
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Solution:
def judgeSquareSum(self, c: int) -> bool:
l,r = 0,int(c ** 0.5)
add_sum = 0
while(l <= r):
add_sum = l*l + r*r
if(add_sum == c):
return True
elif (add_sum > c):
r -= 1
else:
l += 1
return False
|
27. 移除元素
1
2
3
4
5
6
7
8
9
10
|
class Solution:
def removeElement(self, nums: List[int], val: int) -> int:
fast_index,slow_index = 0,0
for fast_index in range(len(nums)):
if(nums[fast_index] != val):
nums[slow_index] = nums[fast_index]
slow_index += 1
return slow_index
|
26. 删除有序数组中的重复项
1
2
3
4
5
6
7
8
9
|
class Solution:
def removeDuplicates(self, nums: List[int]) -> int:
fastIndex,slowIndex = 0,0
for fastIndex in range(len(nums)):
if(nums[fastIndex] != nums[slowIndex]):
slowIndex += 1
nums[slowIndex] = nums[fastIndex]
return slowIndex + 1
# print(nums[0:slowIndex + 1])
|
283. 移动零
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Solution:
def moveZeroes(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
fastIndex,slowIndex = 0,0
for fastIndex in range(len(nums)):
if nums[fastIndex] != 0:
nums[slowIndex] = nums[fastIndex]
slowIndex += 1
# for i in range(len())
# print(slowIndex)
for x in range(len(nums) - slowIndex):
nums[slowIndex] = 0
slowIndex += 1
|
844. 比较含退格的字符串
双指针法 (快慢指针)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class Solution:
def backspaceCompare(self, s: str, t: str) -> bool:
def get_list(s1:str) -> list:
fastIndex,slowIndex = 0,0
s1 = list(s1)
for fastIndex in range(len(s1)):
if s1[fastIndex] == '#' and slowIndex >= 0:
s1[slowIndex] = '\x00'
if slowIndex == 0:
slowIndex = 0
else:
slowIndex -= 1
else:
s1[slowIndex] = s1[fastIndex]
slowIndex += 1
print(slowIndex)
return s1[0:slowIndex]
s = get_list(s)
t = get_list(t)
if s == t:
return True
else:
return False
|
有序数组的平方
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Solution:
def sortedSquares(self, nums: List[int]) -> List[int]:
l,r = 0,len(nums) - 1
nums2 = [x for x in range(len(nums))]
size = len(nums) - 1
while(size >= 0):
if nums[l]*nums[l] > nums[r]*nums[r]:
nums2[size] = nums[l] * nums[l]
l += 1
else:
nums2[size] = nums[r] * nums[r]
r -= 1
size -= 1
# print(nums2)
return nums2
|
排序算法
冒泡排序
1
2
3
4
5
6
7
8
9
|
def bubbleSort(s:list):
n = len(s)
for i in range(n):
for j in range(0,n - i - 1):
if s[j] > s[j + 1]:
tmp = s[j + 1]
s[j + 1] = s[j]
s[j] = tmp
|
209. 长度最小的子数组
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Solution:
#使用滑动窗口来做
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
add_sum = 0
sub_length = float("inf") #定义一个无限大的数
j = 0
for i in range(len(nums)):
add_sum += nums[i]
while add_sum >= target:
sub_length = min(i - j + 1,sub_length) #符合条件 每次取最小值
add_sum -= nums[j]
j += 1
return 0 if sub_length == float("inf") else sub_length
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class Solution:
#使用滑动窗口来做
def minSubArrayLen(self, target: int, nums: List[int]) -> int:
add_sum = 0
sub_length = float("inf") #定义一个无限大的数
j = 0
for i in range(len(nums)):
add_sum += nums[i]
while add_sum - nums[j] >= target:
add_sum -= nums[j]
j += 1
if j > 0:
sub_length = min(i - j + 1,sub_length) #每次取最小值
elif add_sum >= target:
sub_length = min(i - j + 1,sub_length)
elif j == 0 and sub_length == float("inf"):
sub_length = float("inf")
print(i,j,sub_length)
if sub_length == float("inf"):
return 0
else:
return sub_length
# print(sub_length)
|
904. 水果成篮
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class Solution:
def totalFruit(self, fruits: List[int]) -> int:
# 定义一个Counter
j = 0
m = 0
c = Counter()
for i in range(len(fruits)):
c[fruits[i]] += 1
while(len(c) > 2): #不符合条件
c[fruits[j]] -= 1
if c[fruits[j]] == 0:
c.pop(fruits[j])
j += 1
m = max(m,i - j + 1) #符合条件之后取最大值
return m
|
3. 无重复字符的最长子串
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Solution:
def lengthOfLongestSubstring(self, s: str) -> int:
s1 = set() #建立一个集合 哈希表函数有Counter: 用来计数的 还有dict
s = list(s)
j = 0
max_length = 0
for i in range(len(s)):
while s[i] in s1:
s1.remove(s[j])
j += 1
s1.add(s[i])
max_length = max(max_length,i - j + 1)
return max_length
|
203. 移除链表元素
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
dummy = ListNode(next = head)
cur = dummy
while(cur.next):
if(cur.next.val == val):
cur.next = cur.next.next
else:
cur = cur.next
return dummy.next
|
4. 寻找两个正序数组的中位数
/x返回小数,//x返回整数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
size1 = len(nums1)
size2 = len(nums2)
size = size1 + size2
nums = [x for x in range(size)]
for i in range(size1):
nums[i] = nums1[i]
for i in range(len(nums1),size):
nums[i] = nums2[i - size1]
# print(nums)
# 冒泡排序
tmp_num = 0
for i in range(size):
for j in range(size - i - 1):
if nums[j] > nums[j + 1]:
tmp_num = nums[j + 1]
nums[j + 1] = nums[j]
nums[j] = tmp_num
# print(nums,size)
if size % 2 != 0:
return float(nums[(size - 1) // 2])
else:
# num:float = (float(nums[size // 2]) + float(nums[size // 2 - 1]))
# print(num / 2)
return (float(nums[size // 2]) + float(nums[size // 2 - 1])) / 2
|
206. 反转链表
迭代法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
# Definition for singly-linked list.
# 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]:
pre = None
cur = head
while(cur != None):
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
return pre
|
递归
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
# Definition for singly-linked list.
# 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]:
def reverse(cur: Optional[ListNode],pre: Optional[ListNode]):
# 结束标志
if(cur == None):
return pre
# 实际调用的方法
tmp = cur.next
cur.next = pre
pre = cur
cur = tmp
# 递归
return reverse(cur,pre)
return reverse(head,None)
|
递归2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
i = 0
def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
def reverse(cur: Optional[ListNode]):
if not cur:
return None
next_note = reverse(cur.next)
# 如果是尾节点
if next_note == None:
self.i = cur
return cur
# 如果是初节点,则将初节点的值赋值为None
if head == cur:
cur.next = None
next_note.next = cur
return self.i
# 如果是中间节点
else:
next_note.next = cur
return cur
return reverse(head)
|
707. 设计链表
单向链表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
class Node(object):
def __init__(self,x):
self.val = x
self.next = None
class MyLinkedList:
def __init__(self):
self.head = Node(0)
self.size = 0
def get(self, index: int) -> int:
head = self.head
if index <= self.size - 1:
while(index):
head = head.next
index -= 1
return head.val
else:
return -1
def addAtHead(self, val: int) -> None:
dummy = Node(val)
dummy.next = self.head
self.head = dummy
self.size += 1
def addAtTail(self, val: int) -> None:
head = self.head
size = self.size
# pre = head
if size:
while(size):
pre = head
head = head.next
size -= 1
pre.next = Node(val)
self.size += 1
else:
self.addAtHead(val)
def addAtIndex(self, index: int, val: int) -> None:
if index <= 0:
self.addAtHead(val)
elif index == self.size:
self.addAtTail(val)
elif index < self.size:
head = self.head
while(index):
pre = head
head = head.next
index -= 1
pre.next = Node(val)
pre.next.next = head
self.size += 1
else:
return 0
def deleteAtIndex(self, index: int) -> None:
if index > 0 and index <= self.size - 1:
head = self.head
while(index):
pre = head
head = head.next
index -= 1
pre.next = head.next
self.size -= 1
elif index == 0:
head = self.head
self.head = head.next
self.size -= 1
else:
return -1
# Your MyLinkedList object will be instantiated and called as such:
# obj = MyLinkedList()
# param_1 = obj.get(index)
# obj.addAtHead(val)
# obj.addAtTail(val)
# obj.addAtIndex(index,val)
# obj.deleteAtIndex(index)
|
19. 删除链表的倒数第 N 个结点
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
size = 0
dummy = head
while head:
head = head.next
size += 1
head = dummy
if size - n < 0:
return None
elif size == n:
head = head.next
return head
else:
for i in range(size - n - 1):
head = head.next
# print(head.val)
head.next = head.next.next
return dummy
|
快慢指针法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
fast = head
slow = head
# dummy = ListNode(next = head)
for i in range(n):
fast = fast.next
if fast:
while(fast.next):
fast = fast.next
slow = slow.next
slow.next = slow.next.next
else:
head = head.next
return head
|
242. 有效的字母异位词
1
2
3
4
5
6
7
8
9
10
11
|
class Solution:
def isAnagram(self, s: str, t: str) -> bool:
x = Counter()
for i in s:
x[i] += 1
for i in t:
x[i] -= 1
for j in x:
if x[j] != 0:
return False
return True
|
349. 两个数组的交集
1
2
3
4
5
6
7
8
9
10
11
12
|
class Solution:
def intersection(self, nums1: List[int], nums2: List[int]) -> List[int]:
s = Counter()
m = []
for x in nums1:
s[x] = 1
for j in nums2:
if j in s and s[j] == 1:
m.append(j)
s[j] = 0
print(m)
return m
|
1. 两数之和
1
2
3
4
5
6
7
8
9
|
class Solution:
def twoSum(self, nums: List[int], target: int) -> List[int]:
c = Counter()
for i in range(len(nums)):
if target - nums[i] in c:
return [c[target - nums[i]],i]
else:
c[nums[i]] = i
print("Not Found")
|
454. 四数相加 II
加法结合律,转化为两数相加
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class Solution:
def fourSumCount(self, nums1: List[int], nums2: List[int], nums3: List[int], nums4: List[int]) -> int:
c = Counter()
# 四数相加转化为两数下相加
for n1 in nums1:
for n2 in nums2:
if n1 + n2 in c:
c[n1 + n2] += 1
else:
c[n1 + n2] = 1
counter = 0
for n3 in nums3:
for n4 in nums4:
if -(n3 + n4) in c:
counter += c[-n3 - n4]
print(counter)
return counter
|
383. 赎金信
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class Solution:
def canConstruct(self, ransomNote: str, magazine: str) -> bool:
# 定义一个哈希表
c = Counter()
# 初始化
for n1 in magazine:
c[n1] += 1
#判断哈希表内是否存在,如果存在并且index大于等于1则进行减一,如果不存在则说明字符串里面不包含不满足条件
for n2 in ransomNote:
if n2 in c and c[n2] >= 1:
c[n2] -= 1
else:
return False
print(c)
return True
|
15. 三数之和
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
class Solution:
def threeSum(self, nums: List[int]) -> List[List[int]]:
nums = sorted(nums,reverse = False) #升序
dummy = []
size = len(nums)
for i in range(len(nums)):
if nums[i] > 0: #如果该数大于0 则表明后续没有没有任何两个数和当前数和为0
break
if i >= 1: #判断是否和上个数字重复,如果重复则继续
if nums[i] == nums[i - 1]:
continue
#三指针
l = i + 1
r = size - 1
while(l < r):
add_sum = nums[i] + nums[l] + nums[r]
if(add_sum == 0):
dummy.append([nums[i],nums[l],nums[r]])
while l < r and nums[l] == nums[l + 1]: #去重
l += 1
while l < r and nums[r] == nums[r - 1]: #去重
r -= 1
l += 1
r -= 1
#指针移动
elif(add_sum < 0):
l += 1
elif(add_sum > 0):
r -= 1
print(dummy)
return dummy
|
344. 反转字符串
1
2
3
4
5
6
7
8
9
10
11
12
|
class Solution:
def reverseString(self, s: List[str]) -> None:
"""
Do not return anything, modify s in-place instead.
"""
l = 0
r = len(s) - 1
while(l <= r):
s[l],s[r] = s[r],s[l]
l += 1
r -= 1
print(s)
|
18. 四数之和
和三数之和类似,加一个for循环
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
class Solution:
def fourSum(self, nums: List[int], target: int) -> List[List[int]]:
size = len(nums)
nums = sorted(nums)#升序排序
# print(nums)
ans = []
for i in range(size):
if i > 0 and nums[i] == nums[i - 1]: continue # 去重
# if nums[i] > target: return ans
for m in range(i + 1,size):
if m > i + 1 and nums[m] == nums[m - 1]: continue #如果当前字符和上一个字符相同则继续,即去重
l = m + 1
r = size - 1
while(l < r): #双指针
sum = nums[l] + nums[r] + nums[i] + nums[m]
if(sum == target):
ans.append([nums[i],nums[m],nums[l],nums[r]])
while(l < r) and nums[l] == nums[l + 1]: l += 1
while(l < r) and nums[r] == nums[r - 1]: r -= 1
l += 1
r -= 1
elif sum < target:
l += 1
elif sum > target:
r -= 1
print(ans)
return ans
|
剑指 Offer 05. 替换空格
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
class Solution:
def replaceSpace(self, s: str) -> str:
s = list(s)
n = len(s)
# counter = 0
# for i in s:
# if i == ' ':
# counter += 1
#计算空格数
counter = s.count(' ')
#扩展
s.extend([' '] * counter * 2)
m = len(s)
# 双指针 一个指向原来的字符串的末尾,一个指向扩展后的字符串的末尾
l = n - 1
r = m - 1
while(l >= 0):
if (s[l] != ' '):
s[r] = s[l]
r -= 1
l -= 1
else:
s[r - 2 : r + 1] = "%20"
r -= 3
l -= 1
return ''.join(s) #转换为字符串的形式
|
151. 反转字符串中的单词
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
class Solution:
def reverseWords(self, s: str) -> str:
# 去除多余空格
flags = 0
s = list(s)
ans = []
l,r = 0,len(s) - 1
# 使用双指针法,移除开头空格
while(s[l] == ' '): l += 1
## 移除末尾空格
while(s[r] == ' '): r -= 1
## 移除中间空格
while(l <= r):
if(s[l] != ' '):
ans.append(s[l])
l += 1
elif(s[l] == ' ' and s[l - 1] != ' '):
ans.append(s[l])
l += 1
else:
l += 1
print(ans)
# 翻转整个字符串
l = 0
r = len(ans) - 1
while(l < r):
ans[l],ans[r] = ans[r],ans[l]
l += 1
r -= 1
print(ans)
# 在末尾扩展一个空格
ans.extend([' '])
# 单词反转
l = 0
n = len(ans)
for tmp_r in range(n):
if(ans[tmp_r] == ' '):
r = tmp_r - 1
# print(r)
while(l < r):
ans[l],ans[r] = ans[r],ans[l]
l += 1
r -= 1
l = tmp_r + 1
ans = ans[:-1]
# print(ans)
return ''.join(ans)
|
28. 找出字符串中第一个匹配项的下标
常规解法
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
size_haystack = len(haystack)
size = len(needle)
# x = []
if haystack == needle:
# 如果两个字符串是相同的则直接返回0
return 0
for i in range(size_haystack):
# 匹配
if(haystack[i:i + size] == needle):
return i
return -1
|
KMP解法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
class Solution:
def strStr(self, haystack: str, needle: str) -> int:
haystack_len = len(haystack)
needle_len = len(needle)
k = -1
# 初始化prefix数组
prefix = [-1 for x in range(needle_len)]
# 生成next数组
for i in range(1,needle_len):
while k > -1 and needle[k + 1] != needle[i]:
k = prefix[k]
prefix[i] = k
if needle[k + 1] == needle[i]:
k += 1
prefix[i] = k
k = -1
for i in range(haystack_len):
# 遇到不符合的字符串进行回退操作
while(k > -1 and needle[k + 1] != haystack[i]):
k = prefix[k]
if needle[k + 1] == haystack[i]:
k += 1
# print(i,k)
if k == needle_len - 1:
# print(k,needle_len)
return i - k
return -1
|
459. 重复的子字符串
KMP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
class Solution:
def repeatedSubstringPattern(self, s: str) -> bool:
s = list(s)
# 初始化prefix数组
prefix = [-1 for x in range(len(s))]
# print(prefix)
k = -1
# 生成prefix数组
for i in range(1,len(s)):
while k > -1 and s[k + 1] != s[i]:
k = prefix[k]
print(i,k)
prefix[i] = k
if s[k + 1] == s[i]:
k += 1
prefix[i] = k
print(prefix)
# 如果prefix[-1]不等于说明存在相同的前后缀并且字符串长度可以被(字符串长度 - 最长相等前后缀长度)整除则说明是重复字符组成
#数组长度减去最长相同前后缀的长度相当于是第一个周期的长度,也就是一个周期的长度,如果这个周期可以被整除,就说明整个数组就是这个周期的循环
if prefix[-1] != -1 and len(s) % (len(s) - (prefix[-1] + 1)) == 0:
return True
return False
# print(prefix)
|
232. 用栈实现队列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
class MyQueue:
def __init__(self):
self.array = []
def push(self, x: int) -> None:
self.array.append(x)
return self.array
def pop(self) -> int:
x = self.array[0]
self.array.pop(0)
return x
def peek(self) -> int:
return self.array[0]
def empty(self) -> bool:
if self.array:
return False
else:
return True
# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()
|
225. 用队列实现栈
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
|
class MyStack:
def __init__(self):
self.array = []
def push(self, x: int) -> None:
self.array.append(x)
return self.array
def pop(self) -> int:
x = self.array[-1]
self.array.pop(-1)
return x
def top(self) -> int:
return self.array[-1]
def empty(self) -> bool:
if self.array:
return False
else:
return True
# Your MyStack object will be instantiated and called as such:
# obj = MyStack()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.top()
# param_4 = obj.empty()
|
1047. 删除字符串中的所有相邻重复项
1
2
3
4
5
6
7
8
9
10
11
12
|
class Solution:
def removeDuplicates(self, s: str) -> str:
# 消消乐
# s = list(s)
ans = []
for i in range(len(s)):
if ans and s[i] == ans[-1]:
ans.pop(-1)
else:
ans.append(s[i])
# print(ans)
return ''.join(ans)
|
双指针
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class Solution:
def removeDuplicates(self, s: str) -> str:
# 双指针
s = list(s)
fast = slow = 0
while(fast < len(s)):
# 相同则后退
if slow > 0 and s[slow] == s[slow - 1]:
slow -= 1
fast += 1
s[slow] = s[fast]
# 不同直接赋值
else:
s[slow] = s[fast]
slow += 1
fast += 1
return ''.join(s[0:slow])
|
150. 逆波兰表达式求值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class Solution:
def evalRPN(self, tokens: List[str]) -> int:
ans = []
for i in tokens:
if i == '+' or i == '-' or i == '*' or i == '/' and len(ans) >= 2:
x1 = ans.pop(-2)
x2 = ans.pop(-1)
x3 = eval(f'{x1} {i} {x2}')
ans.append(int(x3))
# print(ans)
else:
ans.append(i)
# print(ans)
return int(ans[0])
|
239. 滑动窗口最大值
单调栈,栈里面的值都是单调递增或者递减
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class Solution:
def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
size = len(nums)
d = deque()
ans = []
for i in range(k):
while d and nums[i] >= nums[d[-1]]:
d.pop()
d.append(i)
ans.append(nums[d[0]])
for i in range(k,size):
while d and nums[i] >= nums[d[-1]]:
d.pop()
d.append(i)
while d and d[0] <= i - k:
d.popleft()
ans.append(nums[d[0]])
# print(ans)
return ans
|
347. 前 K 个高频元素
小顶堆的初利用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class Solution:
def topKFrequent(self, nums: List[int], k: int) -> List[int]:
s = {}
for i in range(len(nums)):
s[nums[i]] = s.get(nums[i],0) + 1
d = []
for num,value in s.items():
heappush(d,(value,num))
if len(d) > k:
heappop(d) # pop出来的是最小的也就是顶部的值
result = [0] * k
# pop的时候是从小到大pop,因此需要倒序一下,即从大大小输出
for i in range(-1,k - 1,1):
result[i] = heappop(d)[1]
return result
|
77. 组合
回溯算法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
# 回溯算法
path = []
res = []
def dfs(n,k,startIdx):
# 结束标志
if len(path) == k:
res.append(path[:])# 添加path副本
return
for i in range(startIdx,n + 1):
path.append(i)
dfs(n,k,i + 1)
path.pop() #回溯
dfs(n,k,1)
return res
|
剪枝优化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
class Solution:
def combine(self, n: int, k: int) -> List[List[int]]:
# 回溯算法
path = []
res = []
def dfs(n,k,startIdx):
# 结束标志
if len(path) == k:
res.append(path[:])# 添加path副本
return
lastIdx = n - (k - len(path)) + 2
for i in range(startIdx,lastIdx):
path.append(i)
dfs(n,k,i + 1)
# print(path)
path.pop()
dfs(n,k,1)
# print(res)
return res
|
组合总和 III
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
class Solution:
def __init__(self):
self.res = []
self.path = []
self.sum = 0
def dfs(self,k,n,startIdx):
if self.sum > n: #剪枝
return
if len(self.path) == k:
if self.sum == n:
self.res.append(self.path[:])
return
for i in range(startIdx,10):
self.sum += i
self.path.append(i)
self.dfs(k,n,i + 1)
self.path.pop()
self.sum -= i
def combinationSum3(self, k: int, n: int) -> List[List[int]]:
self.dfs(k,n,1)
print(self.res)
return self.res
|
电话号码的字母组合
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
class Solution:
def __init__(self):
self.phoneNumMaps = {
'2':'abc',
'3':'def',
'4':'ghi',
'5':'jkl',
'6':'mno',
'7':'pqrs',
'8':'tuv',
'9':'wxyz'
}
self.ans = []
self.answer = []
def letterCombinations(self, digits: str) -> List[str]:
if len(digits) == 0:
return []
self.dfs(digits,0)
return self.ans
def dfs(self,digits,idx):
if idx == len(digits):
self.ans.append(''.join(self.answer[:]))
return
m = self.phoneNumMaps[digits[idx]]
for x in m:
self.answer.append(x)
self.dfs(digits,idx + 1)
self.answer.pop()
|
组合总和
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
class Solution:
def __init__(self):
self.ans = []
self.sum = 0
self.answer = []
def dfs(self,candidates: List[int], target: int):
if self.sum > target:
return
if self.sum == target:
answer = sorted(self.answer)
if answer not in self.ans:
self.ans.append(answer)
return
for i in candidates:
self.sum += i
self.answer.append(i)
self.dfs(candidates,target)
self.answer.pop()
self.sum -= i
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
self.dfs(candidates,target)
return self.ans
|
组合总和 II
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
|
class Solution:
def __init__(self):
self.sum = 0
self.ans = []
self.answer = []
def dfs(self,candidates: List[int], target: int,startIdx):
if self.sum > target:
return
if self.sum == target and self.answer not in self.ans:
print(self.answer)
self.ans.append(self.answer[:])
return
for i in range(startIdx,len(candidates)):
if i > startIdx and candidates[i] == candidates[i - 1]: #对同一层去重,如果startIdx > 0的话就是对所有行去重
continue
self.sum += candidates[i]
self.answer.append(candidates[i])
self.dfs(candidates,target,i + 1)
self.answer.pop()
self.sum -= candidates[i]
def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
candidates = sorted(candidates)
self.dfs(candidates,target,0)
return self.ans
|
复原 IP 地址
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
class Solution:
def __init__(self):
self.ans = []
def dfs(self,s: str,startIdx: int,pointNum: int):
if pointNum == 3:
if self.is_valid(s,startIdx,len(s) - 1):
self.ans.append(s[:])
return
for i in range(startIdx,len(s)):
if self.is_valid(s,startIdx,i):
s = s[:i + 1] + '.' + s[i + 1:]
self.dfs(s,i + 2,pointNum + 1)
s = s[:i + 1] + s[i + 2:]
else:
break
def is_valid(self,s: str,startIdx,endIdx):
if startIdx > endIdx : return False
if s[startIdx] == '0' and startIdx != endIdx:
# print(f"startIdx: {startIdx} endIdx: {endIdx} ")
return False
if 0 <= int(s[startIdx:endIdx + 1]) <= 255:
return True
else:
return False
def restoreIpAddresses(self, s: str) -> List[str]:
try:
self.dfs(s,0,0)
print(self.ans)
return self.ans
except Exception as e:
print(e)
return self.ans
|
子集
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
class Solution:
def __init__(self):
self.ans = []
self.result = []
def dfs(self,nums,start):
self.result.append(self.ans[:])
if start == len(nums):
return
for i in range(start,len(nums)):
self.ans.append(nums[i])
self.dfs(nums,i + 1)
self.ans.pop()
def subsets(self, nums: List[int]) -> List[List[int]]:
self.dfs(nums,0)
return self.result
|
子集 II
排列一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
class Solution:
def __init__(self):
self.ans = []
self.result = []
def dfs(self,nums,start):
# if self.ans not in self.result:
# self.result.append(self.ans[:])
ans = sorted(self.ans[:])
if ans not in self.result:
self.result.append(ans)
# print(start)
if start == len(nums): return
for i in range(start,len(nums)):
self.ans.append(nums[i])
self.dfs(nums,i + 1)
self.ans.pop()
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
self.dfs(nums,0)
print(self.result)
return self.result
|
去重版本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
class Solution:
def __init__(self):
self.ans = []
self.result = []
def dfs(self,nums,start):
if self.ans not in self.result:
self.result.append(self.ans[:])
if start == len(nums): return
for i in range(start,len(nums)):
if i > start and nums[i] == nums[i - 1]: #去重
continue
self.ans.append(nums[i])
self.dfs(nums,i + 1)
self.ans.pop()
def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
nums = sorted(nums)
self.dfs(nums,0)
print(self.result)
return self.result
|
递增子序列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
class Solution:
def __init__(self):
self.ans = []
self.result = []
def dfs(self,nums,start):
ans = sorted(self.ans)
if ans != self.ans:
pass
elif ans == self.ans and ans not in self.result and len(ans) > 1:
self.result.append(ans)
if start == len(nums):
return
for i in range(start,len(nums)):
if i > start and nums[i] == nums[i - 1]: continue
self.ans.append(nums[i])
self.dfs(nums,i + 1)
self.ans.pop()
def findSubsequences(self, nums: List[int]) -> List[List[int]]:
self.dfs(nums,0)
print(self.result)
return self.result
|
全排列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
class Solution:
def __init__(self):
self.ans = []
self.result = []
self.tmp = 0
def dfs(self,nums,flags):
if flags == len(nums):
if self.ans not in self.result:
self.result.append(self.ans[:])
return
for i in range(len(nums)):
if nums[i] in self.ans:
continue
self.tmp = nums[i]
self.ans.append(nums[i])
self.dfs(nums,flags + 1)
self.ans.pop()
def permute(self, nums: List[int]) -> List[List[int]]:
self.dfs(nums,0)
print(self.result)
return self.result
|
全排列 II
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
|
class Solution:
def __init__(self):
self.ans = []
self.result = []
self.used = 0
def dfs(self,nums,flags):
if len(self.ans) == len(nums) and self.ans not in self.result:
self.result.append(self.ans[:])
if flags == len(nums):
return
for i in range(len(nums)):
if not self.used[i]: #保证在不同层里面不出现相同的数字
if i > 0 and nums[i] == nums[i - 1] and not self.used[i - 1]: #在同一层里面进行去重
print(self.used[i - 1])
continue #剪枝
self.used[i] = 1
self.ans.append(nums[i])
self.dfs(nums,flags + 1)
self.ans.pop()
self.used[i] = 0
def permuteUnique(self, nums: List[int]) -> List[List[int]]:
self.used = [0] * len(nums)
self.dfs(nums,0)
# print(self.s)
return self.result
|
贪心算法初尝试 - 分发饼干
局部最优到整体最优
1
2
3
4
5
6
7
8
9
|
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
g = sorted(g)
s = sorted(s)
res = 0
for i in range(len(s)):
if res < len(g) and s[i] >= g[res]:
res += 1
return res
|
贪心算法二 - 最大子数组和
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
class Solution:
def getSum(self,nums,start,end):
add_sum = 0
for i in range(start,end):
add_sum += nums[i]
return add_sum
def maxSubArray(self, nums: List[int]) -> int:
ans = 0
result = -float("inf") #定义一个最小值
for i in range(len(nums)):
ans += nums[i]
if ans > result:
result = ans
elif ans <= 0:
ans = 0
print(result)
return result
|
摆动序列
1
2
3
4
5
6
7
8
9
|
class Solution:
def wiggleMaxLength(self, nums: List[int]) -> int:
prev,cur,res = 0,0,1
for i in range(len(nums) - 1):
cur = nums[i + 1] - nums[i]
if cur * prev <= 0 and cur != 0: #如果两个差值小于等于0,则说明是摆动,如果cur等于0则说明是平的
res += 1
prev = cur
return res
|
买卖股票的最佳时机 II
贪心算法,只收集正利润
1
2
3
4
5
6
7
|
class Solution:
def maxProfit(self, prices: List[int]) -> int:
result = 0
for i in range(len(prices) - 1):
tmp_value = max(prices[i + 1] - prices[i],0)
result += tmp_value
return result
|
跳跃游戏
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Solution:
def canJump(self, nums: List[int]) -> bool:
size = len(nums)
if len(nums) == 1: return True
ans = 0
for i in range(len(nums) - 1):
if i <= ans:#下一步可以跳到
ans = max(ans,i + nums[i])
if ans >= len(nums) - 1:
return True
return False
|
跳跃游戏Ⅱ
1
2
3
4
5
6
7
8
9
10
11
|
class Solution:
def jump(self, nums: List[int]) -> int:
ans = 0
max_num = 0
end = 0
for i in range(len(nums) - 1):#最后一个位置没有意义
max_num = max(i + nums[i],max_num) # 每次取跳跃的最大值
if i == end: #如果达到最大值,则进行下一次跳跃,跳跃的终点为下一次的最大值
end = max_num
ans += 1
return ans
|