代码随想录算法训练营Day 1 | 704. 二分查找、27. 移除元素

数组相关算法题的Python实现与思考

一、数组理论基础

文章链接:

知识点总结:

1. 数组在内存中的存储方式:

数组是存储在连续的内存空间相同类型数据的集合。通过下标索引获取下标对应的数据。 

2. 注意:1)下标从0开始;2)数组内存空间的地址连续

因为数组在内存空间地址连续,所以在增删元素的时候,需要移动其他元素的地址

3. 数组元素不可以删除,只能覆盖。

二、704.二分查找

题目链接:704. 二分查找 - 力扣(LeetCode)

文章链接:代码随想录

视频链接:手把手带你撕出正确的二分法 | 二分查找法 | 二分搜索法 | LeetCode:704. 二分查找_哔哩哔哩_bilibili

1. 看到题目的第一想法:

没有注意到题目要求使用二分查找,于是打算使用暴力解法,即按索引遍历数组每一个元素,如果元素等于target,则返回其下标。

2. 看完代码随想录的想法:

二分查找需要涉及到Python中的双指针问题:

左闭右闭区间法:

        1)初始化左指针left和右指针right,使其分别指向数组的头元素下标、尾元素下标;

        2)写while循环防止指针溢出,即左指针如果大于右指针就跳出循环;

        3)写出中间指针middle的更新公式:middle = left + (right - left) // 2 或者 middle = (left+right) // 2

                更加推荐第一个公式的写法,如果left和right非常大容易发生整数溢出,而公式一因为先计算出差值,所以相对更加安全。

                注意:指针指向的是下标索引,是整数类型,所以不能(左指针+右指针)/2

        4)比较middle对应的数组元素与target二者的大小:

                如果target等于该元素,则返回的下标就是middle;

                如果target大于该元素,说明target在右区间内,那么将left指针移动到middle+1处;

                如果target小于该元素,说明target在左区间内,那么将右指针移动到middle-1处;

        5)最后如果循环结束没有找到目标值,则返回-1。

左闭右开区间法:

注意更新右区间时,使其等于middle,其余同上。

3. 实现过程中遇到的困难:

        1)循环函数使用混乱

        2)指针定义模糊不清

        3)刻意区分元素个数的奇偶,导致代码逻辑复杂

        4)没有考虑抛出异常、以及指针溢出的情况

4. 今日收获:

1. Python双指针:

        1)对撞指针:一个从头到尾,一个从尾到头,相向而行-->left = 0, right = len(nums)-1

        2)快慢指针:一个指针移动速度快、一个指针移动速度慢,常用于环形链表-->fast, slow

2. Python循环体:

三、27.移除元素

1. 看到题目的第一想法:

        1)暴力解法:

        遍历数组每一个元素,如果发现其等于val,则循环后面的元素依次向前覆盖,每遇到一个等于val的元素就循环一次;

        但是不知道如何统计不等于val元素的数组大小,因为覆盖不会删除原来的元素,所以数组大小并没有改变,无法返回移除元素后的数组大小。

        2)快慢指针法:

        用快指针遍历数组每个元素,遇到元素等于val的值则continue跳过,遇到不等于val的值则将其放入新数组,最后统计新数组的大小并返回。

2. 看完代码随想录的想法:

        1)初始化快慢指针均指向数组索引0的位置,并且设置数组大小size = len(nums)

        2)以指针是否溢出作为循环条件,若快指针大于数组大小则跳出循环

        3)比较快指针指向元素是否等于val:                

                若不等于则慢指针+1;

                若等于则慢指针不变。

                一次循环结束快指针无论如何也+1,继续遍历下一个元素的值,并进行比较。

        4)最后返回慢指针的数值即可。

3. 实现过程中遇到的困难:

        1)不会灵活利用指针将其作为一个计数工具,只想到将它作为下标索引使用

        2)快慢指针使用时需要防止指针溢出数组长度,要对其进行size设置与限定

四、977.有序数组的平方

1. 看到题目的第一想法:

        使用对撞指针,初始化左指针和右指针分别在数组的头和尾,然后以左指针小于等于右指针为循环终止条件进入循环,然后比较头尾指针指向的元素平方的大小,选取值较大的优先纳入新数组。

2. 看完代码随想录的想法:

        1)设置对撞指针,初始化使其分别指向数组的头和尾;设置新数组的指针,指向数组尾部;

定义存放元素的新数组。

        2)以左指针小于等于右指针为循环终止条件进入循环。

        3)比较头尾指针指向的元素大小:

                如果left指针指向的元素平方更大,则将其加入新数组,并且左指针向右移动一位;

                如果right指针指向的元素平方更大,则将其加入新数组,并且右指针向左移动一位。

                一次循环结束,新数组的指针向左移动一位。

        4)最后返回新数组的大小。

3. 实现过程中遇到的困难:

        1)不知道如何定义新数组及其新指针:

res = [float('inf')] * len(nums)

        2)新指针的元素存放应该是从后往前、从大到小。

        3)左右指针完成循环一次的移动方向并不一样。

### 代码随想录算法训练营 Day20 学习内容与作业 #### 动态规划专题深入探讨 动态规划是一种通过把原问题分解为相对简单的子问题的方式来求解复杂问题的方法[^1]。 #### 主要学习内容 - **背包问题系列** - 背包问题是典型的动态规划应用场景之一。这类题目通常涉及给定容量的背包以及一系列具有不同价值和重量的物品,目标是在不超过总容量的情况下最大化所选物品的价值。 - **状态转移方程构建技巧** - 构建合适的状态转移方程对于解决动态规划问题是至关重要的。这涉及到定义好dp数组(或表格),并找到从前一个状态到下一个状态之间的关系表达式[^2]。 - **优化空间复杂度方法** - 对于某些特定类型的DP问题,可以采用滚动数组等方式来减少所需的空间开销,从而提高程序效率[^3]。 #### 实战练习题解析 ##### 题目:零钱兑换 (Coin Change) 描述:给定不同面额的硬币 coins 和一个总金额 amount。编写函数来计算可以凑成总金额所需的最少的硬币个数。如果没有任何一种硬币组合能组成总金额,返回 `-1`。 解决方案: ```python def coinChange(coins, amount): dp = [float('inf')] * (amount + 1) dp[0] = 0 for i in range(1, amount + 1): for coin in coins: if i >= coin and dp[i - coin] != float('inf'): dp[i] = min(dp[i], dp[i - coin] + 1) return dp[-1] if dp[-1] != float('inf') else -1 ``` 此段代码实现了基于自底向上的迭代方式解决问题,其中 `dp[i]` 表示达到金额 `i` 所需最小数量的硬币数目[^4]。 ##### 题目:完全平方数 (Perfect Squares) 描述:给出正整数 n ,找出若干个不同的 完全平方数 (比如 1, 4, 9 ...)使得它们的和等于n 。问至少需要几个这样的完全平方数? 解答思路同上一题类似,只是这里的“硬币”变成了各个可能的完全平方数值。 ```python import math def numSquares(n): square_nums = set([i*i for i in range(int(math.sqrt(n))+1)]) dp = [float('inf')] *(n+1) dp[0] = 0 for i in range(1,n+1): for sq in square_nums: if i>=sq: dp[i]=min(dp[i],dp[i-sq]+1); return dp[n]; ``` 这段代码同样运用了动态规划的思想去寻找最优解路径,并利用集合存储所有小于等于输入值的最大平方根内的平方数作为候选集[^5]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值