day01 打卡704. 二分查找,27. 移除元素

day01 打卡704. 二分查找,27. 移除元素

704.二分查找

704题目链接

1.第一次错误代码

class Solution {
    public int search(int[] nums, int target) {
        int min = 0;
        int max = nums.length;
        int mid = max / 2;
        while(min < max) {
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                min = mid + 1;
            } else if (nums[mid] > target) {
                max = mid - 1;
            }
        }
        return -1;
    }
}

2.debug后,发现问题

  • 最严重的问题是mid的值没有重新再赋值
  • 初始化max的值 和 跳出while的条件 没有考虑到,界限问题。我这里用的是左闭右闭的情况
  • mid = ( max + min ) / 2中( max + min )可能会超出int的上限值。需要改成mid =min+ ( max-min ) / 2或者mid=min+((max-min)>>1)
class Solution {
    public int search(int[] nums, int target) {
        int min = 0;
        int max = nums.length - 1;
        int mid = max / 2;
        while(min <= max) {
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                min = mid + 1;
            } else if (nums[mid] > target) {
                max = mid - 1;
            }
            mid = min + ( max - min ) / 2;
        }
        return -1;
    }
}

3.改进提高效率的地方: target 如果大于最大的 小于最小的 可以最开始的时候判断直接return -1。放35题改进了。

704的拓展之35.搜索插入位置

35题目链接

1.参考二分查找

class Solution {
    public int searchInsert(int[] nums, int target) {
        int left = 0 ; 
        int right = nums.length - 1;
        int mid;
        if (nums[0] >= target) {
            return 0;
        }
        if (nums[right] == target) {
            return right;
        }
        if (nums[right] < target) {
            return right + 1;
        }

        while (left <= right) {
            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 left;
    }
}

704的拓宽之34.

34题目链接

1.暴力解法,直接两次分开的循环得到开始位置和结束位置

class Solution {
    public int[] searchRange(int[] nums, int target) {
        int[] result = {-1, -1};
        for (int i = 0 ; i<nums.length ; i++) {
            if (nums[i] == target) {
                result[0] = i;
                break;
            }
        }
        for (int i = nums.length-1 ; i>=0; i--) {
            if (nums[i] == target) {
                result[1] = i;
                break;
            }
        }
        return result;
    }
}

2.二分查找左边和右边的界限。暂时有点疑问,后续再补

27.移除元素

27题目链接

1.暴力解法。通过两层的循环,讲后面的数值覆盖前面的

class Solution {
    public int removeElement(int[] nums, int val) {
        int n = nums.length;
        int count = 0;
        int i = 0;
        while (i<n-count) {
            if (nums[i] == val) {
                count++;
                for (int j = i+1 ; j<n; j++) {
                    nums[j-1] = nums[j];
                }
            } else {
                i++;
            }
        }
        return n - count;
    }
}

2.快慢指针。快指针是不包含目标元素的下标;慢指针是更新数组的下标

class Solution {
    public int removeElement(int[] nums, int val) {
        int slow = 0;
        for (int fast = 0 ; fast<nums.length ; fast++) {
            if (nums[fast] != val) {
                nums[slow] = nums[fast];
                slow++;
            }
        } 
        return slow;
    }
}

3.相向双指针。左指针从0下标开始,右指针从n-1下标开始。右指针需要一直保持不等于val的最右边值的下标,左指针不断增加的过程中,一旦遇到了等于val的值,就需要重新赋值,重新赋值的值是此时右指针对应的值(肯定不等于val),并且左指针需要减小,并且保证最右边不等于val。

class Solution {
    public int removeElement(int[] nums, int val) {
        int n = nums.length;
        int left = 0;
        int right = n-1;
        // 保证最右边不等于val
        while(right >= 0 && nums[right] == val) right--;
        while(left <= right) {
            // 左指针遇到了等于val的值,就需要重新赋值
            if (nums[left] == val) {
                nums[left] = nums[right];
                right--;
            }
            left++;
            // 保证最右边不等于val
            while(right >= 0 && nums[right] == val) right--;
        }
        return left;
    }
}

参考资料

代码随想录

posted @ 2023-03-01 20:51  zzzzzzsl  阅读(327)  评论(0)    收藏  举报