代码随想录算法训练营day1

1.二分查找

题目链接:. - 力扣(LeetCode)

思路:二分查找

题解1:

class Solution {
public:
    int search(vector<int>& nums, int target) 
    {
        //定义左右值
        int left=0;
        int right=nums.size()-1;
        while(left<=right)
        {
            //定义二分法的中值
            int middle=left+((right-left)/2);
            if(nums[middle]<target)
            {
                left=middle+1;
            }
            else if(nums[middle]>target)
            {
                right=middle-1;
            }
            else
            {
                return middle;
            }
        }
        return -1;

    }
};

解释:在定义右值的时候我们取了nums.size()-1,这将target的索引值限制在了闭区间[left,right],当left=right时,区间[left,right]仍然有效,所以在while循环中应该使用<=。当nums[middle]<target时,target在右半部分,即[middle+1,right];当nums[middle]>target时,target在左半部分,即[left,middle-1]。

题解2:

class Solution {
public:
    int search(vector<int>& nums, int target) 
    {
        //定义左右值
        int left=0;
        int right=nums.size();
        while(left<right)
        {
            //定义二分法的中值
            int middle=left+((right-left)/2);
            if(nums[middle]<target)
            {
                left=middle+1;
            }
            else if(nums[middle]>target)
            {
                right=middle;
            }
            else
            {
                return middle;
            }
        }
        return -1;

    }
};

解释:在定义右值的时候我们取了nums.size(),这将target的索引值限制在了左闭右开区间[left,right),当left=right时,区间[left,right)无效,所以在while循环中应该使用<。当nums[middle]<target时,target在右半部分,即[middle+1,right);当nums[middle]>target时,target在左半部分,即[left,middle)。

复杂度分析:

时间复杂度:O(log n),因为影响循环次数的因素是int middle=left+((right-left)/2);这行代码

空间复杂度:O(1)

2.移除元素

题目链接:. - 力扣(LeetCode)

思路:快慢指针

题解:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        //定义快慢指针
        int fastindex=0;
        int slowindex=0;
        while(fastindex<nums.size())
        {
            if(nums[fastindex]!=val)
            {
                nums[slowindex++]=nums[fastindex++];
            }
            else
            {
                fastindex++;
            }
        }
        return slowindex;
    }
};

解释:

定义快慢指针,快指针每次循环递增一次,慢指针当快指针为索引的条件下的值不等于val时才会递增,一快一慢。注意while(fastindex<nums.size())不能写成while(fastindex<=nums.size()-1),这时当输入的数组为空数组时会报错。

for循环实现:

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        //定义快慢指针
        int fastindex=0;
        int slowindex=0;
        for(;fastindex<nums.size();fastindex++)
        {
            if(nums[fastindex]!=val)
            {
                nums[slowindex++]=nums[fastindex];
            }
        }
        return slowindex;
    }
};

复杂度分析:

时间复杂度:O(n)

空间复杂度:O(1)

3.有序数组的平方

题目链接:. - 力扣(LeetCode)

思路:双指针

题解:

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        int left=0;
        int right=nums.size()-1;
        int i=nums.size()-1;
        vector<int> result(nums.size(), 0);
        while(left<=right)
        {
            if(pow(nums[left],2)<=pow(nums[right],2))
            {
                result[i]=pow(nums[right],2);
                right--;
            }
            else
            {
                result[i]=pow(nums[left],2);
                left++;
            }
            i--;
        }
        return result;
    }
};

解释:

利用双指针的思想,从两头的数字开始比,比出最大的放在新数组最后面,以此类推,注意while循环里面的条件,当left和right相等时,我们还需要对其进行比较,所以应该是left<=right。

复杂度分析:

时间复杂度:O(n)

空间复杂度:O(n)

暴力解法(时间复杂度是 O(n + nlogn)):

class Solution {
public:
    vector<int> sortedSquares(vector<int>& nums) {
        for(int i=0;i<nums.size();i++)
        {
            nums[i]=pow(nums[i],2);

        }
        sort(nums.begin(),nums.end());
        return nums;
    }
};  

4.搜索插入位置

题目链接:. - 力扣(LeetCode)

思路:二分法

题解:

class Solution {
public:
    int searchInsert(vector<int>& nums, int target) {
        int left=0;
        int right=nums.size()-1;
        while(left<=right)
        {
            int middle=left+(right-left)/2;
            if(nums[middle]<target)
            {
                left=middle+1;
            }
            else if(nums[middle]>target)
            {
                right=middle-1;
            }
            else
            {
                return middle;
            }
        }
        return left;
    }
};

解释:

如果数组中存在value,则按照二分法查找方式去解决;如果不存在,为什么返回的是left?,因为在倒数第二次次循环的时候,假设left=a,则right=a+1,之后middle=a,left=a+1,即返回left。

复杂度分析:

时间复杂度:O(log n)

空间复杂度:O(1)

5.在排序数组中查找元素的第一个和最后一个位置

题目链接:. - 力扣(LeetCode)

思路:二分法

题解:

class Solution {
public:
    vector<int> searchRange(vector<int>& nums, int target) 
    {
        int a=FindLeftBorder(nums,target);
        int b=FindRightBorder(nums,target);
        if(nums.size()==0)
        {
            return {-1,-1};
        }
        else
        {
            return {a,b};
        }
    }

private:
    int FindLeftBorder(vector<int>& nums, int target) 
    {
        int left=0,right=nums.size()-1;
        while(left<=right)
        {
            int middle=left+(right-left)/2;
            if(nums[middle]==target)
            {
                if(middle==0||nums[middle-1]!=target)
                {
                    return middle;
                }
                else
                {
                    right=middle-1;
                }
            }
            else if(nums[middle]>target)
            {
                right=middle-1;
            }
            else
            {
                left=middle+1;
            }
        }
        return -1;
    }
    int FindRightBorder(vector<int>& nums, int target) 
    {
        int left=0,right=nums.size()-1;
        while(left<=right)
        {
            int middle=left+(right-left)/2;
            if(nums[middle]==target)
            {
                if(middle==nums.size()-1||nums[middle+1]!=target)
                {
                    return middle;
                }
                else
                {
                    left=middle+1;
                }
            }
            else if(nums[middle]>target)
            {
                right=middle-1;
            }
            else
            {
                left=middle+1;
            }
        }
        return -1;
    }
};

解释:

首先需要查找左右两边界,比如说左边界,类似于没用重复值的二分法,在nums[middle]==target的条件下我们需要进一步分析,比如说数组为[5,7,7,8,8,10],如果nums[middle-1]!=target即middle前一个的值不是8,则找到的是左边界,否则找到的是第二个8,真正的8在middle的左区间,需要进行right=middle-1。

复杂度分析:

时间复杂度:O(log n)

代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营中,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营中的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14天的训练营中,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论中还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15天的讨论中,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16天的讨论中,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值