当前位置:   article > 正文

代码随想录day1 Java版本

代码随想录day1 Java版本

学习内容为二分查找和双指针

二分查找

力扣704

  1. class Solution {
  2. public int search(int[] nums, int target) {
  3. int i = 0;
  4. int j = nums.length - 1;
  5. while(i <= j) {
  6. int mid = (i + j) >> 1;
  7. if (target > nums[mid])i = mid + 1;
  8. else if (target < nums[mid]) j = mid - 1;
  9. else return mid;
  10. }
  11. return -1;
  12. }
  13. }

注意点:区间

对于左闭右闭区间,也就是[left, right]

        1.while (left <= right) 要使用 <= ,因为left == right是有意义的

        2.目标值在mid左侧时,right = mid-1而不是mid

对于左闭右开区间,也就是[left, right)

        1.while (left < right) 要使用 < ,因为left == right没有意义

        2.目标值在mid左侧时,right = mid而不是mid - 1,因为下一个区间不会比较right处的值

双指针

力扣27 移除元素

给定一个数组和目标值val,要求原地移除数组中所有值等于val的元素,返回数组长度

  1. class Solution {
  2. public int removeElement(int[] nums, int val) {
  3. int j = nums.length;
  4. int i = 0;
  5. while(i < j){
  6. if(nums[i] == val){
  7. nums[i] = nums[j - 1];
  8. j --;
  9. }else{
  10. i ++;
  11. }
  12. }
  13. return i;
  14. }
  15. }

 双指针即通过一快一慢两个指针来减少暴力算法的时间复杂度。

相关练习 二分法部分

力扣35 搜索插入位置

关于此题,要插入的位置就是首个大于target的下标。我们使用左闭右闭区间,当最后跳出循环的时候,一定是left大于right,那么上一步就一定会是left == right。如果 (此刻left == right)

(1)因为right - 1导致left > right, 则说明nums[right]是大于target的,所以此刻的right(跳出循环后的right + 1)(也就是left)就是要插入的位置。

(2)因为left + 1导致left > right,说明nums[left](nums[right])是小于target的,所以left + 1后的下标,也就是新的left的下标是要插入的位置

综上,当最后跳出循环后,要插入的位置为left

  1. class Solution {
  2. public int searchInsert(int[] nums, int target) {
  3. int i = 0;
  4. int j = nums.length - 1;
  5. while (i <= j){
  6. int mid = (i + j) >>> 1;
  7. if (nums[mid] < target) i = mid + 1;
  8. else if (nums[mid] > target) j = mid - 1;
  9. else return mid;
  10. }
  11. return i;
  12. }
  13. }

力扣34 查找元素第一个位置和最后一个位置

思路就是两次二分查找分别找到第一个位置和最后一个位置。

  1. class Solution {
  2. public int[] searchRange(int[] nums, int target) {
  3. if(nums.length == 0){
  4. return new int[]{-1, -1};
  5. }
  6. int first = findFirstPosition(nums, target);
  7. if(first == -1){
  8. return new int[]{-1, -1};
  9. }
  10. int last = findLastPosition(nums, target);
  11. return new int[]{first, last};
  12. }
  13. private int findFirstPosition(int[] nums, int target){
  14. int i = 0;
  15. int j = nums.length - 1;
  16. while(i < j){
  17. int mid = (i + j) >>> 1;
  18. if(nums[mid] < target){
  19. // 我们要在[mid+1,j]中继续二分查找
  20. i = mid + 1;
  21. }
  22. else if(nums[mid] == target){
  23. // 我们要在[i,mid]继续查找
  24. j = mid;
  25. }
  26. else{
  27. // 我们要在[i,mid-1]继续查找
  28. j = mid - 1;
  29. }
  30. }
  31. if(nums[i] == target){
  32. return i;
  33. }
  34. return -1;
  35. }
  36. private int findLastPosition(int[] nums, int target){
  37. int i = 0;
  38. int j = nums.length - 1;
  39. while(i < j){
  40. int mid = (i + j + 1) >>> 1;
  41. if(nums[mid] < target){
  42. // 我们要在[mid+1,j]查找
  43. i = mid + 1;
  44. }
  45. else if(nums[mid] == target){
  46. // 我们要在[mid,j]继续寻找
  47. i = mid;
  48. }
  49. else{
  50. // 我们要在[i,mid-1]继续寻找
  51. j = mid - 1;
  52. }
  53. }
  54. return i;
  55. }
  56. }

本题也可以使用左闭右闭区间的做法,用一个变量单独记录最左或者最右位置

力扣69 x的平方根

  1. class Solution {
  2. public int mySqrt(int x) {
  3. long i = 0;
  4. long j = x;
  5. while (i <= j) {
  6. long mid = (i + j) >>> 1;
  7. if (mid * mid > x) j = mid - 1;
  8. else if (mid * mid == x)return (int)mid;
  9. else i = mid + 1;
  10. }
  11. return (int)j;
  12. }
  13. }

还是找边界,即可以找mid*mid大于x的左边界(首个大于x的mid*mid,那么mid-1就是我们要找的结果),也可以是mid*mid<x的右边界(最后一个小于x的mid*mid,mid就是我们要找的结果),类似力扣35证明过程,可以证明,i-1或者j就是最后我们要的结果。 

力扣367 有效的完全平方数

  1. class Solution {
  2. public boolean isPerfectSquare(int num) {
  3. long left = 0;
  4. long right = num;
  5. while (left <= right) {
  6. long mid = (left + right) >>> 1;
  7. if (mid * mid < num) {
  8. left = mid + 1;
  9. } else if (mid * mid > num) {
  10. right = mid - 1;
  11. } else return true;
  12. }
  13. return false;
  14. }
  15. }
相关练习 双指针部分

 26 删除有序数组中的重复项

 与例题双指针类似。相同方向双指针,i在前,j在后指向下一类数字,当j找到位置后,令i+1并赋值,直到j到头为止(这里j可以一位一位地加而不是内圈的while循环,就不需要break跳出了)

  1. class Solution {
  2. public int removeDuplicates(int[] nums) {
  3. int i = 0;
  4. int j = 0;
  5. while (j < nums.length) {
  6. while (j < nums.length && nums[i] == nums[j]) {
  7. j ++;
  8. }
  9. if (j >= nums.length) break;
  10. i ++;
  11. nums[i] = nums[j];
  12. }
  13. return i + 1;
  14. }
  15. }

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

闽ICP备14008679号