文章目录
语法
Java语法
java类似python collections.Counter的用法
int[], Integer[], List<Integer>, List<String> 互相转换
CPP语法
链表
001. Java链表结点定义
package structure;
public class ListNode {
public int val;
public ListNode next;
public ListNode() {
}
public ListNode(int val) {
this.val = val;
}
public ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
public static ListNode fromArray(int[] list) {
ListNode head = null;
ListNode tail = null;
for (int item : list) {
ListNode node = new ListNode(item);
if (head == null) {
head = node;
tail = node;
} else {
tail.next = node;
tail = node;
}
}
return head;
}
@Override
public String toString() {
StringBuilder res = new StringBuilder();
ListNode p = this;
while (p != null) {
res.append(p.val).append(" -> ");
p = p.next;
}
res.append("O");
return res.toString();
}
}
002. Python链表结点定义
# Definition for singly-linked list.
class ListNode:
def __init__(self, val=0, next=None):
self.val = val
self.next = next
@staticmethod
def fromList(lst):
head = None
tail = None
for item in lst:
node = ListNode(item)
if head is None:
head = node
tail = head
else:
tail.next = node
tail = node
return head
def __str__(self):
p = self
res = ""
while p is not None:
res += f"{p.val} -> "
p = p.next
res += "O"
return res
__repr__ = __str__
19. 删除链表的倒数第N个节点
瞎写的
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
p = head
k = 0
p2 = None
while p is not None:
p = p.next
k += 1
if (k - 1) == n:
p2 = head
if (k - 1) > n:
p2 = p2.next
if p2 is None and k == n:
head = head.next
elif p2.next is not None:
p2.next = p2.next.next
return head
官方题解
class Solution:
def removeNthFromEnd(self, head: ListNode, n: int) -> ListNode:
dummy = ListNode(0, head)
first = head
second = dummy
for i in range(n):
first = first.next
while first:
first = first.next
second = second.next
second.next = second.next.next
return dummy.next
还是官方的好, 我写的和屎一样。希望能默写一下官方题解
206. 反转链表
迭代法
时间复杂度: O ( n ) \mathcal O(n) O(n)
空间复杂度: O ( 1 ) \mathcal O(1) O(1)
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
pre = None
p = head
while p is not None:
tmp = p.next
p.next = pre
pre = p
if tmp is None:
break
p = tmp
return p
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
pre = None
p = head
while p is not None:
tmp = p.next
p.next = pre
pre = p
p = tmp
return pre
递归法
时间复杂度: O ( n ) \mathcal O(n) O(n)
空间复杂度: O ( n ) \mathcal O(n) O(n)
class Solution:
def reverseList(self, head: ListNode) -> ListNode:
if head is None or head.next is None:
return head
node = self.reverseList(head.next)
head.next.next = head
head.next = None
return node
说实话有点没看懂
143. 重排链表
乱写的解法
import math
class Solution:
def reorderList(self, head: ListNode) -> None:
"""
Do not return anything, modify head in-place instead.
"""
nodes = []
p = head
while p is not None:
nodes.append(p)
pre = p
p = p.next
pre.next = None
N = len(nodes)
mid = math.floor(len(nodes) / 2)
list2 = list(reversed(nodes[mid:]))
list1 = nodes[:mid]
if len(list2) > len(list1):
list1.append(list2.pop())
lst = [list1, list2]
for i in range(N):
if i == 0:
head = list1[0]
p = head
else:
p.next = lst[i % 2][i // 2]
p = p.next
按照题解默写的线性表解法
class Solution:
def reorderList(self, head: ListNode) -> None:
if head is None:
return None
p = head
vec = []
while p is not None:
vec.append(p)
p = p.next
i = 0
j = len(vec) - 1
while i < j:
vec[i].next = vec[j]
i += 1
if i == j:
break
vec[j].next = vec[i]
j -= 1
vec[i].next = None # 容易想错
234. 回文链表
234. 回文链表
快慢指针 + 翻转链表
class Solution:
def isPalindrome(self, head: ListNode) -> bool:
pre = None
slow = head
fast = head
while fast is not None and fast.next is not None:
tmp = slow.next
slow.next = pre
pre = slow
fast = fast.next.next
slow = tmp
21. 合并两个有序链表
瞎写的不带头结点的方法
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
pp = None
res = None
p1 = l1
p2 = l2
while p1 is not None or p2 is not None:
if p1 is None and p2 is not None:
p = p2
p2 = p2.next
elif p1 is not None and p2 is None:
p = p1
p1 = p1.next
else:
if p1.val < p2.val:
p = p1
p1 = p1.next
else:
p = p2
p2 = p2.next
if pp is not None:
pp.next = p
pp = pp.next
else:
pp = res = p
return res
看了题解后写的带头结点的方法
class Solution:
def mergeTwoLists(self, l1: ListNode, l2: ListNode) -> ListNode:
pp = dummy = ListNode(-1)
p1 = l1
p2 = l2
while p1 is not None and p2 is not None:
if p1.val < p2.val:
p = p1
p1 = p1.next
else:
p = p2
p2 = p2.next
pp.next = p
pp = pp.next
pp.next = p1 if p1 is not None else p2
return dummy.next
2. 两数相加
class Solution:
def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
p1 = l1
p2 = l2
ret = None
p = None
carry = 0
while p1 is not None or p2 is not None:
v1 = p1.val if p1 is not None else 0
v2 = p2.val if p2 is not None else 0
num = v1 + v2 + carry
node = ListNode(num % 10)
carry = num // 10
if ret is None:
ret = node
p = ret
else:
p.next = node
p = p.next
p1 = p1.next if p1 is not None else None
p2 = p2.next if p2 is not None else None
if carry:
p.next = ListNode(carry)
return ret
328. 奇偶链表
class Solution:
def oddEvenList(self, head: ListNode) -> ListNode:
if head is None: # 用例 []
return None
odds = None
evens = None
index = 1
p = head
evens_head = None
while p is not None:
if index % 2:
if odds is not None:
odds.next = p
odds = p
else:
if evens is not None:
evens.next = p
else:
evens_head = p
evens = p
p = p.next
index += 1
if evens is not None: # 用例 [1]
evens.next = None # 注意了
odds.next = evens_head
return head
class Solution:
def oddEvenList(self, head: ListNode) -> ListNode:
if not head:
return head
oddHead, evenHead = head, head.next
odd, even = oddHead, evenHead
while even and even.next:
odd.next = even.next
odd = odd.next # 别忘了自己要移动
even.next = odd.next
even = even.next
odd.next = evenHead
return head
141. 环形链表
class Solution:
def hasCycle(self, head: ListNode) -> bool:
if head is None or head.next is None:
return False
slow = head
fast = head.next
while slow != fast:
if not slow or not fast or not fast.next:
return False
slow = slow.next
fast = fast.next.next
return True
147. 链表插入排序
class Solution:
def insertionSortList(self, head: ListNode) -> ListNode:
if not head:
return head
dummyHead = ListNode(0)
dummyHead.next = head
lastSorted = head
curr = head.next
while curr:
# 排序区最后的元素小于等于当前元素,把当前元素放排序区后面就行
if lastSorted.val <= curr.val:
lastSorted = lastSorted.next
# 否则
else:
prev = dummyHead
while prev.next.val <= curr.val:
prev = prev.next
# prev.next.val > curr.val
# prev.val <= curr.val
lastSorted.next = curr.next
curr.next = prev.next
prev.next = curr
curr = lastSorted.next
return dummyHead.next
148. 链表归并排序
- 伪代码
merge函数参考 merge-two-sorted-lists
subLength = 1
while subLength < len(listNode):
构造 prev, curr
while curr 非空:
构造head1, head2, 两个链表长度为subLengh, 结尾为空
将curr指向下一个节点
合并两个有序链表
构造新的prev
subLength *= 2
class Solution:
def sortList(self, head: ListNode) -> ListNode:
def merge(head1: ListNode, head2: ListNode) -> ListNode:
dummyHead = ListNode(0)
temp, temp1, temp2 = dummyHead, head1, head2
while temp1 and temp2:
if temp1.val <= temp2.val:
temp.next = temp1
temp1 = temp1.next
else:
temp.next = temp2
temp2 = temp2.next
temp = temp.next
if temp1:
temp.next = temp1
elif temp2:
temp.next = temp2
return dummyHead.next
if not head:
return head
length = 0
node = head
while node:
length += 1
node = node.next
dummyHead = ListNode(0, head)
subLength = 1
while subLength < length:
prev, curr = dummyHead, dummyHead.next
while curr:
# 构造 head1
head1 = curr
for i in range(1, subLength):
if curr.next:
curr = curr.next
else:
break
# 构造 head2
head2 = curr.next
curr.next = None # head1 结尾为空
curr = head2
for i in range(1, subLength):
if curr and curr.next:
curr = curr.next
else:
break
# 将curr指向下一个节点,并让head2 结尾为空
succ = None
if curr:
succ = curr.next
curr.next = None
curr = succ
# 合并两个有序链表
merged = merge(head1, head2)
# 套到上一个节点上
prev.next = merged
# 构造新的prev
while prev.next:
prev = prev.next
subLength *= 2
return dummyHead.next
23. 合并K个升序链表
- 分治合并
class Solution {
public ListNode mergeTwoLists(ListNode a, ListNode b) {
if (a == null || b == null) {
return a != null ? a : b;
}
ListNode head = new ListNode(0);
ListNode tail = head, aPtr = a, bPtr = b;
while (aPtr != null && bPtr != null) {
if (aPtr.val < bPtr.val) {
tail.next = aPtr;
aPtr = aPtr.next;
} else {
tail.next = bPtr;
bPtr = bPtr.next;
}
tail = tail.next;
}
tail.next = (aPtr != null ? aPtr : bPtr);
return head.next;
}
public ListNode merge(ListNode[] lists, int l, int r) {
if (l == r) {
return lists[l];
}
if (l > r) {
return null;
}
int mid = (l + r) >> 1;
return mergeTwoLists(
merge(lists, l, mid),
merge(lists, mid + 1, r)
);
}
public ListNode mergeKLists(ListNode[] lists) {
return merge(lists, 0, lists.length - 1);
}
}
- 堆排序
class Solution {
public ListNode mergeKLists(ListNode[] lists) {
PriorityQueue<Status> queue = new PriorityQueue<>();
for (ListNode node : lists) {
if (node != null) {
queue.offer(new Status(node.val, node));
}
}
ListNode head = new ListNode(0);
ListNode tail = head;
while (!queue.isEmpty()) {
Status f = queue.poll();
tail.next = f.ptr;
tail = tail.next;
if (f.ptr.next != null) {
queue.offer(new Status(f.ptr.next.val, f.ptr.next));
}
}
return head.next;
}
class Status implements Comparable<Status> {
int val;
ListNode ptr;
Status(int val, ListNode ptr) {
this.val = val;
this.ptr = ptr;
}
public int compareTo(Status status2) {
return this.val - status2.val;
}
}
}
86. 分隔链表
class Solution:
def partition(self, head: ListNode, x: int) -> ListNode:
if not head:
return head
head1 = ListNode(0)
p1 = head1
head2 = ListNode(0)
p2 = head2
p = head
while p:
if p.val < x:
p1.next = p
p1 = p1.next
else:
p2.next = p
p2 = p2.next
p = p.next
if head1.next is None:
return head2.next
if head2.next is None:
return head1.next
p1.next = head2.next
p2.next = None
return head1.next
基本编程思想
二分
001. labuladong框架
搜索一个元素时,搜索区间两端闭
while条件带等号,否则需要打补丁
if相等就返回,其他事情甭操心
mid必须加减一,因为区间两端闭
while结束就凉了,凄凄惨惨返-1
搜索左右区间时,搜索区间要阐明
左闭右开最常见,其余逻辑便自明
while要用小于号,这样才能不漏掉
if相等别返回,利用mid锁边界
nums = [1, 1, 3, 6, 6, 6, 7, 8, 8, 9]
def binary_search(nums, target):
'''找一个数'''
l = 0
r = len(nums) - 1
while l <= r:
mid = (l + r) // 2
# 如果是Java Cpp
# mid = l + (r - l) // 2
if nums[mid] == target:
return mid
elif nums[mid] < target:
l = mid + 1
elif nums[mid] > target:
r = mid - 1
return -1
print("binary_search", binary_search(nums, 6))
def lower_bound(nums, target):
'''找左边界'''
l = 0
r = len(nums)
while l < r:
mid = (l + r) // 2
if nums[mid] == target:
r = mid
elif nums[mid] < target:
l = mid + 1
elif nums[mid] > target:
r = mid
# 对未命中情况进行后处理
if l == len(nums):
return -1
return l if nums[l] == target else -1
print("lower_bound", lower_bound(nums, 6))
print("lower_bound", lower_bound(nums, 2))
def upper_bound(nums, target):
'''找右边界'''
l = 0
r = len(nums)
while l < r:
mid = (l + r) // 2
if nums[mid] == target:
l = mid + 1
elif nums[mid] < target:
l = mid + 1
elif nums[mid] > target:
r = mid
if l == 0:
return -1
return l - 1 if nums[l - 1] == target else -1
print("upper_bound", upper_bound(nums, 100))
print("upper_bound", upper_bound(nums, -1))
print("upper_bound", upper_bound(nums, 2))
print("upper_bound", upper_bound(nums, 6))
002. 实现lower_bound与upper_bound
- 默写labuladong算法小抄
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
def lower_bound(nums, target):
l = 0
r = len(nums)
while l < r:
mid = (l + r) // 2
if nums[mid] == target:
r = mid
elif nums[mid] < target:
l = mid + 1
elif nums[mid] > target:
r = mid
if l >= len(nums):
return -1
return l if nums[l] == target else -1
def upper_bound(nums, target):
l = 0
r = len(nums)
while l < r:
mid = (l + r) // 2
if nums[mid] == target:
l = mid + 1
elif nums[mid] < target:
l = mid + 1
elif nums[mid] > target:
r = mid
if l == 0:
return -1
return l - 1 if nums[l - 1] == target else -1
return [lower_bound(nums, target), upper_bound(nums, target)]
LeetCode官方题解将LB与UB整合到了一行代码中(cpp)
并且二分查找的具体方式也有所不同
int binarySearch(vector<int>& nums, int target, bool lower) {
int left = 0, right = (int)nums.size() - 1, ans = (int)nums.size();
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] > target || (lower && nums[mid] >= target)) {
right = mid - 1;
ans = mid;
} else {
left = mid + 1;
}
}
return ans;
}
翻译成python代码
def binary_search(nums, target, lower):
l = 0
r = len(nums) - 1
ans = len(nums)
while l <= r: # diff
mid = (l + r) // 2
# 满足左边就一定会满足右边
if (nums[mid] > target) or (lower and nums[mid] >= target):
r = mid - 1 # diff
ans = mid # diff
else:
l = mid + 1 # common
return ans
TODO: 更深入地学习labuladong算法小抄中关于二分的部分
练习题: 34. 在排序数组中查找元素的第一个和最后一个位置
300. 最长递增子序列
贪心 + 二分
class Solution:
def lengthOfLIS(self, nums: List[int]) -> int:
if not nums:
return 0
N = len(nums)
dp = []
for i, num in enumerate(nums):
if len(dp) == 0 or dp[-1] < num:
dp.append(num)
else:
# lower_bound
l = 0
r = len(dp)
while l < r:
mid = (l + r) // 2
if dp[mid] == num:
r = mid
elif dp[mid] < num:
l = mid + 1
elif dp[mid] > num:
r = mid
dp[l] = num
return len(dp)
4. 寻找两个正序数组的中位数
题解:详细通俗的思路分析, 多解法
上述题解的题解3需要再看一下,感觉写的比官方的简洁
下面的解法参考官方题解两个有序数组的第k元素
的方法,还有些不熟悉的地方。
class Solution:
def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
def getKthElement(k):
index1 = index2 = 0
while True:
# 特殊情况(写错了)
# if index1 + k > n - 1:
# return nums1[n - 1]
# elif index2 + k > m - 1:
# return nums2[m - 1]
# elif k == 1:
# return min(nums1[index1 + k], nums2[index2 + k])
# ---------------------------
# nums1 普遍偏小的情况
if index1 == n:
return nums2[index2 + k - 1]
# nums2 普遍偏小的情况
if index2 == m:
return nums1[index1 + k - 1]
# 死循环退出条件
if k == 1:
return min(nums1[index1], nums2[index2])
# 正常情况
half = k // 2
new_index1 = min(index1 + half - 1, n - 1)
new_index2 = min(index2 + half - 1, m - 1)
if nums1[new_index1] < nums2[new_index2]:
k -= new_index1 - index1 + 1
index1 = new_index1 + 1 # 忘了 + 1
else:
k -= new_index2 - index2 + 1
index2 = new_index2 + 1 # 忘了 + 1
n = len(nums1)
m = len(nums2)
total_len = (n + m)
if total_len % 2:
return getKthElement((total_len + 1) // 2)
else:
return (getKthElement(total_len // 2) + getKthElement(total_len // 2 + 1)) / 2
33. 搜索旋转排序数组
class Solution:
def search(self, nums: List[int], target: int) -> int:
if not nums:
return -1
N = len(nums)
l = 0
r = N - 1
while l <= r:
mid = (l + r) // 2
if nums[mid] == target:
return mid
# 左边有序
# “左边有序”的判断一定要<=,其他的判断可以无脑两个<=
# if nums[0] < nums[mid]:
if nums[0] <= nums[mid]:
# 目标值在左边
# if nums[0] <= target <= nums[mid]:
if nums[0] <= target < nums[mid]:
r = mid - 1
else:
l = mid + 1
# 右边有序
else:
# 目标值在右边
# if nums[mid] <= target <= nums[N - 1]:
if nums[mid] < target <= nums[N - 1]:
l = mid + 1
else:
r = mid - 1
return -1
167. 两数之和 II - 输入有序数组
- 二分
时间 O ( N log N ) O(N\log N) O(NlogN) 空间 O ( N ) O(N) O(N)
class Solution {
public int[] twoSum(int[] numbers, int target) {
for (int i = 0; i < numbers.length; ++i) {
int low = i + 1, high = numbers.length - 1;
while (low <= high) {
int mid = (high - low) / 2 + low;
if (numbers[mid] == target - numbers[i]) {
return new int[]{
i + 1, mid + 1};
} else if (numbers[mid] > target - numbers[i]) {
high = mid - 1;
} else {
low = mid + 1;
}
}
}
return new int[]{
-1, -1};
}
}
- 双指针
时间 O ( N ) O(N) O(N) 空间 O ( 1 ) O(1) O(1)
class Solution {
public int[] twoSum(int[] numbers, int target) {
int low = 0, high = numbers.length - 1;
while (low < high) {
int sum = numbers[low] + numbers[high];
if (sum == target) {
return new int[]{
low + 1, high + 1};
} else if (sum < target) {
++low;
} else {
--high;
}
}
return new int[]{
-1, -1};
}
}
- 双指针 + 二分
时间 :最好 O ( log N ) O(\log N) O(logN) ,最坏 O ( N ) O(N) O(N)
class Solution {
public int[] twoSum(int[] numbers, int target) {
int i = 0, j = numbers.length - 1;
while (i < j) {
int m = (i + j) >>> 1;
if (numbers[i] + numbers[m] > target) {
j = m - 1;
} else if (numbers[m] + numbers[j] < target) {
i = m + 1;
} else if (numbers[i] + numbers[j] > target) {
j--;
} else if (numbers[i] + numbers[j] < target) {
i++;
} else {
return new int[]{
i + 1, j + 1};
}
}
return new int[]{
0, 0};
}
}
class Solution:
def twoSum(self, numbers: List[int], target: int) -> List[int]:
i, j = 0, len(numbers) - 1
while i <= j:
m = (i + j) // 2
if numbers[i] + numbers[m] > target:
j = m - 1
elif numbers[m] + numbers[j] < target:
i = m + 1
elif numbers[i] + numbers[j] < target:
i += 1
elif numbers[i] + numbers[j] > target:
j -= 1
else:
return [i + 1, j + 1]
return [-1, -1]
分治
240. 搜索二维矩阵 II
class Solution:
def searchMatrix(self, matrix, target):
"""
:type matrix: List[List[int]]
:type target: int
:rtype: bool
"""
N = len(matrix)
if not N:
return False
M = len(matrix[0])
i = N - 1
j = 0
while i >= 0 and j < M:
if matrix[i][j] == target:
return True
if matrix[i][j] < target:
j += 1
elif matrix[i][j] > target:
i -= 1
return False
贪心
621. 任务调度器
- 模拟法
class Solution:
def leastInterval(self, tasks: List[str], n: int) -> int:
freq = collections.Counter(tasks)
rest = list(freq.values())
M = len(rest)
nextValid = [1] * M
time = 0
for _ in tasks:
time += 1
# 下一个最早可用时间
minNextValid = min(nextValid[i] for i in range(M) if rest[i] > 0)
time = max(time, minNextValid) # 写错成了min
best = -1
for i in range(M):
# 在剩余任务中,时间满足
if rest[i] > 0 and nextValid[i] <= time:
# 剩余次数最多
if best == -1 or rest[i] > rest[best]:
best = i
rest[best] -= 1
# 根据样例、需要间隔n个
nextValid[best] = time + n + 1
return time
- 构造法
class Solution:
def leastInterval(self, tasks: List[str], n: int) -> int:
freq = collections.Counter(tasks)
maxExec = max(freq.values())
maxCount = sum(1 for cnt in freq.values() if cnt == maxExec)
return max( # 没想到
(maxExec - 1) * (n + 1) + maxCount,
len(tasks) # 没想到
)
861. 翻转矩阵后的得分
class Solution {
public:
int matrixScore(vector<vector<int>> &A) {
int m = A.size(), n = A[0].size();
//m 行 n 列
int ret = m * (1 << (n - 1)); // 忘了 m * ()
// 先“翻转”行再“翻转”列。翻转行必然使第一列全为1
for (int j = 1; j < n; ++j) {
//遍历第j列
int nOnes = 0;
for (int i = 0; i < m; ++i) {
//第i行
if (A[i][0] == 1) {
//如果某一行第一列是0,该行会翻转
nOnes += A[i][j]; // 手抖写成 A[i][0]
} else {
nOnes += (1 - A[i][j]);
}
}
int k = max(nOnes, m - nOnes);
ret += k * (1 << (n - 1 - j));
}
return ret;
}
};
860. 柠檬水找零
先把大面额的钱找出去
class Solution:
def lemonadeChange(self, bills: List[int]) -> bool:
counter = dict(zip([5, 10, 20], [0] * 3))
for bill in bills:
if bill == 5:
counter[5] += 1
elif bill == 10:
if counter[5] < 1:
return False
counter[5] -= 1
counter[10] += 1
else: # 20
if counter[10] >=1 and counter[5] >= 1:
counter[5] -= 1
counter[10] -= 1
elif counter[5] >= 3:
counter[5] -= 3
else:
return False
return True
649. Dota2 参议院
自己瞎写, 超时
class Solution:
def predictPartyVictory(self, senate: str) -> str:
ix = 0
senate = list(senate)
while True:
if len(senate) == 1:
break
for i in itertools.chain(
range(ix + 1, len(senate)),
range(ix),
):
if senate[i] != senate[ix]:
del senate[i]
break
ix += 1
if ix >= len(senate):
ix = 0
return "Dire" if senate[0] == "D" else "Radiant"
官方题解
class Solution:
def predictPartyVictory(self, senate: str) -> str:
n = len(senate)
r_list = collections.deque()
d_list = collections.deque()
for i, ch in enumerate(senate):
if ch == "R":
r_list.append(i)
else:
d_list.append(i)
while r_list and d_list:
if r_list[0] < d_list[0]:
r_list.append(r_list[0] + n)
else:
d_list.append(d_list[0] + n)
r_list.popleft()
d_list.popleft()
return "Radiant" if r_list else "Dire"
TODO:
自己写一遍
376. 摆动序列
class Solution:
def wiggleMaxLength(self, nums: List[int]) -> int:
N = len(nums)
if N < 2:
# 考虑长度为 1 和 0 的情况
return N
pre_delta = nums[1] - nums[0]
ans = 1 if pre_delta == 0 else 2
for i in range(2, N):
delta = nums[i] - nums[i - 1]
if (delta > 0 and pre_delta <= 0) or (delta < 0 and pre_delta >= 0):
ans += 1
pre_delta = delta
return ans
TODO:
自己写一遍
看DP题解
135. 分发糖果
class Solution:
def candy(self, ratings: List[int]) -> int:
L = len(ratings)
left = [1] * L
right = [1] * L
for i in range(1, L):
if ratings[i] > ratings[i - 1]:
left[i] = left[i - 1] + 1
cnt = left[L - 1]
for i in reversed(range(0, L - 1)):
if ratings[i] > ratings[i + 1]:
right[i] = right[i + 1] + 1
cnt += max(left[i], right[i])
return cnt
455. 分发饼干
排序+贪心
class Solution:
def findContentChildren(self, g: List[int], s: List[int]) -> int:
g.sort()
s.sort()
s_N = len(s)
s_start = 0
cnt = 0
for child_demand in g:
while s_start < s_N:
biscuit = s[s_start]
s_start += 1
if biscuit >= child_demand:
cnt += 1
break
if s_start >= s_N:
break
return cnt
605. 种花问题
class Solution:
def canPlaceFlowers(self, flowerbed: List[int], n: int) -> bool:
N = len(flowerbed)
def available(i):
if flowerbed[i] == 0 and \
(i == 0 or flowerbed[i - 1] == 0) and \
(i == N - 1 or flowerbed[i + 1] == 0):
return True
return False
cnt = 0
for i in range(N):
if available(i):
cnt += 1
flowerbed[i] = 1
return n <= cnt
官方题解看不懂,这个题解思路和我一样,但是会提前return,比我做得好。
class Solution {
public boolean canPlaceFlowers(int[] flowerbed, int n) {
for(int i=0; i<flowerbed.length; i++) {
if(flowerbed[i] == 0 && (i == 0 || flowerbed[i-1] == 0) && (i == flowerbed.length-1 || flowerbed[i+1] == 0)) {
n--;
if(n <= 0) return true;
flowerbed[i] = 1;
}
}
return n <= 0;
}
}
搜索法
回溯法
51. N 皇后
51. N 皇后
baseline
from typing import List
class Solution:
def dfs(self, i):
if i >= self.n:
self.res.append(["".join(row) for row in self.board])
return
for j in range(self.n):
if self.isValid(i, j):
self.board[i][j] = "Q"
self.dfs(i + 1)
self.board[i][j] = "."
def isValid(self, x, y):
for i in range(x):
if self.board[i][y] == "Q":
return False
for j in range(y):
if self.board[x][j] == "Q":
return False
i = x - 1
j = y -