算法随想录打卡第一天|704. 二分查找、27. 移除元素

704. 二分查找 - 力扣(LeetCode)

自己的解法是这样的,超出了时间限制,现在觉得应该是在mid的计算中出了问题。

然后在mid的转换中没有right减去1或者left加上1。这两点的问题。

自己很习惯的方式是左闭合加上右闭合。可以省去很多对于临界值忘记考虑的麻烦。

超时代码贴出:

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

改进后的代码。代码是一个很抠细节的东西。

public static int search(int[] nums, int target) {
        int len = nums.length;
        int left = 0;
        int right = len - 1;
        //左闭合右闭合
        while (left <= right) {
            int mid = left + (right - left) / 2;//防止想加以后溢出(left + right) / 2;
            if (nums[mid] == target) {
                return mid;
            } else if (nums[mid] < target) {
                left = mid + 1;//挪一位mid;
            } else if (nums[mid] > target) {
                right = mid - 1;//挪一位mid;
            }
        }
        return -1;
    }

27. 移除元素 - 力扣(LeetCode)

这题真的是小题大做了,改了很多版本以后,边界问题得不到解决。最终觉得不太适合左右端点往中间移动的双指针这样的模式。适合快慢双指针。

public int removeElement(int[] nums, int val) {
        int left = 0;
        int len = nums.length;
        int right = len - 1;
        int count = 0;
        // 需要找的最多次数就是len次,len从前往后找,
        // 找到以后和right对调,对调以后right左移动一个单位
        // 有一个极限情况,左边不等于val时,右边刚好等于val
        // 左边发现和val相等的元素时,元素是交换
        while (left <= right) {
            if (nums[left] != val) {
                left++;
                if (nums[right] == val) {
                    right--;
                    count++;
                }
            } else {
                count++;
                //交换
                int temp = nums[left];
                nums[left] = nums[right];
                nums[right] = temp;
                left++;
                right--;
            }
        }
        return count;
    }

快慢双指针的方法:

这里的++i和i++结合运用的非常巧妙,感觉跟我这个二分法的mid没有前移一位或者后移一位我在这里犯了同样的错误。i是快指针,快指针找到目标值以后直接赋值给慢指针的位置。

但是我考虑到一个慢指针原来的值被丢弃的问题。

后来想到了,因为慢指针所到之处,快指针肯定都经过了,所以,需要的值肯定都已经存好了,所以不会有这个问题。也不需要追加一个数组作为内存开销。

public static int removeElement(int[] nums, int val) {
        int size = nums.length;
        int cnt = 0;
        for(int i = 0;i < size; ++i){
            if(nums[i] != val){
                nums[cnt++] = nums[i];
            }
        }
        return cnt;
    }

 

posted @ 2024-05-22 12:57  haha77-77  阅读(18)  评论(0)    收藏  举报