当前位置:   article > 正文

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

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

704.二分查找

1.左闭右闭

思路:left表示数组的第一个元素的下标,right表示数组的最后一个元素的下标,mid代表数组的中间元素的下标,如果arr[mid]<val(val表示要查找的值),那么left=mid+1;如果arr[mid]>val(val表示要查找的值),那么right=mid-1;如果arr[mid]==val,则返回mid的值。

注意,循环条件是left<=right,因为是左左闭右闭,所以如果left==right,就表示一个元素,这时也能查找,除非left>right,说明已经没有元素了。

2.左闭右开

跟左闭右闭的唯一区别是,因为是右开,所以最右边的元素是取不到的,所以最开始初始化right=nums.size(),同时,因为是右开,所以循环条件是left<right,因为left<right说明有超过1的元素个数,如果left>=right,是没有元素的,还要注意,如果arr[mid]>val(val表示要查找的值),那么right-1,那么right=mid,因为右边是取不到的,所以如果right=mid-1,就取不到mid左边的元素了

  1. class Solution {
  2. public:
  3. int search(vector<int>& nums, int target)
  4. {
  5. //左闭右闭
  6. // int left = 0;
  7. // int right = nums.size() - 1;
  8. // while (left <= right)
  9. // {
  10. // int middle = left + (right - left) / 2;
  11. // if (nums[middle] > target)
  12. // {
  13. // right = middle - 1;
  14. // }
  15. // else if (nums[middle] < target)
  16. // {
  17. // left= middle + 1;
  18. // }
  19. // else
  20. // {
  21. // return middle;
  22. // }
  23. // }
  24. // return -1;
  25. // }
  26. //左闭右开
  27. int left = 0;
  28. int right = nums.size() ;
  29. while (left < right)
  30. {
  31. int middle = left + (right - left) / 2;
  32. if (nums[middle] > target)
  33. {
  34. right = middle;
  35. }
  36. else if (nums[middle] < target)
  37. {
  38. left= middle + 1;
  39. }
  40. else
  41. {
  42. return middle;
  43. }
  44. }
  45. return -1;
  46. }
  47. };

27.移除元素

1.暴力解

直接来一个for循环遍历数组的所有元素,如果找到了要移除的元素,则将这个元素后面的元素依次覆盖前面的元素,即把它们一个个往前挪动。

2.双指针1(难)

设置pre=0;cur=0;将cur遍历,如果arr[i]!=val(要查找的值),那么arr[pre++]=arr[cur],即pre++,表示pre会往后面移动一位,如果arr[i]==val,那么只有cur移动,pre还在原来的位置,cur不断++,直到找到不是val的值,那么将该值赋值给pre所在的位置,这时候pre才可以继续往前移动,达到将不是val的值不断往前移动,实现覆盖的效果。

3.双指针2(难)

设置left=0;right=nums.size()-1;如果left<=right(注意,这里=是考虑如果left>right,因为left是一个一个动的,所以这时候left肯定在right的右边,那么这是left代表的就是数组的长度)&&arr[left]!=val,那么left可以不断往右移动,直到找到对应的val值,这时候,右边的指针(并不是指针,只是个比喻)right就可以开始移动了,只要它所指的值不是val,那么就可以不用移动,直接把这个值赋值给被删除元素的位置,然后right--就实现了把最右边不是val的值赋值给val原本所在的位置,并且这时候又会实现长度自动减一的结果;如果它所指的值是val,那么肯定要往左边移动,因为val本来就是要被删除的,right--其实就实现了删除右边多余的val的值。

  1. class Solution {
  2. public:
  3. int removeElement(vector<int>& nums, int val) {
  4. //暴力解
  5. // int size=nums.size();
  6. // for(int i=0;i<size;i++)
  7. // {
  8. // if(nums[i]==val)
  9. // {
  10. // for(int j=i+1;j<nums.size();j++)
  11. // {
  12. // nums[j-1]=nums[j];
  13. // }
  14. // i--;
  15. // size--;
  16. // }
  17. // }
  18. // return size;
  19. // }
  20. //双指针
  21. // int pre=0;
  22. // for(int i=0;i<nums.size();i++)
  23. // {
  24. // if(nums[i]!=val)
  25. // {
  26. // nums[pre++]=nums[i];
  27. // }
  28. // }
  29. // return pre;
  30. // }
  31. //双向指针
  32. int left=0;
  33. int right=nums.size()-1;
  34. while(left<=right)
  35. {
  36. while(left<=right&&nums[left]!=val)
  37. left++;
  38. while(left<=right&&nums[right]==val)
  39. right--;
  40. if(left<right)
  41. {
  42. nums[left++]=nums[right--];
  43. }
  44. }
  45. return left;
  46. }
  47. };

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/黑客灵魂/article/detail/959242
推荐阅读
相关标签
  

闽ICP备14008679号