第一题:题目链接https://leetcode.cn/submissions/detail/623568420/
代码:
/**
* 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 hasPathSum(TreeNode* root, int targetSum) {
if (root == nullptr) {
return false;
}
if (root->left == nullptr && root->right == nullptr) {
return targetSum == root->val;
}
//dfs递归,检查有无目标值
return hasPathSum(root->left, targetSum - root->val) ||
hasPathSum(root->right, targetSum - root->val);
}
};
解题逻辑:
题目给了我们一颗二叉树,那么我们可以直接利用搜索解题。
由于解答注定要遍历整棵树,那么使用dfs或bfs都无妨,这里我们使用dfs深搜算法。
首先剪枝,若根节点为空,直接返回false,只有根节点,判断根节点值是否等于目标。
接着直接递归,逐个访问子节点。
考察点:
- 二叉树遍历,叶子节点判断
- 递归应用
第二题:题目链接https://leetcode.cn/problems/single-element-in-a-sorted-array/description/
代码:
class Solution {
public:
int singleNonDuplicate(vector<int>& nums) {
int n = nums.size();
if(n == 1) return nums[0];
int left = 0, right = n - 1;
while(left < right) {
int mid = (left + right) / 2;
// 使mid为偶数索引
if(mid % 2 == 1) mid--;
if(nums[mid] == nums[mid+1]) {
// 单一元素在右侧
left = mid + 2;
} else {
//单一元素在左侧或当前
right = mid;
}
}
return nums[left];
}
};
解题逻辑:
题目要求时间复杂度为O(log(n)),空间复杂度为O(1),因此我们使用二分查找算法。
首先仍旧剪枝,若只有一个元素,直接返回该元素。
由于只有一个单一元素,所以当mid为偶数下标时,若nums[mid] == nums[mid+1],则单一元素一定在右侧;nums[mid] != nums[mid+1],那么单一元素在左侧或当前。继续while循环直至left>=right。
为什么left=mid+2?
- 跳过一个完整的配对:执行该表达式的条件为nums[mid]已经等于nums[mid+1],因此直接跳过mid+1下标的判断。
- 避免死循环:对于[1,1,2,3,3],若left=mid+1:
- 第一次:left=0,right=4,mid=2。单一元素在当前位置,right变为2
- 第二次:left=0,right=2,mid=0(经过偶数校准),单一元素在右侧,left变为1
- 第三次,left=1,right=2,mid=0(经过偶数校准),单一元素在右侧,left变为1
- 重复第三次循环……
- 产生原因:没有跳过一个完整的配对,经过mid偶数校准后,mid可能会跳出left-right边界,此时已经逻辑错误,陷入死循环。
考察点:
- 偶数下标判断单一元素位置
- 二分查找应用
- left,right,mid边界处理