代码随想录算法训练营第一天 | 704. 二分查找 、27. 移除元素

704.二分查找

1.Thought:

循环遍历数组元素,找到目标记录并返回下标i,若未找到,则返回-1.(注意应用有序、无重复)

2.实践:

2.1左闭右闭:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() - 1;
while (left <= right) {
int mid = (left + right) / 2;
if (nums[mid] == target) {
return mid;
}
else if (nums[mid] < target) {
left = mid + 1;
}
else if (nums[mid] > target) {
right = mid - 1;
}
}
return -1;
}
};

2.2左闭右开

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size() ;
while (left < right) {
int mid = (left+right)/2;
if (nums[mid] < target) {
left = mid + 1;
}
else if (nums[mid] > target) {
right = mid;
}
else
return mid;
}
return -1;
}
};

3.总结:

3.1 :

有序不重复数组应想到二分法

3.2 :

二分法包含左闭右闭与左闭右开,注意循环结束判断条件,以及右端点的选取

27、移除元素

1.Thought:

遍历整个数组,遇到目标元素将其用后一个不等于他的元素顶替。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len = nums.size();
for (int i = 0; i < nums.size(); i++) {
int j = i;
if (nums[j] == val) {
while (nums[j + 1] == val) {
j++;
}
nums[i] = nums[j + 1];
len--;
}
i++;
}
return len;
}
};

修改后:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len = nums.size();
int i = 0;

while (i < len) {
if (nums[i] == val) {
nums[i] = nums[len - 1];
len--;
} else {
i++;
}
}
return len;
}
};

在这个方法中,当发现当前元素等于 val 时,将最后一个元素复制到当前位置,同时减小数组长度。由于我们将最后一个元素复制到当前位置,所以不需要担心数组的顺序问题。(即将目标元素移到最后)

2.双指针法:

思路:使用两个指针,第一个用来遍历数组,第二个用于生成目标数组。如果遍历到非目标值,则继续,否则将非目标值加到生成数组中,其指针向后加一。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int len = nums.size();
int n=0;
for (int i = 0; i < len; i++) {
if (nums[i] != val) {
nums[n] = nums[i];
n++;
}
}
return n;
}
};