学习目标:
学习代码随想录--二叉树
- 每天学习1道,复习两道
学习内容:
2025.4.7
复习内容:
-
两两交换链表中的节点
-
最大二叉树
学习内容
- 合并二叉树
2025.4.8
复习内容:
-
二分查找
-
合并二叉树
-
- 移除元素
学习内容:
- 二叉搜索树中的搜索
2025.4.9
学习内容:
- 验证二叉搜索树
2025.4.11
学习内容:
-
验证二叉搜索树 -- 迭代法
-
二叉搜索树的最小绝对差
复习内容:
-
有序数组的平方
-
长度最小的子数组
2025.4.12忘了保存了
2025.4.13
学习内容:
- 二叉树的最近公共祖先
复习内容:
- 二叉搜索树中的众数
58.区间和
2025.4.14
学习内容:
- 二叉搜索树的最近公共祖先
复习内容:
-
二叉树的最近公共祖先
-
开发商购买土地(第五期模拟笔试)
2025.4.15
学习内容:
- 二叉搜索树中的插入操作
复习内容:
-
二叉搜索树的最近公共祖先
-
移除链表元素
2025.4.21
学习内容
-
删除二叉搜索树中的节点
-
修剪二叉搜索树
2025.4.22
学习内容:
- 将有序数组转换为二叉搜索树
2025.4.23
学习内容:
- 把二叉搜索树转换为累加树
复习内容:
-
删除二叉搜索树中的节点
-
修剪二叉搜索树
2025.4.25
复习内容:
-
把二叉搜索树转换为累加树
-
将有序数组转换为二叉搜索树
-
修剪二叉搜索树
-
删除二叉搜索树中的节点
学习产出:
**
2025.4.7
**
24.交换链表中的节点
cpp
ListNode* swapPairs(ListNode* head) {
ListNode* dummyHead = new ListNode();
dummyHead -> next = head;
ListNode* node = dummyHead;
while (node -> next != nullptr && node -> next -> next != nullptr)
{
ListNode* cur = node -> next;
ListNode* curNext = node -> next -> next -> next;
node -> next = node -> next -> next;
node -> next -> next = cur;
node -> next -> next -> next = curNext;
node = node -> next -> next;
}
head = dummyHead -> next;
delete(dummyHead);
return head;
}
654. 最大二叉树
cpp
TreeNode* constructMaximumBinaryTree(vector<int>& nums) {
TreeNode* root = new TreeNode();
if (nums.size() == 1)
{
root -> val = nums[0];
return root;
}
int maxIndex = 0, maxValue = INT_MIN;
for (int i = 0; i < nums.size(); i++)
{
if (maxValue < nums[i])
{
maxIndex = i;
maxValue = nums[i];
}
}
root -> val = maxValue;
//分割数组
if (maxIndex > 0)
{
vector<int> leftNums(nums.begin(), nums.begin() + maxIndex);
root -> left = constructMaximumBinaryTree(leftNums);
}
if (maxIndex < nums.size() - 1)
{
vector<int> rightNums(nums.begin() + maxIndex + 1, nums.end());
root -> right = constructMaximumBinaryTree(rightNums);
}
return root;
}
617. 合并二叉树
cpp
//递归法 --- 前序遍历
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if (root1 == nullptr) return root2;
if (root2 == nullptr) return root1;
root1 -> val += root2 -> val;
root1 -> left = mergeTrees(root1 -> left, root2 -> left);
root1 -> right = mergeTrees(root1 -> right, root2 -> right);
return root1;
}
cpp
//迭代法
TreeNode* mergeTrees(TreeNode* root1, TreeNode* root2) {
if (root1 == nullptr) return root2;
if (root2 == nullptr) return root1;
queue<TreeNode*> que;
que.push(root1);
que.push(root2);
while (!que.empty())
{
TreeNode* node1 = que.front(); que.pop();
TreeNode* node2 = que.front(); que.pop();
node1 -> val += node2 -> val;
if (node1 -> left != nullptr && node2 -> left != nullptr)
{
que.push(node1 -> left);
que.push(node2 -> left);
}
if (node1 -> right != nullptr && node2 -> right != nullptr)
{
que.push(node1 -> right);
que.push(node2 -> right);
}
if (node1 -> left == nullptr && node2 -> left != nullptr)
{
node1 -> left = node2 -> left;
}
if (node1 -> right == nullptr && node2 -> right != nullptr)
{
node1 -> right = node2 -> right;
}
}
return root1;
}
**
2025.4.8
704. 二分查找
cpp
int findLeftEnd(vector<int> nums, int target)
{
int l = 0, r = nums.size() - 1;
while (l < r)
{
int mid = (l + r + 1) >> 1;
if (nums[mid] > target) r = mid - 1;
else l = mid;
}
return l;
}
int findRightFirst(vector<int> nums, int target)
{
int l = 0, r = nums.size() - 1;
while (l < r)
{
int mid = (l + r) >> 1;
if (nums[mid] >= target) r = mid;
else l = mid + 1;
}
return l;
}
//上面两种方法都可以,可以看实际应用场景进行使用
int search(vector<int>& nums, int target) {
//int ans = findLeftEnd(nums, target);
int ans = findRightFirst(nums, target);
if (nums[ans] == target) return ans;
return -1;
}
27. 移除元素
cpp
//双指针算法
int removeElement(vector<int>& nums, int val) {
int count = 0;
for (int i = 0; i < nums.size(); i++)
{
if (nums[i] != val)
{
nums[count++] = nums[i];
}
}
return count;
}
700. 二叉搜索树中的搜索
cpp
//递归法
TreeNode* searchBST(TreeNode* root, int val) {
if (root == nullptr || root -> val == val) return root;
TreeNode* node = new TreeNode();
if (root -> val > val) node = searchBST(root -> left, val);
else node = searchBST(root -> right, val);
return node;
}
cpp
//迭代法
TreeNode* searchBST(TreeNode* root, int val) {
while (root != nullptr)
{
if (root -> val > val) root = root -> left;
else if (root -> val < val) root = root -> right;
else return root;
}
return nullptr;
}
2025.4.9
98. 验证二叉搜索树
cpp
//递归(中序遍历)
TreeNode* pre = nullptr;
bool isValidBST(TreeNode* root) {
if (root == nullptr) return true;
bool left = isValidBST(root -> left);
if (pre != nullptr && pre -> val >= root -> val) return false;
pre = root;
bool right = isValidBST(root -> right);
return left && right;
}
csharp
//递归将节点值存入数组(中序遍历)
vector<int> nums;
void traversal(TreeNode* node)
{
if (node -> left != nullptr) traversal(node -> left);
nums.push_back(node -> val);
if (node -> right != nullptr) traversal(node -> right);
}
bool isValidBST(TreeNode* root) {
nums.clear();
if (root == nullptr) return true;
traversal(root);
for (int i = 1; i < nums.size(); i++)
{
if (nums[i - 1] >= nums[i]) return false;
}
return true;
}
2025.4.11
98. 验证二叉搜索树 -- 迭代法
csharp
TreeNode* maxNode;
bool isValidBST(TreeNode* root) {
stack<TreeNode*> stk;
if (root != nullptr) stk.push(root);
TreeNode* maxNode = nullptr;
while (!stk.empty())
{
TreeNode* node = stk.top();
stk.pop();
if (node != nullptr)
{
if (node -> right) stk.push(node -> right);
stk.push(node);
stk.push(nullptr);
if (node -> left) stk.push(node -> left);
}
else
{
node = stk.top();
stk.pop();
if (maxNode == nullptr || maxNode -> val < node -> val) maxNode = node;
else return false;
}
}
return true;
}
530. 二叉搜索树的最小绝对差
cpp
//递归数组
public:
vector<int> nums;
void traversal(TreeNode* node)
{
if (node -> left != nullptr) traversal(node -> left);
nums.push_back(node -> val);
if (node -> right != nullptr) traversal(node -> right);
}
int getMinimumDifference(TreeNode* root) {
nums.clear();
traversal(root);
int result = INT_MAX;
for (int i = 1; i < nums.size(); i++)
{
result = min(result, nums[i] - nums[i - 1]);
}
return result;
}
cpp
//递归记录前序节点
public:
TreeNode* preNode = nullptr;
int result = INT_MAX;
void traversal(TreeNode* node)
{
if (node -> left != nullptr) traversal(node -> left);
if (preNode != nullptr)
{
result = min(result, node -> val - preNode -> val);
}
preNode = node;
if (node -> right != nullptr) traversal(node -> right);
}
int getMinimumDifference(TreeNode* root) {
traversal(root);
return result;
}
2025.4.13
cpp
//迭代法
public:
TreeNode* preNode = nullptr;
int result = INT_MAX;
int getMinimumDifference(TreeNode* root) {
stack<TreeNode*> stk;
if (root != nullptr) stk.push(root);
while (!stk.empty())
{
TreeNode* node = stk.top();
stk.pop();
if (node != nullptr)
{
if (node -> right != nullptr) stk.push(node -> right);
stk.push(node);
stk.push(nullptr);
if (node -> left != nullptr) stk.push(node -> left);
}
else
{
node = stk.top();
stk.pop();
if (preNode != nullptr) result = min(result, node -> val - preNode -> val);
preNode = node;
}
}
return result;
}
977. 有序数组的平方
cpp
//暴力做法,直接平方+快排
void quick_sort(vector<int> &nums, int l, int r)
{
if (l >= r) return;
int x = nums[(l + r) >> 1];
int i = l - 1, j = r + 1;
while (i < j)
{
do i++; while (x > nums[i]);
do j--; while (x < nums[j]);
if (i < j) swap(nums[i], nums[j]);
}
quick_sort(nums, l, j);
quick_sort(nums, j + 1, r);
}
vector<int> sortedSquares(vector<int>& nums) {
for (int i = 0; i < nums.size(); i++)
{
nums[i] *= nums[i];
}
quick_sort(nums, 0, nums.size() - 1);
return nums;
}
cpp
//双指针法
public:
vector<int> sortedSquares(vector<int>& nums) {
int i = 0, j = nums.size() - 1;
//初始化
vector<int> result(nums.size(), 0);
int k = j;
while (k >= 0)
{
if (nums[i] * nums[i] > nums[j] * nums[j])
{
result[k] = nums[i] * nums[i];
i++;
}
else
{
result[k] = nums[j] * nums[j];
j--;
}
k--;
}
return result;
}
209. 长度最小的子数组
cpp
public:
//滑动窗口
int minSubArrayLen(int target, vector<int>& nums) {
int minLength = INT_MAX;
int i = 0;
int result = 0;
for (int j = 0; j < nums.size(); j++)
{
result += nums[j];
while (result >= target)
{
minLength = min(minLength, j - i + 1);
result -= nums[i++];
}
}
return minLength == INT_MAX ? 0 : minLength;
}
236. 二叉树的最近公共祖先
cpp
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == p || root == q || root == nullptr) return root;
TreeNode* right = lowestCommonAncestor(root -> right, p, q);
TreeNode* left = lowestCommonAncestor(root -> left, p, q);
if (left != nullptr && right != nullptr) return root;
if (left != nullptr && right == nullptr) return left;
else if (left == nullptr && right != nullptr) return right;
else return nullptr;
}
501. 二叉搜索树中的众数
cpp
//作为普通二叉树
void traversal(TreeNode* node, unordered_map<int, int> &map)
{
//前序遍历
map[node -> val]++;
if (node -> left) traversal(node -> left, map);
if (node -> right) traversal(node -> right, map);
}
bool static cmp(const pair<int, int> &A, const pair<int, int> &B)
{
return A.second > B.second;
}
vector<int> findMode(TreeNode* root) {
unordered_map<int, int> map;
traversal(root, map);
vector<pair<int, int>> nums(map.begin(), map.end());
sort(nums.begin(), nums.end(), cmp);
vector<int> result;
result.push_back(nums[0].first);
for (int i = 1; i < nums.size(); i++)
{
if (nums[i].second == nums[0].second) result.push_back(nums[i].first);
else break;
}
return result;
}
cpp
//利用二叉搜索树的特性:中序遍历有序
TreeNode* preNode;
int maxCount = 0;
int count = 0;
vector<int> result;
void traversal(TreeNode* node)
{
if (node -> left) traversal(node -> left);
if (preNode == nullptr) count = 1;
if (preNode != nullptr && preNode -> val != node -> val)
{
count = 1;
}
else if (preNode != nullptr && preNode -> val == node -> val)
{
count++;
}
//清空数组,重新添加众数
if (count > maxCount)
{
result.clear();
maxCount = count;
result.push_back(node -> val);
}
else if (count == maxCount) result.push_back(node -> val);
preNode = node;
if (node -> right) traversal(node -> right);
}
vector<int> findMode(TreeNode* root) {
if (root == nullptr) return result;
traversal(root);
return result;
}
58.区间和
cpp
#include <iostream>
#include <vector>
using namespace std;
int main()
{
int n;
int a, b;
cin >> n;
vector<int> nums(n);
vector<int> sums(n);
int preSum = 0;
for (int i = 0; i < n; i++)
{
cin >> nums[i];
preSum += nums[i];
sums[i] = preSum;
}
while (cin >> a >> b)
{
int ans = 0;
if (a == 0) ans = sums[b];
else ans = sums[b] - sums[a - 1];
cout << ans << endl;
}
}
2025.4.14
235. 二叉搜索树的最近公共祖先
cpp
TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
if (root == nullptr) return root;
if (root -> val > p -> val && root -> val > q -> val)
{
TreeNode* left = lowestCommonAncestor(root -> left, p, q);
if (left != nullptr) return left;
}
if (root -> val < p -> val && root -> val < q -> val)
{
TreeNode* right = lowestCommonAncestor(root -> right, p, q);
if (right != nullptr) return right;
}
return root;
}
44. 开发商购买土地(第五期模拟笔试)
cpp
#include <iostream>
#include <vector>
#include <climits>
using namespace std;
int main()
{
int n, m;
cin >> n >> m;
vector<vector<int>> nums(n, vector<int>(m, 0));
int sum = 0;
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
{
cin >> nums[i][j];
sum += nums[i][j];
}
vector<int> horizontal(n, 0);
for (int i = 0; i < n; i++)
for (int j = 0; j < m; j++)
horizontal[i] += nums[i][j];
vector<int> vertical(m, 0);
for (int j = 0; j < m; j++)
for (int i = 0; i < n; i++)
vertical[j] += nums[i][j];
int result = INT_MAX;
int horizontalCut = 0;
for (int i = 0; i < n; i++)
{
//这块才实现了横向的区间和
horizontalCut += horizontal[i];
result = min(result, abs(sum - horizontalCut - horizontalCut));
}
int verticalCut = 0;
for (int j = 0; j < m; j++)
{
//这块实现了纵向的区间和
verticalCut += vertical[j];
result = min(result, abs(sum - verticalCut - verticalCut));
}
cout << result << endl;
}
2025.4.15
701. 二叉搜索树中的插入操作
cpp
//存在返回值的递归
TreeNode* insertIntoBST(TreeNode* root, int val) {
if (root == nullptr)
{
TreeNode* node = new TreeNode(val);
return node;
}
if (root -> val > val) root -> left = insertIntoBST(root -> left, val);
if (root -> val < val) root -> right = insertIntoBST(root -> right, val);
return root;
}
cpp
//无返回值的递归:利用parent记录
TreeNode* parent;
void traversal(TreeNode* node, int val)
{
if (node == nullptr)
{
TreeNode* cur = new TreeNode(val);
if (parent -> val > val) parent -> left = cur;
else parent -> right = cur;
return;
}
parent = node;
if (node -> val > val) traversal(node -> left, val);
else traversal(node -> right, val);
return;
}
TreeNode* insertIntoBST(TreeNode* root, int val) {
//因为存在空节点测试的案例,所以一定要有这个判断
if (root == nullptr)
{
root = new TreeNode(val);
return root;
}
traversal(root, val);
return root;
}
cpp
//迭代法:通过大左小右的方式,先找到空节点,同时也利用parent记录上一个节点
TreeNode* insertIntoBST(TreeNode* root, int val) {
if (root == nullptr)
{
root = new TreeNode(val);
return root;
}
TreeNode* cur = root;
TreeNode* parent;
while (cur != nullptr)
{
parent = cur;
if (cur -> val > val) cur = cur -> left;
else cur = cur -> right;
}
TreeNode* node = new TreeNode(val);
if (parent -> val > val) parent -> left = node;
else parent -> right = node;
return root;
}
203. 移除链表元素
cpp
ListNode* removeElements(ListNode* head, int val) {
ListNode* dummyHead = new ListNode();
dummyHead -> next = head;
ListNode* cur = dummyHead;
while (cur -> next != nullptr)
{
if (cur -> next -> val == val)
{
ListNode* x = cur -> next;
cur -> next = cur -> next -> next;
delete(x);
}
else
//关注这个位置,因为判断的是cur -> next不为空,所以上面需要更新cur时,下面就不需要更新了,只有cur -> val != val的时候,才需要更新cur的值
cur = cur -> next;
}
head = dummyHead -> next;
return head;
}
2025.4.21
450. 删除二叉搜索树中的节点
cpp
//删除二叉排序树的节点---递归
TreeNode* deleteNode(TreeNode* root, int key) {
if (root == nullptr) return root;
if (root -> val > key) root -> left = deleteNode(root -> left, key);
else if (root -> val < key) root -> right = deleteNode(root -> right, key);
if (root -> val == key)
{
//左右子节点为空
if (root -> left == nullptr && root -> right == nullptr)
{
delete root;
return nullptr;
}
//左节点为空
if (root -> left == nullptr)
{
TreeNode* resNode = root -> right;
delete root;
return resNode;
}
//右节点为空
else if (root -> right == nullptr)
{
TreeNode* resNode = root -> left;
delete root;
return resNode;
}
//左右节点都不为空
else
{
//先找到右子树的最左节点
TreeNode* cur = root -> right;
while (cur -> left != nullptr)
{
cur = cur -> left;
}
cur -> left = root -> left;
TreeNode* resNode = root -> right;
delete root;
return resNode;
}
}
return root;
}
cpp
//迭代法(与递归法的删除逻辑相同,不同的只有遍历)
TreeNode* deleteOneNode(TreeNode* node)
{
if (node == nullptr) return node;
if (node -> left == nullptr && node -> right == nullptr)
{
delete node;
return nullptr;
}
if (node -> left == nullptr)
{
TreeNode* resNode = node -> right;
delete node;
return resNode;
}
else if (node -> right == nullptr)
{
TreeNode* resNode = node -> left;
delete node;
return resNode;
}
else
{
TreeNode* cur = node -> right;
while (cur -> left != nullptr)
{
cur = cur -> left;
}
cur -> left = node -> left;
TreeNode* resNode = node -> right;
delete node;
return resNode;
}
}
TreeNode* deleteNode(TreeNode* root, int key) {
TreeNode* cur = root, *pre = nullptr;
while (cur)
{
if (cur -> val == key) break;
pre = cur;
if (cur -> val > key) cur = cur -> left;
else cur = cur -> right;
}
//根节点被删除
if (pre == nullptr)
{
root = deleteOneNode(cur);
return root;
}
if (pre -> left && pre -> left -> val == key)
{
pre -> left = deleteOneNode(cur);
}
if (pre -> right && pre -> right -> val == key)
{
pre -> right = deleteOneNode(cur);
}
return root;
}
669. 修剪二叉搜索树
cpp
//递归法
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (root == nullptr) return nullptr;
if (root -> val > high)
{
TreeNode* left = trimBST(root -> left, low, high);
return left;
}
if (root -> val < low)
{
TreeNode* right = trimBST(root -> right, low, high);
return right;
}
root -> left = trimBST(root -> left, low, high);
root -> right = trimBST(root -> right, low, high);
return root;
}
cpp
//迭代法
TreeNode* trimBST(TreeNode* root, int low, int high) {
if (root == nullptr) return nullptr;
//寻找合适的root,然后再进行修剪
while (root != nullptr && (root -> val < low || root -> val > high))
{
if (root -> val < low) root = root -> right;
else root = root -> left;
}
//修剪左子树
TreeNode* cur = root;
while (cur != nullptr)
{
//左子树是否符合条件
while (cur -> left != nullptr && cur -> left -> val < low)
{
cur -> left = cur -> left -> right;
}
cur = cur -> left;
}
cur = root;
while (cur != nullptr)
{
//这块需要用while来判断,因为if的话只能判断一次,但是需要多次判断是否修剪这个节点
while (cur -> right != nullptr && cur -> right -> val > high)
{
cur -> right = cur -> right -> left;
}
cur = cur -> right;
}
return root;
}
2025.4.22
108. 将有序数组转换为二叉搜索树
cpp
//递归法,每一段循环都采用左闭右闭的方式
TreeNode* traversal(vector<int> nums, int l, int r)
{
if (l > r) return nullptr;
int mid = l + (r - l) / 2;
TreeNode* root = new TreeNode(nums[mid]);
root -> left = traversal(nums, l, mid - 1);
root -> right = traversal(nums, mid + 1, r);
return root;
}
TreeNode* sortedArrayToBST(vector<int>& nums) {
TreeNode* root = traversal(nums, 0, nums.size() - 1);
return root;
}
cpp
TreeNode* sortedArrayToBST(vector<int>& nums) {
if (nums.size() == 0) return nullptr;
//定义三个队列
queue<TreeNode*> nodeQue;
queue<int> leftQue;
queue<int> rightQue;
//创建一个空节点,等找到了中间位置,再对空节点进行赋值
TreeNode* node = new TreeNode();
nodeQue.push(node);
//记录当前nodeQue的空节点所需要存储的左右边界的值
leftQue.push(0);
rightQue.push(nums.size() - 1);
while (!nodeQue.empty())
{
//将队列中的节点取出,并对其赋值
TreeNode* curNode = nodeQue.front(); nodeQue.pop();
int left = leftQue.front(); leftQue.pop();
int right = rightQue.front(); rightQue.pop();
int mid = left + (right - left) / 2;
curNode -> val = nums[mid];
//找到了根节点,然后为其添加左右节点
if (left <= mid - 1)
{
curNode -> left = new TreeNode();
nodeQue.push(curNode -> left);
leftQue.push(left);
rightQue.push(mid - 1);
}
if (right >= mid + 1)
{
curNode -> right = new TreeNode();
nodeQue.push(curNode -> right);
leftQue.push(mid + 1);
rightQue.push(right);
}
}
return node;
}
2025.4.23
538. 把二叉搜索树转换为累加树
cpp
//递归法
int pre = 0;
//需要采用逆向中序遍历,即右中左
void traversal(TreeNode* node)
{
if (node == nullptr) return;
traversal(node -> right);
pre += node -> val;
node -> val = pre;
traversal(node -> left);
}
TreeNode* convertBST(TreeNode* root) {
traversal(root);
return root;
}
cpp
//迭代法
TreeNode* convertBST(TreeNode* root) {
stack<TreeNode*> stk;
int pre = 0;
if (root != nullptr) stk.push(root);
while (!stk.empty())
{
TreeNode* node = stk.top();
stk.pop();
if (node != nullptr)
{
if (node -> left) stk.push(node -> left);
stk.push(node);
stk.push(nullptr);
if (node -> right) stk.push(node -> right);
}
else
{
node = stk.top();
stk.pop();
pre += node -> val;
node -> val = pre;
}
}
return root;
}