LeetCode 704 二分查找
题目链接:704
思路:采用二分查找,左右指针用于确定目标所在范围,每次判断范围的中间值是否为目标,若不是则更新范围。
代码:
class Solution {
public:
int search(vector<int>& nums, int target) {
// 确定左右边界初始值
int left = 0;
int right = nums.size() - 1;
int i;
while (left <= right) {
i = (left + right) / 2;
// 判断中间值是否为目标
if (nums[i] == target)
return i;
else if (nums[i] > target)
// 若中间值大于目标,则移动右指针
right = i-1;
else
// 若中间值小于目标,则移动左指针
left = i+1;
}
return -1;
}
};
注意:在更新范围时,不应写成right = i
或left = i
, 否则可能导致死循环。
LeetCode 27 移除元素
题目链接:27
解1:快慢指针
思路:移除元素,也可理解为选出不等于val
的元素,并重新写入数组。采用快慢指针,慢指针用于指示下一写入的位置, 快指针用于遍历搜索不等于val
的值。为便于理解,可想象有一个新数组,快指针在旧数组中遍历搜索不等于val
的值,并依次写入新数组中。只不过,实际实现时,新数组的内存地址与旧数组重合。
代码:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
// pos用于指示下一写入的位置,search用于遍历数组
int pos = 0;
int search = 0;
for (search; search<nums.size(); ++search) {
// 若search指向的值等于val,则不写入
// 否则,将该值写入pos指向的位置
if (nums[search] != val) {
nums[pos] = nums[search];
// 若pos处写入值,则pos向后移动,指示下一位置
++pos;
}
}
return pos;
}
};
分析:最坏情况遍历序列2次
解2:双指针优化
思路:通过左右指针,依次将靠右的值赋给靠左的val
。左右指针向中心移动直至重合。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int left = 0;
int right = nums.size() - 1;
while (left <= right) {
if (nums[left] == val) {
// 若左值为val,则将右值赋给左值,并将右指针右移
// 左指针不动,在下轮中判断新的左值
nums[left] = nums[right];
--right;
} else {
++left;
}
}
return left;
}
};
分析:至多遍历一次