代码随想录算法训练营第一天|704.二分查找、27. 移除元素、977.有序数组的平方

代码随想录算法训练营第一天|704.二分查找、27. 移除元素、977.有序数组的平方

704.二分查找

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果 target 存在返回下标,否则返回 -1。
你必须编写一个具有 O(log n) 时间复杂度的算法。

思路:二分法,先设置一下初始值
left = 0,
right = nums.size()-1
然后就是设置middle,即二分法的核心,取中点值
middle = (left + right) / 2
现在就是要进行while循环求解了,那么什么时候要跳出循环,即设置边界值,这里有两种情况

  • 左闭右闭,即循环内的middle可以取到左边界和右边界值
  • 左闭右开,即循环内的middle可以取到左边界值,但不能取到右边界值(左开右闭类似)

首先是第一种情况,那么就是while (left <= right),因为当left = right时middle = left = right,此时是合法可以取到的
当nums[middle] > target时,即目标值在中点左边,更新右边界值,
right = middle - 1(因为此时的nums[middle]不是解)
当nums[middle] < target时,同理,left = middle + 1
再更新下middle = (left + right) / 2

然后是第二种情况,那么就是while (left < right),因为当left = right时middle = right,但因为我们右开,不能取到右边界值,所以不合法,因此left不能等于right
当nums[middle] > target时,即目标值在中点左边,更新右边界值,
right = middle(此时nums[middle]不是解,且我们不能取到右边界值,所以直接是right = middle)
当nums[middle] < target时,即目标值在中点右边,更新左边界值,
left = middle + 1(这里是左闭,nums[middle]不是解,所以要加1)
再更新下middle = (left + right) / 2

但是第二个情况下有一种特殊情况需要特别处理,就是只有一个数的时候,比如[5],此时left = 0, right = 0,无法进入循环体,所以我们这里多加个语句判断下初始的右边界值是否=target即可

// 左闭右闭
class Solution {
    public:
        int search(vector<int>& nums, int target) {
            int left_index = 0;
            int right_index = nums.size() - 1;
            int middle = (left_index + right_index) / 2;
            while (left_index <= right_index) {
                if (nums[middle] == target)
                    return middle;
                else if (nums[middle] > target) {
                    right_index = middle - 1;
                } else {
                    left_index = middle + 1;
                }
                middle = (left_index + right_index) / 2;
            }
            return -1;
        }
};
// 左闭右开
class Solution {
    public:
        int search(vector<int>& nums, int target) {
            int left_index = 0;
            int right_index = nums.size() - 1;
            int middle = (left_index + right_index) / 2;
            if (nums[right_index] == target)
                return right_index;
            while (left_index < right_index) {
                if (nums[middle] == target) {
                    return middle;
                } else if (nums[middle] > target) {
                    right_index = middle;
                } else {
                    left_index = middle + 1;
                }
                middle = (left_index + right_index) / 2;
            }
            return -1;
        }
};

27. 移除元素

给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素。元素的顺序可能发生改变。然后返回 nums 中与 val 不同的元素的数量。

思路:

  • 暴力解法:两层循环,外层循环遍历一遍整个数组,当遇到val时进行内层循环,将val后面的元素都往前推一格
  • 双指针法,定义fastindex和slowindex,fastindex遍历一遍整个数组,当元素不等于val时用slowindex存储该元素,当元素等于val时跳过该元素

代码:

// 暴力解法
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int size = nums.size();
        for (int i = 0; i < size; i++) {
            if (nums[i] == val) {
                for (int j = i+1; j < size; j++) {
                    nums[j-1] = nums[j]; 
                }
                size--;
                i--;
            }
        }
        return size;
    }
};
//双指针法
class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int slowindex = 0;
        for (int fastindex = 0; fastindex < nums.size(); fastindex++) {
            if (nums[fastindex] != val) {
                nums[slowindex++] = nums[fastindex];
            }
        }
        return slowindex;
    }
};

977.有序数组的平方

给你一个按 非递减顺序 排序的整数数组 nums,返回 每个数字的平方 组成的新数组,要求也按 非递减顺序 排序。

思路:双指针法,slowindex = 0, fastindex = nums.size()-1,一个指向最左边,另一个指向最右边,然后创建一个新数组,不断比较slowindex和fastindex指向元素的平方谁大,大的那个元素值存进新数组,然后更新指向大元素的指针。注意临界条件是
while (slowindex <= fastindex)

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int slow_index = 0;
        int fast_index = nums.size() - 1;
        int size = nums.size();
        vector<int> array(size);
        while (slow_index <= fast_index) {
            int left = nums[slow_index];
            int right = nums[fast_index];
            size--;
            if (left*left < right*right) {
                array[size] = right*right;
                fast_index--;
            } else {
                array[size] = left*left;
                slow_index++;
            }
        }
        return array;
    }
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值