704.二分查找
思路:首尾双指针比较中间元素,若target小于中间则在左边区域 ,否则在右边区域,有一点递归思想。
第一次解答:
class Solution {
public:
int search(vector<int>& nums, int target) {
int n=nums.size();
int middle=n/2;
int left=0;
int right=n-1;
while(left!=right){
if(target<=nums[middle]){return middle;}
if(target<nums[middle]){
right=middle;
middle=(left+middle)/2;
}else{
left=middle;
middle=(right+middle)/2;
}
}
return -1;
}
};
错误原因:if(target<=nums[middle]){return middle;}这里判断条件书写错误
第二次解答:
class Solution {
public:
int search(vector<int>& nums, int target) {
int n=nums.size();
int left=0;
int right=n-1;
while(left!=right){
int middle=(left+right)/2;
if(target==nums[middle]){return middle;}
if(target<nums[middle]){
right=middle;
}else{
left=middle;
}
}
return -1;
}
};
出现超时原因:问题出在 left
和 right
的更新逻辑上。具体来说,当 target
不在数组中时,left
和 right
的更新可能会导致它们永远无法相等,从而陷入无限循环。会出现不管怎么更新 left一直等于middle,从而进入死循环。突破点在于每次更新都要缩小范围。
正确解答:
class Solution {
public:
int search(vector<int>& nums, int target) {
int n=nums.size();
int left=0;
int right=n-1;
while(left<=right){
int middle = left+(right - left) / 2; // 防止溢出
if(target==nums[middle]){return middle;}
if(target<nums[middle]){
right=middle-1; //这里缩小范围
}else{
left=middle+1; //这里缩小范围
}
}
return -1;
}
};
提示:直接使用 (left + right) / 2
来计算 middle
可能会导致整数溢出,尤其是当 left
和 right
的值非常大时。例如,如果 left
为 INT_MAX
,right
为 INT_MAX
,直接加法 left + right
会超出整数类型的范围。比如 left = 2147483647
(即 INT_MAX
),right = 2147483647
。直接使用 middle = (left + right) / 2
会得到:4294967294 会超出整数范围
因此推荐用:middle = left+(right - left) / 2;
27. 移除元素
解答思路:
遍历nums中的所有元素,每次遍历k都加1,如果出现当前元素等于val,将当前元素之后的所有元素前移一格,然后k-1。
错误解答:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int k=0;
int length=nums.size();
for(int i=0;i<length;i++){
if(nums[i]==val){
for(int j=i;j<length-1;j++){
nums[j]=nums[j+1];
}
k--;
}
k++;
}
return k;
}
};
问题在于后面的元素前移后,应该继续从当前元素开始遍历,而且遍历长度也应该减1。
正确解答:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int k=0;
int length=nums.size();
for(int i=0;i<length;i++){
if(nums[i]==val){
for(int j=i;j<length-1;j++){
nums[j]=nums[j+1];
}
i--;length--; //这里的作用是让下次遍历仍然从当前位置开始,并且总的遍历长度减一
k--;
}
k++;
}
return k;
}
};
其他优秀解答:
class Solution {
public:
int removeElement(vector<int>& nums, int val) {
int k = 0;
for (int x : nums) {
if (x != val) {
nums[k++] = x;
}
}
return k;
}
};
作者:灵茶山艾府
链接:https://leetcode.cn/problems/remove-element/solutions/2802809/jian-dan-ti-jian-dan-zuo-pythonjavaccgoj-72bn/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
977.有序数组的平方
思路:第一种,求绝对值后排序
第二种,双指针 找绝对值最小的 然后从最小值的两端开始比较 ,这个思路实现起来太复杂了,还不如从最边边开始比较。
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int>ans(nums.size());
int left=0;
int right=nums.size()-1;
int maxIndex=nums.size()-1;
while(left<right){
if(abs(nums[left])<abs(nums[right])){
ans[maxIndex]=nums[right]*nums[right];
right--;
}
else{
ans[maxIndex]=nums[left]*nums[left];
left++;
}
maxIndex--;
}
return ans;
}
};
这种判断条件少了个等号 导致 第一个元素一直为0
正确解答:
class Solution {
public:
vector<int> sortedSquares(vector<int>& nums) {
vector<int>ans(nums.size());
int left=0;
int right=nums.size()-1;
int maxIndex=nums.size()-1;
while(left<=right){ //这里判断条件是小于等于
if(abs(nums[left])<abs(nums[right])){
ans[maxIndex]=nums[right]*nums[right];
right--;
}
else{
ans[maxIndex]=nums[left]*nums[left];
left++;
}
maxIndex--;
}
return ans;
}
};