class Solution {
public:
bool hasCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast && fast->next){
slow = slow->next;
fast = fast->next->next;
if(fast == slow){
return true;
}
}
return false;
}
};
使用快慢指针,如果快慢指针汇合说明有环。
class Solution {
public:
ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {
ListNode* A = headA;
ListNode* B = headB;
while(A != B){
A = A != NULL ? A ->next : headB;
B = B != NULL ? B->next : headA;
}
return A;
}
};
代码答案很精妙,双指针遍历两个链表,因为a+c+b == b+c+a,所以必然汇合。
class Solution {
private:
int ans; //全局变量
int dfs(TreeNode* node){
if(node == NULL){
return 0;
}
int l_val = dfs(node->left);
int r_val = dfs(node->right);
ans = max(ans, l_val + r_val + node->val);
return max(max(l_val, r_val) + node->val, 0); //注意这里要用0截断负收益
}
public:
int maxPathSum(TreeNode* root) {
ans = INT_MIN;
dfs(root);
return ans;
}
};
使用递归,返回的是顺着该节点往下的值,同时修改ans为/\的最大值。
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root == nullptr){
return 0;
}
swap(root->left, root->right);
invertTree(root->left);
invertTree(root->right);
return root;
}
};
简单递归。
class Solution {
public:
int maxDepth(TreeNode* root) {
if(root == nullptr){
return 0;
}
int depth = 0;
int l_depth = maxDepth(root->left);
int r_depth = maxDepth(root->right);
return max(l_depth, r_depth) + 1;
}
};
同样递归计算左右子树,之后取max加1。
class Solution {
public:
int ans = 0;
int diameterOfBinaryTree(TreeNode* root) {
auto dfs = [&](this auto&& dfs, TreeNode* node){
if(node == nullptr){
return -1;
}
int l_len = dfs(node->left) + 1;
int r_len = dfs(node->right) + 1;
ans = max(ans, l_len + r_len);
return max(l_len, r_len);
};
dfs(root);
return ans;
}
};
其实是最大路径和的简化版,相当于所有路的权重都为1。递归即可,这里学一下Lambda函数的写法,写一个dfs,递归算左右的直径,ans是加和。
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast && fast->next){
fast = fast->next->next;
slow = slow->next;
if(fast == slow){
while(slow != head){
slow = slow->next;
head = head->next;
}
return slow;
}
}
return nullptr;
}
};
依旧快慢指针,在环形链表一的基础上,因为从slow出去的步数正好是从头开始到入口的步数,所以加一个判断即可步进到入口。
class Solution {
public:
int trap(vector<int>& height) {
int ans = 0, pre_max = 0, suf_max = 0;
int left = 0, right = height.size() - 1;
while(left < right){
pre_max = max(pre_max, height[left]);
suf_max = max(suf_max, height[right]);
ans += pre_max > suf_max ? suf_max-height[right--] : pre_max-height[left++];
}
return ans;
}
};
传统方法使用两个数组储存左右高度;这里使用左右双指针,因为只要一侧比另一侧高度小,就能确定他能装的水量,实现O(1)的空间复杂度。
class Solution {
public:
void moveZeroes(vector<int>& nums) {
int i0 = 0;
for(int& x : nums){
if(x){
swap{x, nums[i0]};
i0++;
}
}
}
};
快慢指针。快指针遍历数组元素,慢指针是标志着空位,如果快指针检测到非零元素则交换至空位,然后慢指针右移一位。