Day01

Day01 代码随想录刷题

知识点:二分查找、双指针

一、LeetCode704.二分查找

1.解题思路

二分法查找首先要明确区间,根据区间不同有两种常用方法,第一种方法是左闭右闭[],第二种方法是左闭右开[)

2.代码实现

2.1 方法一:左闭右闭

因为左闭右闭,两侧的数据可能有效,当计算mid后,若mid所指的nums[mid]不是目标值target,则代表mid的数据nums[mid]无效,不能出现在两侧,所以需要对其进行加一或者减一的操作

返回值存在三种情况:

不存在target,R = L - 1,LR会出现反向超越情况

存在target,在中间

存在target,在两侧,R = L

# way 1 []
def lower_bound(nums, target):
    l, r = 0, len(nums) - 1
    while l <= r:
        mid = l + (r - l)//2
        if nums[mid] > target:
            r = mid - 1
        elif nums[mid] < target:
            l = mid + 1
        else:
            return mid
    return -1

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        return lower_bound(nums, target)

2.2 方法二:左闭右开

因为左闭右开,右侧的数据无效,左侧的数据可能有效,当计算mid后,若mid所指的nums[mid]不是目标值target,则代表mid的数据nums[mid]无效,故不能出现在左侧但可以出现在右侧,所以只有在左侧更新时需要加一,右侧更新不需要减一的操作。

返回值存在三种情况:

不存在target,R = L,LR会出现相等情况

存在target,在中间

存在target,在左侧,R = L + 1

# way 2 [)
def lower_bound2(nums, target):
    l,r = 0,len(nums)
    while l < r:
        mid = l + (r - l)//2
        if nums[mid] > target:
            r = mid
        elif nums[mid] < target:
            l = mid + 1
        else: 
            return mid
    return -1 

class Solution:
    def search(self, nums: List[int], target: int) -> int:
        return lower_bound2(nums, target)

该解法使用了二分法,时间复杂度O(log n),因为额外维护了3个指针,所以空间复杂度O(1)

二、LeetCode027.移除元素

1.解题思路

使用快慢指针,快指针j用来遍历数组的每个元素,慢指针i作为下标来更新数组。

2.代码实现

关键在于,当快指针j指向的值为 要保留的数时(!=val),将其值更新到慢指针i作为下标的数组中nums[i]

数组元素无法被删除,只能被覆盖

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        i = 0
        j = 0
        # # while循环法
        # while j < len(nums):
        #     if nums[j] != val:
        #         nums[i] = nums[j]
        #         i += 1
        #     j += 1

        # return i

        # for循环法
        for j in range(0,len(nums)):
            if nums[j] != val:
                nums[i] = nums[j]
                i+= 1
            j += 1
        return i

该解法额外设计了两个指针ij用来遍历整个列表,列表中每个元素最多被操作2次,总共最多2n次,所以时间复杂度O(n),因为额外维护了2个指针,所以空间复杂度O(1)

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

1.解题思路

要找targetnums数组中的左右边界,无非存在 3 种情况:

targetnums列表中存在target

targetnums列表中不存在target

target < nums[0]或者target > nums[n-1]

后2种情况可以通过以下代码排除:

if len(nums) == 0 or nums[0] > target or nums[-1] < target:
    return [-1,-1]

只剩第一种情况,我们需要利用两次二分法来确定左右边界,确定边界的二分法与普通二分法不同,如确定左边界:

nums[mid] == target时,程序不返回mid而是继续将区间向左压缩,所以是right = mid - 1

相反,确定右边界时,当nums[mid] == target时,执行right = mid + 1

两者这么做的原因是:当找到target时,不一定是最左或者最右的target,需要进一步查找。

2.代码实现

