代码随想录算法训练营第一天|Day1数组基础

704. 二分查找

题目链接:https://leetcode.cn/problems/binary-search/

文章讲解:https://programmercarl.com/0704.%E4%BA%8C%E5%88%86%E6%9F%A5%E6%89%BE.html

视频讲解:https://www.bilibili.com/video/BV1fA4y1o715

我的解题思路

  • 该题使用二分法解答。
  • 使用二分的原因:该数组为升序
int search(int* nums, int numsSize, int target) {
    int left=0;
    int right=numsSize-1;
    while(left<=right){
        int mid=(left +right )/2;
        if(nums[mid]==target ){
            return mid;
        }
        else  if(nums[mid]>target){
            right=mid-1;
        }
        else if(nums[mid]<target){
            left=mid+1;
        }
        
    }
    return -1;
}

学习反思 

看完讲解才意识到区间的问题,我以前都是用举例子的方式来写,相对来说耗费时间更多,但是按这种分完后会快很多。

  • 第一种--左闭右闭区间

    思考:

    • 假设在 nums = [0, 1, 2,] 中查找1。由于是左闭右闭区间,需要包含 0 与 2 [0, 2],因此 left 指针为 0,right 指针为 2, 即为len(nums) - 1.

    • 在 while 循环中,若查找到 [1, 1],left == right 是可以满足区间定义的,因此 while left <= right。当进行if else的判断的时候,mid就会已经被判断了,此时直接都进行 +1 或者 -1的操作即可。

  • 第二种--左闭右开区间

    思考:

    • 同样假设在 nums = [0, 1, 2, ] 中查找1。由于是左闭右开区间,需要包含 0 与 2  [0, 3) ,因此 left 指针为 0,right 指针为 3, 即为len(nums).
    • 在 while 循环中,若查找到 [1, 1),等于1又小于1是矛盾的,无法满足区间定义,因此 while(left < right)。当进行if else的判断的时候,mid一般根据写法指向中间偏左的位置,比如首先指向1。判断之后对于左边来说是[0, 1),对于1右边来说是[2, 3),所以left = mid + 1,right = mid。

根据第二种思路写出的代码

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

27. 移除元素

题目链接:https://leetcode.cn/problems/remove-element/

文章讲解:https://programmercarl.com/0027.%E7%A7%BB%E9%99%A4%E5%85%83%E7%B4%A0.html

视频讲解:https://www.bilibili.com/video/BV12A4y1Z7LP

我的解题思路

1.暴力解法(不做解释)

int removeElement(int* nums, int numsSize, int val) {  
    int i = 0;  
    int j = 0;  
    while (i < numsSize) {  
        if (nums[i] != val) {  
            nums[j] = nums[i];  
            j++;  
        }  
        i++;  
    }   
    return j;  
}  

2.快慢指针

双指针法(快慢指针法): 通过一个快指针和慢指针在一个for循环下完成两个for循环的工作。

定义快慢指针

  • 快指针:寻找新数组的元素 ,新数组就是不含有目标元素的数组
  • 慢指针:指向更新 新数组下标的位置
int removeElement(int* nums, int numsSize, int val) {
    int slow=0;
    for(int fast=0;fast<numsSize;fast++){
        if(nums[fast]!= val){
            nums[slow++]=nums[fast];
        }
    }
    return slow;
}

学习反思 

虽然知道双指针法(快慢指针法)在数组和链表的操作中是非常常见的,但这道题还是没有办法立刻想到这种思路。

977.有序数组的平方 

题目链接:https://leetcode.cn/problems/squares-of-a-sorted-array/

文章讲解:https://programmercarl.com/0977.%E6%9C%89%E5%BA%8F%E6%95%B0%E7%BB%84%E7%9A%84%E5%B9%B3%E6%96%B9.html

视频讲解: https://www.bilibili.com/video/BV1QB4y1D7ep

我的解题思路

1.暴力解法(但其实根据时间复杂度要求暴力解法是不符合的,但我最先想到的是暴力解法)

//先算出每个的平方
int* sortedSquares(int* nums, int numsSize, int* returnSize) {  
    int* result = (int*)malloc(sizeof(int) * numsSize);  
    *returnSize = numsSize;  
    for (int i = 0; i < numsSize; i++) {  
        result[i] = nums[i] * nums[i];  
    }    
    bubbleSort(result, numsSize);  
    return result;  
}  
//再用冒泡排序
void bubbleSort(int* arr, int n) {  
    int i, j, temp;  
    for (i = 0; i < n-1; i++) {  
        for (j = 0; j < n-i-1; j++) {  
            if (arr[j] > arr[j+1]) {  
                temp = arr[j];  
                arr[j] = arr[j+1];  
                arr[j+1] = temp;  
            }  
        }  
    }  
}  
  

2.双指针法

int* sortedSquares(int* nums, int numsSize, int* returnSize) {  
    *returnSize = numsSize;  
    int* result = (int*)malloc(sizeof(int) * numsSize);  
    int left = 0, right = numsSize - 1, index = numsSize - 1;  
  
    while (left <= right) {  
        int leftSquare = nums[left] * nums[left];  
        int rightSquare = nums[right] * nums[right];  
  
        if (leftSquare > rightSquare) {  
            result[index] = leftSquare;  
            left++;  
        } else {  
            result[index] = rightSquare;  
            right--;  
        }  
        index--;  
    }  
  
    return result;  
}  

学习反思 

对双指针法更加熟练了。

总结

第一次写博客,花费了较长时间,但是感觉写完以后脑海中的知识更具象化了,记忆更清晰了,希望能在之后的过程中坚持下去!!!

第二十二天的算法训练营主要涵盖了Leetcode题目中的三道题目,分别是Leetcode 28 "Find the Index of the First Occurrence in a String",Leetcode 977 "有序数组的平方",和Leetcode 209 "长度最小的子数组"。 首先是Leetcode 28题,题目要求在给定的字符串中找到第一个出现的字符的索引。思路是使用双指针来遍历字符串,一个指向字符串的开头,另一个指向字符串的结尾。通过比较两个指针所指向的字符是否相等来判断是否找到了第一个出现的字符。具体实现的代码如下: ```python def findIndex(self, s: str) -> int: left = 0 right = len(s) - 1 while left <= right: if s[left == s[right]: return left left += 1 right -= 1 return -1 ``` 接下来是Leetcode 977题,题目要求对给定的有序数组中的元素进行平方,并按照非递减的顺序返回结果。这里由于数组已经是有序的,所以可以使用双指针的方法来解决问题。一个指针指向数组的开头,另一个指针指向数组的末尾。通过比较两个指针所指向的元素的绝对值的大小来确定哪个元素的平方应该放在结果数组的末尾。具体实现的代码如下: ```python def sortedSquares(self, nums: List[int]) -> List[int]: left = 0 right = len(nums) - 1 ans = [] while left <= right: if abs(nums[left]) >= abs(nums[right]): ans.append(nums[left ** 2) left += 1 else: ans.append(nums[right ** 2) right -= 1 return ans[::-1] ``` 最后是Leetcode 209题,题目要求在给定的数组中找到长度最小的子数组
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值