第一题:二分搜索法,题目不难,主要注意二分法的区间划分有两种情况:左闭右闭与左闭右开。
class Solution {
public:
#左闭右闭
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)
right = middle - 1;
else if(nums[middle] < target)
left = middle + 1;
else return middle;
}
return -1;
}
};
class Solution {
public:
#左闭右开
int search(vector<int>& nums, int target) {
int left = 0;
int right = nums.size();
while(left < right){
int middle = (left + right)/2;
if(nums[middle] > target)
right = middle;
else if(nums[middle] < target)
left = middle + 1;
else return middle;
}
return -1;
}
};
第二题是搜索插入位置,第一种解法是纯纯的暴力解,找到第一个大于等于target的数组下标。复杂度不满足要求,但是能通过。
class Solution {
public:
int searchInsert(vector<int>& nums, int target) {
for(int i = 0; i < nums.size(); i++){
if(nums[i] >= target) #找到第一个大于等于target的值下标
return i;
}
return nums.size();
}
};
第二种是利用二分法,若target在数组中,则直接返回下标,若不在数组中,则返回right+1。
class Solution {
public:
int searchInsert(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)
right = mid-1;
else if (nums[mid]<target)
left = mid + 1;
else return mid;
}
return right + 1;
}
};
第三题是在排序数组中查找元素的第一个和最后一个位置。利用二分法找到第一个和最后一个元素位置。
class Solution {
public:
vector<int> searchRange(vector<int>& nums, int target) {
int first = -1;
int last = -1;
int left = 0;
int right = nums.size() - 1;
//寻找第一个左边界
while(left <= right){//左闭右闭
int mid = (left + right)/2;
if(nums[mid] == target){
first = mid;
right = mid - 1;
}
else if(nums[mid] > target)
right = mid - 1;
else if(nums[mid] < target)
left = mid + 1;
}
//寻找最后一个右边界
int left1 = 0;
int right1 = nums.size() - 1;
while(left1 <= right1){
int mid = (left1 + right1)/2;
if(nums[mid] == target){
last = mid;
left1 = mid + 1;
}
else if(nums[mid] > target)
right1 = mid - 1;
else if(nums[mid] < target)
left1 = mid + 1;
}
return {first, last};
}
};
第四题是移除元素,先用暴力法试试水:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int size = nums.size();
for(int i = 0; i < size; i++){
if(nums[i] == val){
for(int j = i; j < size - 1; j++)
nums[j] = nums[j+1];
size--;
i--;#防止有多个val时被跳过
}
}
return size;
}
};
方法二使用双指针法,fast指针指示新数组元素,slow指针指示新数组元素对应下标,每遍历到一个非val元素,更新一次slow。
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int slow = 0;
for(int fast = 0; fast < nums.size(); fast++){
if(nums[fast] != val){
nums[slow] = nums[fast];
slow++;
}
}
return slow;
}
};
第五题是有序数组的平方,可以先平方再排序。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
for(int i=0; i < nums.size(); i++)
nums[i] = nums[i]*nums[i];
sort(nums.begin(), nums.end());
return nums;
}
};
第二种方法是双指针法,考虑到平方数的最大值一定位于数组的两侧,用i,j指示数组的两侧。
class Solution {
public:
#双指针法
vector<int> sortedSquares(vector<int>& nums) {
int k = nums.size()-1;
vector<int> result(nums.size(), 0);
for(int i=0, j=nums.size()-1;i<=j;){
if(nums[i]*nums[i] < nums[j]*nums[j]){
result[k] = nums[j]*nums[j];
k--;
j--;
}
else{
result[k] = nums[i]*nums[i];
k--;
i++;
}
}
return result;
}
};