704. 二分查找(题目链接:力扣)
思路:第一眼看到题目描述就想直接枚举了,但还是按照二分查找的方式写了一遍,唯一要注意的就是每次区间闭合的问题,要保持一致性。
int search(vector<int> &nums, int target)
{
int left = 0;
int right = nums.size() - 1;
while (left <= right)
{
int middle = (left + right) / 2;
if (nums[middle] < target)
{
left = middle + 1;
}
else if (nums[middle] > target)
{
right = middle - 1;
}
else
{
return middle;
}
}
return -1;
}
27. 移除元素 (题目链接:力扣)
思路:看到题目描述说空间复杂度为O(1)就知道不能定义新数组,那么就用尾插法吧,时间复杂度为O(n^2),但比从头开始找删除元素要好些。
int removeElement(vector<int> &nums, int val)//尾插法删除数组元素
{
int size = nums.size();
for (int i = size - 1; i >= 0; i--)
{
if (nums[i] == val)
{
int j = i;
while (j < size - 1)
{
nums[j++] = nums[j + 1];
}
size--;
}
}
return size;
}
后面看到卡哥的解析重新拾起了双指针的方法,其实主要还是靠fastIndex指针每次找到需要保存下来的元素,slowIndex可以看做是新数组的尾指针,这种方法时间复杂度为O(n),而且很好理解,强烈推荐!
int removeElement(vector<int>& nums, int val){
int slowIndex = 0;
for(int fastIndex = 0; fastIndex < nums.size(); fastIndex++){
if(nums[fastIndex] != val){
nums[slowIndex++] = nums[fastIndex];
}
}
return slowIndex;
}
还有一种也是以前用过的更快捷的方法(但是会改变原有数组的相对位置),有点类似于以前学过的k值匹配?这种方法相当于一行田埂,有很多坑位,有的坑位里中了萝卜,有的坑位没种萝卜,现在要让萝卜从左向右连续不能间断。左边找坑位,右边找萝卜,把右边的萝卜往左边的坑位里填。
int removeElement(vector<int>& nums, int val) {
int leftIndex = 0;
int rightIndex = nums.size() - 1;
while (leftIndex <= rightIndex) {
while (leftIndex <= rightIndex && nums[leftIndex] != val){
++leftIndex;
}
while (leftIndex <= rightIndex && nums[rightIndex] == val) {
-- rightIndex;
}
if (leftIndex < rightIndex) {
nums[leftIndex++] = nums[rightIndex--];
}
}
return leftIndex;
}