二叉树展开为链表
分析: ??先进行先序遍历,然后根据遍历结果进行链接。 代码:
class Solution {
public:
vector<TreeNode*> res;
void dfs(TreeNode* root) {
if(root) {
res.push_back(root);
dfs(root->left);
dfs(root->right);
}
}
void flatten(TreeNode* root) {
dfs(root);
TreeNode* ptr = new TreeNode(0);
TreeNode* head = ptr;
for(TreeNode* x : res) {
ptr->left = NULL;
ptr->right = x;
ptr = x;
}
root = head->right;
}
};
最长连续序列
分析: ??暴力求解:先利用set将所有数据进行去重。然后枚举集合里的元素,接着从枚举的元素开始顺序枚举,直到满足不再连续的条件,记录此次枚举的最大长度即可。 ??但是,题目要求时间复杂度为o(n),所以需要进行优化。考虑如下情况:设当前枚举的为x,如果x - 1已经在集合里面,那么就直接跳过,因为枚举从x-1开始时其最大长度肯定是大于从x开始。 代码:
class Solution {
public:
int longestConsecutive(vector<int>& nums) {
unordered_set<int> nums_set;
for(int x : nums) {
nums_set.insert(x);
}
int res = 0;
for(int x : nums_set) {
if(nums_set.count(x - 1) == 0) {
int cur = x;
int temp = 0;
while(nums_set.count(cur)) {
temp++;
cur++;
}
res = max(res, temp);
}
}
return res;
}
};
环形链表 II
方法一: ??遍历链表,如果当前节点不在集合里就加入,否则说明遇到环的开始处。 代码:
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
unordered_set<ListNode*> st;
ListNode* ptr = head;
while(ptr) {
if(st.count(ptr)) {
return ptr;
}else {
st.insert(ptr);
ptr = ptr->next;
}
}
return NULL;
}
};
方法二: ??快慢指针。我们使用两个指针,fast与slow。它们起始都位于链表的头部。随后,slow指针每次向后移动一个位置,而fast指针向后移动两个位置。如果链表中存在环,则fast指针最终将再次与slow指针在环中相遇。 ??证明见官方题解: 代码:
class Solution {
public:
ListNode *detectCycle(ListNode *head) {
ListNode *slow = head, *fast = head;
while (fast != nullptr) {
slow = slow->next;
if (fast->next == nullptr) {
return nullptr;
}
fast = fast->next->next;
if (fast == slow) {
ListNode *ptr = head;
while (ptr != slow) {
ptr = ptr->next;
slow = slow->next;
}
return ptr;
}
}
return nullptr;
}
};
|