class Solution:
    # 二分法
    def leftMargin(self,nums,target):
        l, r = 0, len(nums) - 1
        while l <= r:
            mid = l + (r - l)//2
            if nums[mid] < target:
                l = mid + 1
            else:
                r = mid - 1
        if nums[l] == target:
            return l
        else:
            return -1

    def rightMargin(self,nums,target):
        l, r = 0, len(nums) - 1
        while l <= r:
            mid = l + (r - l)//2
            if nums[mid] <= target:
                l = mid + 1
            else:
                r = mid - 1
        if nums[r] == target:
            return r
        else:
            return -1


    def searchRange(self, nums: List[int], target: int) -> List[int]:
 
        # # 暴力解法
        # l = 0
        # r = len(nums) - 1
        # while l < r and (nums[l]!=target or nums[r]!=target):
        #     if nums[l] != target:
        #         l += 1
        #     if nums[r] != target:
        #         r -= 1
        # if l > r:
        #     return [-1,-1]
        # elif l == r:
        #     if nums[l] == target:
        #         return [l,r]
        #     else:
        #         return [-1,-1]
        # return [l,r]


        # 二分法
        if len(nums) == 0 or nums[0] > target or nums[-1] < target:
            return [-1,-1]
        return[self.leftMargin(nums,target),self.rightMargin(nums,target)]

该解法只用了2次二分法,所以时间复杂度还是O(logn),因为额外设计维护了几个指针,所以空间复杂度O(1)

四、LeetCode035.搜索插入位置

1.解题思路

还是二分法,while 循环的条件是left <= right

1.1 当数组中有值为target的元素时,按照普通的二分法,找到该值的索引后返回即可;

1.2 当数组中没有值为target的元素时,最后一次循环搜寻区间可能为一个或两个元素(数组元素个数为偶数时),即right = leftright = left + 1,这两种情况时都有mid = left

如果最后一次循环时mid所在位置的值大,即nums[mid] > target,则right = mid - 1结束循环,不影响left,且left的位置就是要插入的位置;

如果最后一次循环时mid所在位置的值小,即nums[mid] < target,则left = mid + 1结束循环,此时更新后的left的位置就是要插入的位置;

综上,若数组内没有值为target的元素,最后都只需要返回left的索引。

2.代码实现

只需要将普通二分法最后的return -1改为return left即可

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        # # 暴力解法
        # i = 0
        # j = 0
        # for j in range(0,len(nums)):
        #     if nums[j] >= target:
        #         return j
        #     j += 1
        # return j 

        # 二分法
        l = 0
        r = len(nums) - 1
        while l <= r:
            mid = l + (r -l)//2
            if nums[mid] < target:
                l = mid + 1
            elif nums[mid] > target:
                r = mid - 1
            else:
                 return mid
        return l

该解法在普通的二分法基础上只修改了返回值,所以时间复杂度还是O(logn),因为额外设计维护了几个指针,所以空间复杂度O(1)

### 苍穹外卖 Day01 课程内容概述 #### 项目初始化与环境搭建 在苍穹外卖项目的第一页(Day01),主要涉及的是项目的初始配置以及开发环境的搭建工作。这一步骤通常包括创建项目结构、引入必要的依赖库以及设置数据库连接等内容。 为了确保系统的稳定性和可扩展性,在此阶段会完成以下几项重要任务: - **Spring Boot 项目初始化**:通过 Spring Initializr 创建基础框架,选择合适的 Starter Dependencies 来支持后续的功能实现[^4]。 - **Maven 配置文件调整**:修改 `pom.xml` 文件中的版本号及相关插件配置,以便于管理外部资源和工具链集成[^5]。 #### 数据模型定义 针对业务逻辑的需求分析之后,紧接着就是数据表的设计及其对应的 Java 实体类编写过程。例如 Employee 表格将会被映射成一个名为 `Employee` 的 POJO (Plain Old Java Object),其中包含了诸如 id, username, password 等字段来表示每位雇员的基本资料信息[^6]。 此外还可能涉及到其他关联表格如 Department 或 Role ,它们之间可能存在一对多或者多对多的关系模式,这些都需要提前规划好并落实到具体的代码当中去。 ```java @Entity @Table(name="employee") public class Employee { @Id @GeneratedValue(strategy=GenerationType.IDENTITY) private Long id; private String name; // Getters and Setters omitted for brevity } ``` #### 控制器层接口声明 基于 RESTful API 设计理念下,控制器负责接收客户端请求并将参数传递给服务层处理后再返回响应结果。因此在这个部分里我们需要按照既定规则制定各个 HTTP 方法所对应的操作路径及其输入输出格式说明文档[^7]。 比如新增加一条记录可以采用 POST 请求方式;而如果要查询某个特定对象则应该利用 GET 加上唯一标识符作为附加条件等等... --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值