1 介绍
本博客用来记录代码随想录leetcode200题之额外题目相关题目。
2 训练
解题思路:二分查找。
C++代码如下,
class Solution {
public:
vector<int> smallerNumbersThanCurrent(vector<int>& a) {
vector<int> b = a;
sort(b.begin(), b.end());
vector<int> res;
for (auto x : a) {
auto iter = lower_bound(b.begin(), b.end(), x);
int i = distance(b.begin(), iter);
res.emplace_back(i);
}
return res;
}
};
python3代码如下,
class Solution:
def smallerNumbersThanCurrent(self, a: List[int]) -> List[int]:
b = copy.deepcopy(a)
b.sort()
res = []
for x in a:
i = bisect.bisect_left(b, x)
res.append(i)
return res
题目2:941. 有效的山脉数组
解题思路:模拟。
C++代码如下,
class Solution {
public:
bool validMountainArray(vector<int>& a) {
int n = a.size();
if (n < 3) return false;
if (!(a[0] < a[1])) return false;
if (!(a[n-2] > a[n-1])) return false;
int i = 0;
while (i+1 < n && a[i] < a[i+1]) i += 1;
int j = i;
while (j+1 < n && a[j] > a[j+1]) j += 1;
if (j != n-1) return false;
return true;
}
};
python3代码如下,
class Solution:
def validMountainArray(self, a: List[int]) -> bool:
n = len(a)
if n < 3:
return False
if not (a[0] < a[1]):
return False
if not (a[-2] > a[-1]):
return False
i = 0
while i + 1 < n and a[i] < a[i+1]:
i += 1
j = i
while j + 1 < n and a[j] > a[j+1]:
j += 1
if j != n-1:
return False
return True
题目3:1207. 独一无二的出现次数
解题思路:模拟。
C++代码如下,
class Solution {
public:
bool uniqueOccurrences(vector<int>& a) {
unordered_map<int, int> cnt1;
for (auto x : a) cnt1[x]++;
unordered_map<int, int> cnt2;
for (auto [k, v] : cnt1) {
cnt2[v]++;
if (cnt2[v] > 1) return false;
}
return true;
}
};
python3代码如下,
class Solution:
def uniqueOccurrences(self, a: List[int]) -> bool:
cnt = collections.Counter(a)
res = collections.Counter(cnt.values())
for k in res:
if res[k] > 1:
return False
return True
题目4:283. 移动零
解题思路:双指针。
C++代码如下,
class Solution {
public:
void moveZeroes(vector<int>& a) {
int n = a.size();
int i = 0;
int j = 0;
while (j < n) {
if (a[j] != 0) {
swap(a[i], a[j]);
i += 1;
}
j += 1;
}
return;
}
};
python3代码如下,
class Solution:
def moveZeroes(self, a: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n = len(a)
i = 0
j = 0
while j < n:
if a[j] == 0:
pass
else:
a[i], a[j] = a[j], a[i]
i += 1
j += 1
return
题目5:189. 轮转数组
解题思路:分三步走。第1步,先翻转整个列表。第2步,翻转列表的[0,k)
部分。第3步,翻转列表的[k,n)
部分。
C++代码如下,
class Solution {
public:
void rotate(vector<int>& a, int k) {
int n = a.size();
k %= n;
reverse(a.begin(), a.end());
reverse(a.begin(), a.begin()+k);
reverse(a.begin()+k, a.end());
return;
}
};
python3代码如下,
class Solution:
def reverse(self, a: list, i: int, j: int) -> None:
while i < j:
a[i], a[j] = a[j], a[i]
i += 1
j -= 1
return
def rotate(self, a: List[int], k: int) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n = len(a)
k %= n
self.reverse(a, 0, n-1)
self.reverse(a, 0, k-1)
self.reverse(a, k, n-1)
return
题目6:724. 寻找数组的中心下标
解题思路:模拟。
C++代码如下,
class Solution {
public:
int pivotIndex(vector<int>& a) {
a.insert(a.begin(), 0);
int n = a.size();
vector<int> s(n, 0);
for (int i = 1; i < n; ++i) {
s[i] = s[i-1] + a[i];
}
for (int i = 1; i < n; ++i) {
if (s[i-1] == s[n-1] - s[i]) {
return i-1;
}
}
return -1;
}
};
python3代码如下,
class Solution:
def pivotIndex(self, a: List[int]) -> int:
a.insert(0, 0)
n = len(a)
s = [0] * n
for i in range(1,n):
s[i] = s[i-1] + a[i]
for i in range(1,n):
if s[i-1] == s[n-1] - s[i]:
return i-1
return -1
解题思路:二分查找。
C++代码如下,
class Solution {
public:
vector<int> searchRange(vector<int>& a, int target) {
int n = a.size();
auto iter = lower_bound(a.begin(), a.end(), target);
if (iter == a.end() || *iter != target) {
return {-1,-1};
}
int i = distance(a.begin(), iter);
iter = upper_bound(a.begin(), a.end(), target);
int j = distance(a.begin(), iter);
j -= 1;
return {i,j};
}
};
python3代码如下,
class Solution:
def searchRange(self, nums: List[int], target: int) -> List[int]:
i = bisect.bisect_left(nums, target)
if i >= len(nums) or (i < len(nums) and nums[i] != target): #特判
return [-1,-1]
j = bisect.bisect_right(nums, target)
j -= 1
return [i,j]
题目8:922. 按奇偶排序数组 II
解题思路:双指针算法。
C++代码如下,
class Solution {
public:
vector<int> sortArrayByParityII(vector<int>& a) {
int n = a.size();
int i = 0, j = 1;
while (i < n && j < n) {
while (i < n && a[i] % 2 == 0) {
i += 2;
}
while (j < n && a[j] % 2 == 1) {
j += 2;
}
if (i < n && j < n) {
swap(a[i], a[j]);
}
}
return a;
}
};
python3代码如下,
class Solution:
def sortArrayByParityII(self, a: List[int]) -> List[int]:
n = len(a)
i = 0
j = 1
while i < n and j < n:
while i < n and a[i] % 2 == 0:
i += 2
while j < n and a[j] % 2 == 1:
j += 2
if i < n and j < n:
a[i], a[j] = a[j], a[i]
return a
题目9:35. 搜索插入位置
解题思路:二分查找。
C++代码如下,
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
auto iter = lower_bound(nums.begin(), nums.end(), target);
return distance(nums.begin(), iter);
}
};
python3代码如下,
class Solution:
def searchInsert(self, nums: List[int], target: int) -> int:
return bisect.bisect_left(nums, target)
题目10:24. 两两交换链表中的节点
解题思路:对于node->a->b->…,三步操作。第1步,a.next = b.next。第2步,b.next = a。第3步,node.next = b。
C++代码如下,
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* swapPairs(ListNode* head) {
ListNode *dummy = new ListNode(0, head);
ListNode *node = dummy;
while (node->next != nullptr && node->next->next != nullptr) {
ListNode *a = node->next;
ListNode *b = node->next->next;
a->next = b->next;
b->next = a;
node->next = b;
node = node->next->next;
}
return dummy->next;
}
};
python3代码如下,
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def swapPairs(self, head: Optional[ListNode]) -> Optional[ListNode]:
dummy = ListNode(0,head)
node = dummy
while node.next is not None and node.next.next is not None:
a = node.next
b = node.next.next
a.next = b.next
b.next = a
node.next = b
node = node.next.next
return dummy.next
题目11:234. 回文链表
解题思路:将原链表拆分成2个链表(先切割后翻转链表)。比较这2个链表中的元素值。
C++代码如下,
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverse(ListNode* head) {
ListNode *a = head;
ListNode *prev = nullptr;
while (a != nullptr) {
ListNode *b = a->next;
a->next = prev;
prev = a;
a = b;
}
return prev;
}
bool isPalindrome(ListNode* head) {
ListNode *slow = head;
ListNode *fast = head;
while (slow->next != nullptr && fast->next != nullptr && fast->next->next != nullptr) {
slow = slow->next;
fast = fast->next->next;
}
//切割
ListNode *a = head;
ListNode *b = slow->next;
slow->next = nullptr;
//翻转
b = reverse(b);
while (a != nullptr && b != nullptr) {
if (a->val != b->val) {
return false;
}
a = a->next;
b = b->next;
}
return true;
}
};
python3代码如下,
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverse(self, head: Optional[ListNode]) -> Optional[ListNode]:
a = head
prev = None
while a is not None:
b = a.next
a.next = prev
prev = a
a = b
return prev
def isPalindrome(self, head: Optional[ListNode]) -> bool:
slow = head
fast = head
while slow.next is not None and fast.next is not None and fast.next.next is not None:
slow = slow.next
fast = fast.next.next
a = head
b = slow.next
slow.next = None
#翻转链表b
b = self.reverse(b)
while a is not None and b is not None:
if a.val != b.val:
return False
a = a.next
b = b.next
return True
题目12:143. 重排链表
解题思路:先通过快慢指针分割原链表为a
和b
。然后翻转链表b
。最后合并两个链表即可。
C++代码如下,
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode() : val(0), next(nullptr) {}
* ListNode(int x) : val(x), next(nullptr) {}
* ListNode(int x, ListNode *next) : val(x), next(next) {}
* };
*/
class Solution {
public:
ListNode* reverse(ListNode *head) {
ListNode *prev = nullptr;
ListNode *curr = head;
while (curr != nullptr) {
ListNode *nxt = curr->next;
curr->next = prev;
prev = curr;
curr = nxt;
}
return prev;
}
void reorderList(ListNode* head) {
ListNode *slow = head;
ListNode *fast = head;
while (slow->next != nullptr && fast->next != nullptr && fast->next->next != nullptr) {
slow = slow->next;
fast = fast->next->next;
}
ListNode *a = head;
ListNode *b = slow->next;
slow->next = nullptr;
b = reverse(b);
ListNode *res = a;
ListNode *prev = nullptr;
while (a != nullptr && b != nullptr) {
ListNode *na = a->next;
ListNode *nb = b->next;
a->next = b;
if (prev != nullptr) {
prev->next = a;
}
prev = b;
a = na;
b = nb;
}
if (prev != nullptr && a != nullptr) {
prev->next = a;
}
head = res;
return;
}
};
python3代码如下,
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverse(self, head: Optional[ListNode]) -> Optional[ListNode]:
prev = None
a = head
while a is not None:
b = a.next
a.next = prev
prev = a
a = b
return prev
def reorderList(self, head: Optional[ListNode]) -> None:
"""
Do not return anything, modify head in-place instead.
"""
fast = head
slow = head
while slow.next is not None and fast.next is not None and fast.next.next is not None:
slow = slow.next
fast = fast.next.next
#先分隔
a = head
b = slow.next
#后翻转
b = self.reverse(b)
slow.next = None
res = a
prev = None
while a is not None and b is not None:
na = a.next
nb = b.next
if prev is not None:
prev.next = a
a.next = b
prev = b
a = na
b = nb
if a is not None and prev is not None:
prev.next = a
return res
题目13:141. 环形链表
解题思路:快慢指针法,慢指针走一步,快指针走两步。如果存在环,则它们会相遇。
C++代码如下,
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool hasCycle(ListNode *head) {
if (head == nullptr) { //特判
return false;
}
ListNode *slow = head;
ListNode *fast = head;
while (slow->next != nullptr && fast->next != nullptr && fast->next->next != nullptr) {
slow = slow->next;
fast = fast->next->next;
if (slow == fast) {
return true;
}
}
return false;
}
};
python3代码如下,
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def hasCycle(self, head: Optional[ListNode]) -> bool:
if head is None: #特判
return False
slow = head
fast = head
while slow.next is not None and fast.next is not None and fast.next.next is not None:
slow = slow.next
fast = fast.next.next
if slow == fast:
return True
return False
题目14:面试题 02.07. 链表相交
解题思路:a走到末尾更新为headB,而b走到末尾则更新为headA,注意只能更新一次。
C++代码如下,
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
if (headA == nullptr || headB == nullptr) {
return nullptr;
}
ListNode *a = headA;
ListNode *b = headB;
vector<int> cnt = {0,0};
while (!(a == nullptr and b == nullptr)) {
if (a == b) return a;
if (a->next == nullptr) {
a = headB;
cnt[0] += 1;
} else {
a = a->next;
}
if (b->next == nullptr) {
b = headA;
cnt[1] += 1;
} else {
b = b->next;
}
if (cnt[0] >= 2 || cnt[1] >= 2) break;
}
return nullptr;
}
};
python3代码如下,
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> ListNode:
if headA is None or headB is None: #特判
return None
a = headA
b = headB
cnt = [0,0]
while not (a is None and b is None):
if a == b:
return a
if a.next is None:
cnt[0] += 1
a = headB
else:
a = a.next
if b.next is None:
cnt[1] += 1
b = headA
else:
b = b.next
if cnt[0] >= 2 or cnt[1] >= 2:
break
return None
题目15:205. 同构字符串
解题思路:哈希表。
C++代码如下,
class Solution {
public:
bool check(string s, string t) {
unordered_map<char,char> mp;
if (s.size() != t.size()) return false;
int n = s.size();
for (int i = 0; i < n; ++i) {
if (mp.count(s[i]) == 0) {
mp[s[i]] = t[i];
} else {
if (mp[s[i]] != t[i]) return false;
}
}
return true;
}
bool isIsomorphic(string s, string t) {
return check(s,t) && check(t,s);
}
};
python3代码如下,
class Solution:
def check(self, s: str, t: str) -> bool:
mp = collections.defaultdict(str)
if len(s) != len(t):
return False
n = len(s)
for i in range(n):
if s[i] in mp:
if mp[s[i]] != t[i]:
return False
else:
mp[s[i]] = t[i]
return True
def isIsomorphic(self, s: str, t: str) -> bool:
return self.check(s, t) and self.check(t, s)
题目16:1002. 查找共用字符
解题思路:模拟即可。
C++代码如下,
class Solution {
public:
vector<string> commonChars(vector<string>& words) {
unordered_map<int, unordered_map<int,int>> map_idx_cnt;
for (int i = 0; i < words.size(); ++i) {
string word = words[i];
for (char c : word) {
map_idx_cnt[i][c] += 1;
}
}
vector<string> res;
for (int i = 0; i < 26; ++i) {
char c = 'a' + i;
string s(1, c);
int minv = 110;
for (auto [_, cnt] : map_idx_cnt) {
minv = min(minv, cnt[c]);
}
for (int j = 0; j < minv; ++j) {
res.emplace_back(s);
}
}
return res;
}
};
python3代码如下,
class Solution:
def commonChars(self, words: List[str]) -> List[str]:
map_idx_cnt = collections.defaultdict(map)
for i,word in enumerate(words):
cnt = collections.defaultdict(int)
for c in word:
cnt[c] += 1
map_idx_cnt[i] = cnt
res = []
for i in range(26):
c = chr(i+ord('a'))
minv = 110
for j in map_idx_cnt:
cnt = map_idx_cnt[j]
minv = min(minv, cnt[c])
for _ in range(minv):
res.append(c)
return res
题目17:925. 长按键入
解题思路:双指针算法。
C++代码如下,
class Solution {
public:
bool isLongPressedName(string name, string typed) {
int n = name.size();
int m = typed.size();
if (n == 0 && m == 0) return true;
else if (n == 0 || m == 0) return false;
int i = 0;
int j = 0;
while (i < n && j < m) {
char c = name[i];
int cnt1 = 0;
while (name[i] == c) {
i += 1;
cnt1 += 1;
}
int cnt2 = 0;
while (typed[j] == c) {
j += 1;
cnt2 += 1;
}
if (cnt1 > cnt2) return false;
}
if (i == n && j == m) return true;
else return false;
}
};
python3代码如下,
class Solution:
def isLongPressedName(self, name: str, typed: str) -> bool:
if len(name) == 0 and len(typed) == 0:
return True
elif len(name) == 0:
return False
elif len(typed) == 0:
return False
i = 0
j = 0
while i < len(name) and j < len(typed):
c = name[i]
cnt1 = 0
while i < len(name) and name[i] == c:
i += 1
cnt1 += 1
cnt2 = 0
while j < len(typed) and typed[j] == c:
j += 1
cnt2 += 1
if cnt1 > cnt2:
return False
if i == len(name) and j == len(typed):
return True
else:
return False
题目18:844. 比较含退格的字符串
解题思路:模拟。
C++代码如下,
class Solution {
public:
bool backspaceCompare(string s, string t) {
string ns = "";
string nt = "";
for (char c : s) {
if (c == '#') {
if (ns.size() > 0) {
ns = ns.substr(0,ns.size()-1);
}
} else {
ns += c;
}
}
for (char c : t) {
if (c == '#') {
if (nt.size() > 0) {
nt = nt.substr(0,nt.size()-1);
}
} else {
nt += c;
}
}
return ns == nt;
}
};
python3代码如下,
class Solution:
def backspaceCompare(self, s: str, t: str) -> bool:
ns = ""
nt = ""
for c in s:
if c == "#":
if len(ns) > 0:
ns = ns[0:-1]
else:
ns += c
for c in t:
if c == "#":
if len(nt) > 0:
nt = nt[0:-1]
else:
nt += c
return ns == nt
题目19:129. 求根节点到叶节点数字之和
解题思路:回溯。
C++代码如下,
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int res = 0;
int cur = 0;
void dfs(TreeNode* node) {
if (node->left == nullptr && node->right == nullptr) {
res += cur * 10 + node->val;
return;
}
cur = cur * 10 + node->val;
if (node->left != nullptr) {
dfs(node->left);
}
if (node->right != nullptr) {
dfs(node->right);
}
cur /= 10;
return;
}
int sumNumbers(TreeNode* root) {
dfs(root);
return res;
}
};
python3代码如下,
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def sumNumbers(self, root: Optional[TreeNode]) -> int:
res = 0
cur = 0
def dfs(node: Optional[TreeNode]) -> None:
nonlocal res,cur
if node.left is None and node.right is None:
res += cur * 10 + node.val
return
#处理代码
cur = cur * 10 + node.val
if node.left is not None:
dfs(node.left)
if node.right is not None:
dfs(node.right)
cur //= 10
return
dfs(root)
return res
题目20:1382. 将二叉搜索树变平衡
解题思路:根据有序数组构建二叉搜索树。
C++代码如下,
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> nums;
void dfs(TreeNode* node) {
if (node == nullptr) return;
dfs(node->left);
nums.emplace_back(node->val);
dfs(node->right);
return;
}
TreeNode* getTreeFromVector(int left, int right) {
if (left > right) return nullptr;
int mid = (left + right) / 2;
TreeNode* root = new TreeNode(nums[mid]);
root->left = getTreeFromVector(left,mid-1);
root->right = getTreeFromVector(mid+1,right);
return root;
}
TreeNode* balanceBST(TreeNode* root) {
this->nums.clear();
dfs(root);
return getTreeFromVector(0,nums.size()-1);
}
};
python3代码如下,
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def balanceBST(self, root: TreeNode) -> TreeNode:
nums = []
def dfs(node: TreeNode) -> None:
nonlocal nums
if node is None:
return
dfs(node.left)
nums.append(node.val)
dfs(node.right)
return
dfs(root)
def getTreefromList(left: int, right) -> TreeNode:
nonlocal nums
if left > right:
return
mid = (left + right) // 2
root = TreeNode(nums[mid])
root.left = getTreefromList(left,mid-1)
root.right = getTreefromList(mid+1,right)
return root
return getTreefromList(0,len(nums)-1)
题目21:100. 相同的树
解题思路:递归。
C++代码如下,
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
bool isSameTree(TreeNode* p, TreeNode* q) {
if (p == nullptr && q == nullptr) return true;
else if (p == nullptr || q == nullptr) return false;
if (p->val != q->val) return false;
return isSameTree(p->left,q->left) && isSameTree(p->right,q->right);
}
};
python3代码如下,
# Definition for a binary tree node.
# class TreeNode:
# def __init__(self, val=0, left=None, right=None):
# self.val = val
# self.left = left
# self.right = right
class Solution:
def isSameTree(self, p: Optional[TreeNode], q: Optional[TreeNode]) -> bool:
if p is None and q is None:
return True
elif p is None or q is None:
return False
if p.val != q.val:
return False
return self.isSameTree(p.left,q.left) and self.isSameTree(p.right,q.right)
解题思路:二叉树的层序遍历。
C++代码如下,
/*
// Definition for a Node.
class Node {
public:
int val;
Node* left;
Node* right;
Node* next;
Node() : val(0), left(NULL), right(NULL), next(NULL) {}
Node(int _val) : val(_val), left(NULL), right(NULL), next(NULL) {}
Node(int _val, Node* _left, Node* _right, Node* _next)
: val(_val), left(_left), right(_right), next(_next) {}
};
*/
class Solution {
public:
Node* connect(Node* root) {
if (root == nullptr) return root;
queue<Node*> q;
q.push(root);
while (!q.empty()) {
int n = q.size();
vector<Node*> nodes;
while (n--) {
auto t = q.front();
q.pop();
nodes.emplace_back(t);
if (t->left) q.push(t->left);
if (t->right) q.push(t->right);
}
for (int i = 0; i < nodes.size()-1; ++i) {
nodes[i]->next = nodes[i+1];
}
nodes.back()->next = nullptr;
}
return root;
}
};
python3代码如下,
"""
# Definition for a Node.
class Node:
def __init__(self, val: int = 0, left: 'Node' = None, right: 'Node' = None, next: 'Node' = None):
self.val = val
self.left = left
self.right = right
self.next = next
"""
class Solution:
def connect(self, root: 'Optional[Node]') -> 'Optional[Node]':
if root is None: #特判root为None的情况
return None
q = collections.deque([])
q.append(root)
while len(q) > 0:
n = len(q)
nodes = []
while n > 0:
t = q.popleft()
nodes.append(t)
if t.left is not None:
q.append(t.left)
if t.right is not None:
q.append(t.right)
n -= 1
for i in range(len(nodes)-1):
nodes[i].next = nodes[i+1]
nodes[-1].next = None
return root
题目23:52. N 皇后 II
解题思路:回溯。
C++代码如下,
class Solution {
public:
vector<int> rows, cols, dg, undg;
int res = 0;
int n;
void dfs(int i) {
if (i == n) {
res += 1;
return;
}
for (int j = 0; j < n; ++j) {
if (cols[j] == 0 && dg[i+j] == 0 && undg[i-j+n] == 0) {
//g[i][j] = 1;
rows[i] = 1;
cols[j] = dg[i+j] = undg[i-j+n] = 1;
dfs(i+1);
//g[i][j] = 0;
rows[i] = 0;
cols[j] = dg[i+j] = undg[i-j+n] = 0;
}
}
return;
}
int totalNQueens(int n) {
this->n = n;
rows.resize(n, 0);
cols.resize(n, 0);
dg.resize(2*n, 0);
undg.resize(2*n, 0);
dfs(0);
return res;
}
};
python3代码如下,
class Solution:
def totalNQueens(self, n: int) -> int:
rows = [0] * n
cols = [0] * n
dg = [0] * (2 * n)
undg = [0] * (2 * n)
res = 0
g = [[0] * n for _ in range(n)]
def dfs(i: int) -> None:
nonlocal res
if i == n:
res += 1
return
for j in range(n):
if cols[j] == 0 and dg[i+j] == 0 and undg[i-j+n] == 0:
g[i][j] = 1
rows[i] = 1
cols[j] = dg[i+j] = undg[i-j+n] = 1
dfs(i+1)
g[i][j] = 0
rows[i] = 0
cols[j] = dg[i+j] = undg[i-j+n] = 0
return
dfs(0)
return res
题目24:649. Dota2 参议院
解题思路:理解题意,禁止发言是永久性的。模拟。
C++代码如下,
class Solution {
public:
string predictPartyVictory(string senate) {
int n = senate.size();
while (true) {
int cnt1 = 0; //R
int cnt2 = 0; //D
for (int i = 0; i < n; ++i) {
if (senate[i] == 'R') {
if (cnt2 > 0) {
senate[i] = '#';
cnt2 -= 1;
} else {
cnt1 += 1;
}
} else if (senate[i] == 'D') {
if (cnt1 > 0) {
senate[i] = '#';
cnt1 -= 1;
} else {
cnt2 += 1;
}
}
}
if (cnt1 > 0) {
for (int i = 0; i < n; ++i) {
if (senate[i] == 'D') {
senate[i] = '#';
cnt1 -= 1;
if (cnt1 == 0) break;
}
}
}
if (cnt2 > 0) {
for (int i = 0; i < n; ++i) {
if (senate[i] == 'R') {
senate[i] = '#';
cnt2 -= 1;
if (cnt2 == 0) break;
}
}
}
if (count(senate.begin(), senate.end(), 'R') == 0 || count(senate.begin(), senate.end(), 'D') == 0) break;
}
string res = "";
if (count(senate.begin(), senate.end(), 'R')) res = "Radiant";
else res = "Dire";
return res;
}
};
python3代码如下,
class Solution:
def predictPartyVictory(self, senate: str) -> str:
senate = list(senate)
n = len(senate)
while True:
cnt1 = 0 #"R"的数目
cnt2 = 0 #"D"的数目
for i in range(n):
if senate[i] == 'R':
if cnt2 > 0:
senate[i] = '#'
cnt2 -= 1
else:
cnt1 += 1
elif senate[i] == "D":
#senate[i] == "D"
if cnt1 > 0:
senate[i] = "#"
cnt1 -= 1
else:
cnt2 += 1
if cnt1 > 0:
for i in range(n):
if senate[i] == "D":
senate[i] = "#"
cnt1 -= 1
if cnt1 == 0:
break
if cnt2 > 0:
for i in range(n):
if senate[i] == "R":
senate[i] = "#"
cnt2 -= 1
if cnt2 == 0:
break
if senate.count('R') == 0 or senate.count('D') == 0:
break
res = ""
if senate.count("R") == 0:
res = "Dire"
else:
res = "Radiant"
return res
题目25:1221. 分割平衡字符串
解题思路:贪心。
C++代码如下,
class Solution {
public:
int balancedStringSplit(string s) {
int cnt1 = 0; //R的数量
int cnt2 = 0; //L的数量
int res = 0;
for (char c : s) {
if (c == 'R') {
cnt1 += 1;
} else {
cnt2 += 1;
}
if (cnt1 == cnt2 && cnt1 != 0) {
res += 1;
cnt1 = 0;
cnt2 = 0;
}
}
return res;
}
};
python3代码如下,
class Solution:
def balancedStringSplit(self, s: str) -> int:
cnt1 = 0 #R的数量
cnt2 = 0 #L的数量
res = 0
for c in s:
if c == "R":
cnt1 += 1
else:
cnt2 += 1
if cnt1 == cnt2 and cnt1 != 0:
res += 1
cnt1 = 0
cnt2 = 0
return res
题目26:5. 最长回文子串
解题思路:动态规划。注意读题,连续子数组。
(1)状态定义d[i][j]
:s[i:j+1]
是否为回文串。
(2)状态初始化,d[i][i] = True
,其余为False
。
(3)状态转移,
if s[left] == s[right]:
if left + 1 == right:
dp[left][right] = True
else:
dp[left][right] = dp[left+1][right-1]
(4)由状态转移可知,left
从大到小遍历,而right
从小到大遍历。
(5)答案返回最长回文串。
C++代码如下,
class Solution {
public:
string longestPalindrome(string s) {
int n = s.size();
string res(1,s[0]);
vector<vector<int>> dp(n, vector<int>(n, false));
for (int i = 0; i < n; ++i) dp[i][i] = true;
for (int i = n-1; i >= 0; --i) {
for (int j = i+1; j < n; ++j) {
if (s[i] == s[j]) {
if (i + 1 == j) {
dp[i][j] = true;
} else {
dp[i][j] = dp[i+1][j-1];
}
if (dp[i][j] == true && res.size() < j - i + 1) {
res = s.substr(i,j-i+1);
}
}
}
}
return res;
}
};
python3代码如下,
class Solution:
def longestPalindrome(self, s: str) -> str:
n = len(s)
res = s[0]
dp = [[False] * n for _ in range(n)]
for i in range(n):
dp[i][i] = True
for left in range(n-1,-1,-1):
for right in range(left+1,n):
if s[left] == s[right]:
if left + 1 == right:
dp[left][right] = True
else:
dp[left][right] = dp[left+1][right-1]
if dp[left][right] == True and len(res) < right - left + 1:
res = s[left:right+1]
return res
题目27:132. 分割回文串 II
解题思路:根据题目26,可以在
O
(
n
2
)
O(n^2)
O(n2)时间复杂度下预处理出isPalindromic[i][j]
数组,判断s[i,j+1]
是否为回文串。
(1)状态定义dp[i]
:s[0:i+1]
的最小分割次数。
(2)状态初始化:
dp = [i for i in range(n)]
(3)状态转移:
for j in range(0,i):
if isPalindromic[j+1][i]:
dp[i] = min(dp[i], dp[j] + 1)
(4)答案返回dp[n-1]
。
C++代码如下,
class Solution {
public:
int minCut(string s) {
int n = s.size();
vector<vector<bool>> isPalindromic(n, vector<bool>(n, false));
for (int i = 0; i < n; ++i) isPalindromic[i][i] = true;
for (int i = n-1; i >= 0; --i) {
for (int j = i+1; j < n; ++j) {
if (s[i] == s[j]) {
if (i + 1 == j) isPalindromic[i][j] = true;
else isPalindromic[i][j] = isPalindromic[i+1][j-1];
}
}
}
vector<int> dp(n, 0);
for (int i = 0; i < n; ++i) dp[i] = i;
for (int i = 0; i < n; ++i) {
if (isPalindromic[0][i]) {
dp[i] = 0;
continue;
}
for (int j = 0; j < i; ++j) {
if (isPalindromic[j+1][i]) {
dp[i] = min(dp[i], dp[j] + 1);
}
}
}
return dp[n-1];
}
};
python3代码如下,
class Solution:
def minCut(self, s: str) -> int:
n = len(s)
isPalindromic = [[False] * n for _ in range(n)]
for i in range(n):
isPalindromic[i][i] = True
for left in range(n-1,-1,-1):
for right in range(left+1,n):
if s[left] == s[right]:
if left + 1 == right:
isPalindromic[left][right] = True
else:
isPalindromic[left][right] = isPalindromic[left+1][right-1]
dp = [0] * n
for i in range(n):
dp[i] = i
for i in range(1,n):
if isPalindromic[0][i]:
dp[i] = 0
continue
for j in range(0,i):
if isPalindromic[j+1][i]:
dp[i] = min(dp[i], dp[j] + 1)
return dp[n-1]
题目28:673. 最长递增子序列的个数
解题思路:动态规划,每次保存dp
对应的cnt
。
C++代码如下,
class Solution {
public:
int findNumberOfLIS(vector<int>& nums) {
int n = nums.size();
vector<int> dp(n, 1);
vector<int> cnt(n, 1);
for (int i = 0; i < n; ++i) {
for (int j = 0; j < i; ++j) {
if (nums[j] < nums[i]) {
if (dp[i] < dp[j] + 1) {
dp[i] = dp[j] + 1;
cnt[i] = cnt[j];
} else if (dp[i] == dp[j] + 1) {
cnt[i] += cnt[j];
}
}
}
}
int maxv = dp[0];
for (int i = 1; i < n; ++i) {
maxv = max(maxv, dp[i]);
}
int res = 0;
for (int i = 0; i < n; ++i) {
if (dp[i] == maxv) res += cnt[i];
}
return res;
}
};
python3代码如下,
class Solution:
def findNumberOfLIS(self, nums: List[int]) -> int:
n = len(nums)
dp = [1] * n
cnt = [1] * n
for i in range(n):
for j in range(i):
if nums[j] < nums[i]:
if dp[i] < dp[j] + 1:
dp[i] = dp[j] + 1
cnt[i] = cnt[j]
elif dp[i] == dp[j] + 1:
cnt[i] += cnt[j]
res = 0
maxv = max(dp)
for i in range(n):
if dp[i] == maxv:
res += cnt[i]
return res
题目29:841. 钥匙和房间
解题思路:bfs。
C++代码如下,
class Solution {
public:
bool canVisitAllRooms(vector<vector<int>>& rooms) {
int n = rooms.size();
unordered_set<int> target;
for (int i = 0; i < n; ++i) target.insert(i);
unordered_set<int> visited;
queue<int> q;
q.push(0);
visited.insert(0);
while (!q.empty()) {
int a = q.front();
q.pop();
for (int b : rooms[a]) {
if (visited.count(b) == 0) {
visited.insert(b);
q.push(b);
}
}
}
return target == visited;
}
};
python3代码如下,
class Solution:
def canVisitAllRooms(self, rooms: List[List[int]]) -> bool:
n = len(rooms)
target = set([i for i in range(n)])
q = collections.deque([0])
visited = set()
visited.add(0)
while len(q) > 0:
a = q.popleft()
for b in rooms[a]:
if b not in visited:
q.append(b)
visited.add(b)
return visited == target
题目30:127. 单词接龙
解题思路:考虑word
的最大长度为10,那么用26个字符依次替换每一个位置,然后判断生成的单词b
在不在原先的wordList
中,即可以判断a
可以走到哪些b
。同时也不会超出时间限制。
C++代码如下,
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
set<string> words;
words.insert(beginWord);
for (auto word : wordList) words.insert(word);
int res = 0;
queue<string> q;
q.push(beginWord);
set<string> visited;
visited.insert(beginWord);
while (!q.empty()) {
int n = q.size();
res += 1;
while (n--) {
string a = q.front();
q.pop();
if (a == endWord) return res;
set<string> bs;
for (int i = 0; i < a.size(); ++i) {
for (int j = 0; j < 26; ++j) {
char c = 'a' + j;
if (c != a[i]) {
string b = a;
b[i] = c;
if (words.count(b)) {
bs.insert(b);
}
}
}
}
for (string b : bs) {
if (visited.count(b) == 0) {
q.push(b);
visited.insert(b);
}
}
}
}
return 0;
}
};
python3代码如下,
class Solution:
def ladderLength(self, beginWord: str, endWord: str, wordList: List[str]) -> int:
words = wordList + [beginWord]
words = set(words)
q = collections.deque([beginWord])
visited = set()
visited.add(beginWord)
res = 0
while len(q) > 0:
n = len(q)
res += 1
for _ in range(n):
a = q.popleft()
if a == endWord:
return res
bs = set()
a = list(a)
for i in range(len(a)):
for j in range(26):
c = chr(ord('a')+j)
if c != a[i]:
preva = a[i]
a[i] = c
b = "".join(a)
if b in words:
bs.add(b)
a[i] = preva
for b in bs:
if b not in visited:
q.append(b)
visited.add(b)
return 0
题目31:684. 冗余连接
解题思路:并查集。
C++代码如下,
class Solution {
public:
vector<int> findRedundantConnection(vector<vector<int>>& edges) {
int n = edges.size();
vector<int> p(n+1, 0);
for (int i = 1; i <= n; ++i) p[i] = i;
function<int(int)> find =[&] (int x) -> int {
if (p[x] == x) return p[x];
p[x] = find(p[x]);
return p[x];
};
for (auto edge : edges) {
int pa = find(edge[0]), pb = find(edge[1]);
if (pa == pb) return edge;
else p[pa] = pb;
}
return {-1,-1};
}
};
python3代码如下,
class Solution:
def findRedundantConnection(self, edges: List[List[int]]) -> List[int]:
n = len(edges)
p = [i for i in range(n+1)]
def find(x: int) -> int:
if p[x] == x:
return p[x]
p[x] = find(p[x])
return p[x]
for a,b in edges:
pa, pb = find(a), find(b)
if pa != pb:
p[pa] = pb
else:
return [a,b]
return [-1,-1]
题目32:685. 冗余连接 II
解题思路:存在入度为2的结点,判断删除哪一条边之后,剩余图是一个有根树。不存在入度为2的结点,当做无向图判断。
C++代码如下,
class Solution {
public:
vector<vector<int>> edges;
vector<int> p;
int find(int x) {
if (p[x] == x) return p[x];
p[x] = find(p[x]);
return p[x];
}
bool check_delete_edge(vector<int> delete_edge) {
int n = edges.size();
p.resize(n+1,0);
for (int i = 1; i <= n; ++i) p[i] = i;
for (auto edge : edges) {
if (edge == delete_edge) continue;
int a = edge[0], b = edge[1];
int pa = find(a), pb = find(b);
if (pa == pb) return false;
else p[pa] = pb;
}
return true;
}
vector<int> find_redundant_edge() {
int n = edges.size();
p.resize(n+1,0);
for (int i = 1; i <= n; ++i) p[i] = i;
for (auto edge : edges) {
int a = edge[0], b = edge[1];
int pa = find(a), pb = find(b);
if (pa == pb) return edge;
else p[pa] = pb;
}
return {-1,-1};
}
vector<int> findRedundantDirectedConnection(vector<vector<int>>& edges) {
this->edges = edges;
int n = edges.size();
vector<int> ind(n+1,0);
for (auto edge: edges) {
ind[edge[1]] += 1;
}
vector<vector<int>> targets;
for (int i = n-1; i >= 0; --i) {
vector<int> edge = edges[i];
if (ind[edge[1]] == 2) {
targets.emplace_back(edge);
}
}
if (targets.size() == 2) {
if (check_delete_edge(targets[0])) {
return targets[0];
} else {
return targets[1];
}
} else if (targets.size() == 0) {
vector<int> res = find_redundant_edge();
return res;
}
return {-1,-1};
}
};
python3代码如下,
class Solution:
def __init__(self) -> None:
self.edges = []
def check_delete_edge(self, edge: list) -> bool:
n = len(self.edges)
p = [0] * (n + 1)
for i in range(1,n+1):
p[i] = i
def find(x: int) -> int:
if p[x] == x:
return p[x]
p[x] = find(p[x])
return p[x]
for a,b in self.edges:
if [a,b] == edge: #edge被删除了
continue
pa, pb = find(a), find(b)
if pa == pb:
return False
else:
p[pa] = pb
return True
def find_redundant_edge(self) -> list:
n = len(self.edges)
p = [0] * (n + 1)
for i in range(1,n+1):
p[i] = i
def find(x: int) -> int:
if p[x] == x:
return p[x]
p[x] = find(p[x])
return p[x]
for a,b in self.edges:
pa, pb = find(a), find(b)
if pa == pb:
return [a,b]
else:
p[pa] = pb
return [-1,-1]
def findRedundantDirectedConnection(self, edges: List[List[int]]) -> List[int]:
self.edges = edges
n = len(edges)
ind = [0] * (n + 1)
for a,b in edges:
ind[b] += 1
#度为2的结点,它对应的边
target = []
for i in range(n-1,-1,-1):
a, b = edges[i][0], edges[i][1]
if ind[b] == 2:
target.append([a,b])
if len(target) == 2:
if self.check_delete_edge(target[0]):
return target[0]
else:
return target[1]
elif len(target) == 0:
res = self.find_redundant_edge()
return res
题目33:657. 机器人能否返回原点
解题思路:模拟即可。
C++代码如下,
class Solution {
public:
bool judgeCircle(string moves) {
int a = count(moves.begin(), moves.end(), 'U');
int b = count(moves.begin(), moves.end(), 'D');
int c = count(moves.begin(), moves.end(), 'L');
int d = count(moves.begin(), moves.end(), 'R');
return a == b && c == d;
}
};
python3代码如下,
class Solution:
def judgeCircle(self, moves: str) -> bool:
a = moves.count('U')
b = moves.count('D')
c = moves.count('L')
d = moves.count('R')
return a == b and c == d
题目34:31. 下一个排列
解题思路:从末尾开始,找到一个最靠后的数对,满足nums[i] < nums[j] && i < j
,交换i
和j
,然后对nums[i+1:]
进行排序,返回。如果没有,返回从小到大的排序。
C++代码如下,
class Solution {
public:
void nextPermutation(vector<int>& nums) {
int n = nums.size();
for (int i = n-1; i >= 0; --i) {
for (int j = n-1; j > i; --j) {
if (nums[i] < nums[j]) {
swap(nums[i], nums[j]);
sort(nums.begin()+i+1,nums.end());
return;
}
}
}
sort(nums.begin(), nums.end());
return;
}
};
python3代码如下,
class Solution:
def nextPermutation(self, nums: List[int]) -> None:
"""
Do not return anything, modify nums in-place instead.
"""
n = len(nums)
for i in range(n-1,-1,-1):
for j in range(n-1,i,-1):
if nums[i] < nums[j]:
nums[i], nums[j] = nums[j], nums[i]
nums[i+1:] = sorted(nums[i+1:])
return
nums.sort()
return
题目35:463. 岛屿的周长
解题思路:对于gird[i][j]=1
的格子,它的四邻域内的格子的值为0
,则最终周长加上1
。
C++代码如下,
class Solution {
public:
int islandPerimeter(vector<vector<int>>& grid) {
int dirs[4][2] = {{-1,0},{1,0},{0,-1},{0,1}};
int n = grid.size();
int m = grid[0].size();
int res = 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < m; ++j) {
if (grid[i][j] == 1) {
for (int k = 0; k < 4; ++k) {
int ni = i + dirs[k][0];
int nj = j + dirs[k][1];
if (ni < 0 || ni >= n || nj < 0 || nj >= m) {
res += 1;
continue;
}
if (grid[ni][nj] == 0) {
res += 1;
}
}
}
}
}
return res;
}
};
python3代码如下,
class Solution:
def islandPerimeter(self, grid: List[List[int]]) -> int:
dirs = [[-1,0], [1,0], [0,-1], [0,1]]
n = len(grid)
m = len(grid[0])
res = 0
for i in range(n):
for j in range(m):
if grid[i][j] == 1:
for k in range(4):
ni = i + dirs[k][0]
nj = j + dirs[k][1]
if ni < 0 or ni >= n or nj < 0 or nj >= m:
res += 1
continue
if grid[ni][nj] == 0:
res += 1
return res
解题思路:模拟。
C++代码如下,
class Solution {
public:
vector<int> sortByBits(vector<int>& arr) {
sort(arr.begin(), arr.end(), [&](const int &a, const int &b) {
int cnt1 = __builtin_popcount(a);
int cnt2 = __builtin_popcount(b);
return cnt1 < cnt2 || (cnt1 == cnt2 && a < b);
});
return arr;
}
};
python3代码如下,
class Solution:
def sortByBits(self, arr: List[int]) -> List[int]:
arr.sort(key=lambda x : [x.bit_count(),x])
return arr