GitHub链接:https://github.com/WilliamWuLH/LeetCode
如果你觉得不错可以 ⭐Star 和 Fork ❤
226.Invert Binary Tree
递归:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* invertTree(TreeNode* root) {
if(root == NULL)
return root;
TreeNode* temp = root->left;
root->left = root->right;
root->right = temp;
if(root->left != NULL)
invertTree(root->left);
if(root->right != NULL)
invertTree(root->right);
return root;
}
};
234.Palindrome Linked List
双指针(快慢指针)+ 反转后半部分链表:
/**
* Definition for singly-linked list.
* struct ListNode {
* int val;
* ListNode *next;
* ListNode(int x) : val(x), next(NULL) {}
* };
*/
class Solution {
public:
bool isPalindrome(ListNode* head) {
ListNode* fast = head;
ListNode* slow = head;
while(fast != NULL && fast->next != NULL){
fast = fast->next->next;
slow = slow->next;
}
ListNode* pre = NULL;
while(slow != NULL){
ListNode* temp = slow;
slow = slow->next;
temp->next = pre;
pre = temp;
}
fast = head;
while(pre != NULL){
if(fast->val != pre->val)
return false;
fast = fast->next;
pre = pre->next;
}
return true;
}
};
236.Lowest Common Ancestor of a Binary Tree
递归 DFS + 公共前缀:
思路很简单:先对两个结点进行深度优先搜索,并且记录搜索的路径,走左子树的话路径记录为 0,走右子树的话记录为 1,由此记录方式可以唯一并且准确记录从根结点到达目标结点的路径。
然后再判断这两个目标结点的路径的公共前缀,即到达这两个目标结点必须经过的共同路径。
找到它们的共同路径,在共同路径(公共前缀)的最后一个结点就-是这两个目标结点的最近公共祖先。
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
vector<int> ppath, qpath;
dfs(root, p, ppath);
dfs(root, q, qpath);
int len = min(ppath.size(), qpath.size());
for(int i=0; i<len; i++){
if(ppath[i] != qpath[i])
break;
if(ppath[i])
root = root->right;
else
root = root->left;
}
return root;
}
bool dfs(TreeNode* root, TreeNode* target, vector<int> &path){
if(root == target)
return true;
if(root != NULL){
if(root->left != NULL){
path.push_back(0);
if( dfs(root->left, target, path) )
return true;
path.pop_back();
}
if(root->right != NULL){
path.push_back(1);
if( dfs(root->right, target, path) )
return true;
path.pop_back();
}
}
return false;
}
};
238.Product of Array Except Self
乘积 = 左边全部数的乘积 * 右边全部数的乘积:
一趟循环,先算出左边全部数的乘积,再一趟循环回来,算出答案。
class Solution {
public:
vector<int> productExceptSelf(vector<int>& nums) {
vector<int> ans;
int temp = 1;
for(int i=0; i<nums.size(); i++){
if(i == 0){
ans.push_back(1);
continue;
}
ans.push_back(ans[i-1]*nums[i-1]);
}
for(int i=nums.size()-2; i>=0; i--){
temp *= nums[i+1];
ans[i] *= temp;
}
return ans;
}
};
239.Sliding Window Maximum
双端队列:
为什么选择双端队列?
既可以弹出队首元素,也可以弹出队尾元素,也可以在队尾插入元素,也可以访问队首元素。
在双端队列中维持一个数组值单调递减的队列,队列中的元素必须都在窗口中,并且队首元素就是最大值,第二个就是第二大的值,以此类推。
每次来一个元素,判断这个元素应该在这个双端队列的什么位置,从双端队列的队尾开始判断,比它小的都要弹出队列,直到找到比它大的或者是队列为空了,把此时的这个元素插入队列中。
并且需要判断此时的队首是否还在新窗口中,即此时的最大值是否还合法,不合法(不在窗口中)就必须弹出。
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> ans;
deque<int> dq;
int len = nums.size();
for(int i=0; i<len; i++){
while(!dq.empty()){
if(dq.front() <= i-k)
dq.pop_front();
else if(nums[ dq.back() ] < nums[i])
dq.pop_back();
else
break;
}
dq.push_back(i);
if(i+1 >= k)
ans.push_back(nums[ dq.front() ]);
}
return ans;
}
};