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

704 使用二分法的前提是数组元素本身是有序的,同时数组中还应无重复元素,因为一旦存在重复元素,使用二分法返回的数组下标可能不是唯一的。
二分法有两种写法,一种是左闭右闭,第二种是左闭右开。两种方法主要的区别主要是边界处理不同。
左闭右闭:[left,right],left = 0,right = size-1。while中的循环条件应该是left<=right,根据数组值大小与目标值大小情况,每次循环将目前的数组缩小到原来的一半。时间复杂度O(log2N)。 middle = left + (right - left) / 2。
左闭右开:[left,right),left = 0,right = size。因为数组元素下标从零开始,此时right的下标数是无效的。while循环的条件是left<right。左指针变化:left = middle+1;right = middle。middle = left + (right - left) / 2。
27 移除数组中的元素
方法一:(暴力解)
使用两个for循环即可,第一个循环用来遍历数组,第二个for循环用来移动后续元素。

点击查看代码
for(int i=0;i<numsSize;i++){
    if(val==nums[i]){
         for(int j=i;j<numsSize-1;j++){
            nums[j]=nums[j+1];
        }
        i--;
        numsSize=numsSize-1;
    }
   }
如上代码,暴力解中有两个点需要注意,其一:移动的过程中,需要将遍历数组的i进行回退,因为移动完成后变量i所在的元素实际上是新的元素,需要重新进行判断。其二:题设中要求我们返回删除后的数组元素长度,我们在改变数组元素长度的变量时要注意最后更改,以防出现改变变量后续仍使用该变量的问题。 方法二:(双指针) 双指针即使用快慢指针,快指针用来寻找删除后数组的元素,即非val,慢指针用来承接快指针找的的元素。最后返回slow的值,即为数组长度。
点击查看代码
   int slow=0,n = numsSize;
   for(int fast=0;fast<n;fast++){
    if(nums[fast]!=val){
        nums[slow++] = nums[fast];
        }
   }
   return slow;
}
细节理解:该解法利用快指针遍历,若遇到非val,则快指针移动,慢指针移动,如遇到val,则快指针移动,慢指针不移动,慢指针停留位置,即为下次非val填充值。且最后slow停留位置就是数组长度,因为nums[slow++] = nums[fast]先使用slow,再对slow进行增加,slow停留处是需要填充值的位置,前面均为删除后的数组元素,巧合slow值即为数组长度。 977 有序数组的平方 本题所给的数组是一个非递减的数组,题设要求将所有元素进行平方,且平方后的数组元素进行非递减的排列。最容易想到的方法自然是将每个元素都进行平方然后进行排序,时间复杂度为O(n²)。第二个方式就是使用双指针,时间复杂度O(n),整体的思路是将两个指针分别起始数组的头和尾,因为当前平方最大值只有可能在这两个位置出现,所以我们将两个元素分别平方,进行比较,将最大值放入到更新数组的末尾,如最大值出现在头指针,则头指针向左移,若出现在尾指针则右移。代码如下:
点击查看代码
  int p=0;
    int q=numsSize-1;
    *returnSize = numsSize; 
    int *ans  = (int *)malloc(sizeof(int)*numsSize);
    for(int index = numsSize-1;index>=0;index--){
        int lval = nums[p]*nums[p];
        int rval = nums[q]*nums[q];
        if(lval>=rval){
            ans[index] = lval;
            p++;
        }else{
            ans[index]  = rval;
            q--;
        }
    }
    return ans;
posted @ 2026-02-25 11:26  Wdre  阅读(1)  评论(0)    收藏  举报