letcode刷题(2020.01.01--2020.01.10)

1.移除元素(2020.1.1)

题目描述:

给定一个数组 nums 和一个值 val,你需要原地移除所有数值等于 val 的元素,返回移除后数组的新长度。

不要使用额外的数组空间,你必须在原地修改输入数组并在使用 O(1) 额外空间的条件下完成。

元素的顺序可以改变。你不需要考虑数组中超出新长度后面的元素。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/remove-element
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

 

解题思路:

  1. 采用双指针,首先定义快指针j为0,慢指针i为0,传入的数字长度为length
  2. 使用while循环,如果j不小于length,跳出循环
  3. 如果快指针指定元素不等于val,将元素移动到慢指针位置。快慢指针同时加1。否则,快指针加1

代码实现:

class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
        length = len(nums)
        j = 0
        i = 0
        while j<length:
            if nums[j] != var:
                nums[i] = nums[j]
                i += 1
                j += 1
            else:
                j += 1
        res = length - (j - i)
        return res

2.搜索插入位置(2020.1.2)

题目描述:

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

你可以假设数组中无重复元素。

示例 1:

输入: [1,3,5,6], 5
输出: 2
示例 2:

输入: [1,3,5,6], 2
输出: 1
示例 3:

输入: [1,3,5,6], 7
输出: 4
示例 4:

输入: [1,3,5,6], 0
输出: 0

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/search-insert-position
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

  1. 对于有序列表搜索问题,我们使用二分法进行查找
  2. 首先定义begin、end两个变量,begin为二分开始位置,end为二分结束位置。
  3. 使用while循环,当begin大于end时,说明列表中未找到目标值。如果将目标值插入列表中,所在位置应该为begin
  4. 进入while循环,定义mid变量为(begin+end)//2,判断nums[mid]与taget的关系,等于-返回mid,大于-end=mid-1,小于-begin=mid+1

代码实现:

class Solution:
    def searchInsert(self, nums: List[int], target: int) -> int:
        end = len(nums) - 1
        begin = 0
        while begin <= end:
            mid = (begin + end) // 2
            if nums[mid] == target:
                return mid
            elif nums[mid] > target:
                end = mid - 1
            else:
                begin = mid + 1                
        return begin

3.最大子序和(2020.1.3)

题目描述:

给定一个整数数组 nums ,找到一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。

示例:

输入: [-2,1,-3,4,-1,2,1,-5,4],
输出: 6
解释: 连续子数组 [4,-1,2,1] 的和最大,为 6。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/maximum-subarray
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

  1.  使用贪心算法,把单个数组作为输入来查找最大元素的问题,每一步都选择最佳方法,到最后就是全局的最优方案
  2. 定义变量curr_max、sum_max都等于列表的第一个元素
  3. 遍历列表,每次令curr_max等于curr_max、curr_max+当前元素,两者中最大的值,max_sum等于max_sum、curr_max中最大的值
  4. 循环结束后,得到的max_sum就为连续子数组的最大和

代码实现:

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        n = len(nums)
        curr_max = sum_max = nums[0]
        for i in range(1,n):
            curr_max = max(nums[i], nums[i] + curr_max)
            sum_max = max(sum_max, curr_max)
            print(curr_max,sum_max)
        return sum_max

4.最后一个单词的长度(2020.1.4)

题目描述:

给定一个仅包含大小写字母和空格 ' ' 的字符串,返回其最后一个单词的长度。

如果不存在最后一个单词,请返回 0 。

说明:一个单词是指由字母组成,但不包含任何空格的字符串。

示例:

输入: "Hello World"
输出: 5

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/length-of-last-word
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

  1. 首先去除字符串的前后空格,判断字符串如果为空,返回0
  2. 从字符串后面往前遍历,找到第一个为空格的字符,那么空格后的字符串就为最后一个单词,返回其长度
  3. 如果字符串中没有空格,证明该字符串只有一个单词,返回字符串的长度即可

代码实现:

class Solution:
    def lengthOfLastWord(self, s: str) -> int:
        #去除字符串前后空格
        s = s.strip()
        #如果为空,返回0
        if not s:
            return 0
        n = len(s)
        while 0 <= n:
            #查找最后一个空格,返回空格之后的字符串长度
            if s[n-1] == ' ':
                return len(s) - n 
            n -= 1
        #如果字符一个单词,返回传入的字符串长度
        else:
            return len(s)

5.加一(2020.1.5)

题目描述:

给定一个由整数组成的非空数组所表示的非负整数,在该数的基础上加一。

最高位数字存放在数组的首位, 数组中每个元素只存储单个数字。

你可以假设除了整数 0 之外,这个整数不会以零开头。

示例 1:

输入: [1,2,3]
输出: [1,2,4]
解释: 输入数组表示数字 123。
示例 2:

输入: [4,3,2,1]
输出: [4,3,2,2]
解释: 输入数组表示数字 4321。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/plus-one
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

  1. 将整数数组转行成相应的整数
  2. 将整数加1后,转换成字符串
  3. 再将字符串转换成列表

代码实现:

class Solution:
    def plusOne(self, digits: List[int]) -> List[int]:
        sum = 0
        for i in digits:
            sum = sum*10 + i
        sum = str(sum + 1)
        return list(sum)

6.二进制求和(2020.1.6)

题目描述:

给定两个二进制字符串,返回他们的和(用二进制表示)。

输入为非空字符串且只包含数字 1 和 0。

示例 1:

输入: a = "11", b = "1"
输出: "100"
示例 2:

输入: a = "1010", b = "1011"
输出: "10101"

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/add-binary
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

  1. 使用int方法将二进制字符串转换为十进制整型,再进行相加
  2. 将相加的结果使用bin方法转换为二进制字符串,返回结果

代码实现:

class Solution:
    def addBinary(self, a: str, b: str) -> str:
        c = int(a,2) + int(b,2)
        return bin(c)[2:]

7.x 的平方根

题目描述:

实现 int sqrt(int x) 函数。

计算并返回 x 的平方根,其中 x 是非负整数。

由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去。

示例 1:

输入: 4
输出: 2
示例 2:

输入: 8
输出: 2
说明: 8 的平方根是 2.82842..., 
     由于返回类型是整数,小数部分将被舍去。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/sqrtx
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

  1. 本次我们使用二分查找法,通过观察我们可以发现,当整数大于3时,整数的平方根就小于等于该数的二分之一
  2. 定义left和right,left为0,right为x//2+1,x//2+1用于兼容0,1,2,3
  3. 使用while循环,当left不小于right时,跳出循环,定义变量mid为(left+right+1)//2,当mid的平方大于x时,right = mid - 1,否则,left等于mid
  4. 通过一次次的循环查找,最后得到的left等于right,且都为x的平方根

代码实现:

class Solution:
    def mySqrt(self, x: int) -> int:
        left = 0
        right = x//2 + 1
        while left < right:
            mid = (left + right + 1)//2
            sqrt = mid*mid
            if sqrt > x:
                right = mid - 1
            else:
                left = mid
        return right

8.统计参与通信的服务器(2020.1.8)

题目描述:

这里有一幅服务器分布图,服务器的位置标识在 m * n 的整数矩阵网格 grid 中,1 表示单元格上有服务器,0 表示没有。

如果两台服务器位于同一行或者同一列,我们就认为它们之间可以进行通信。

请你统计并返回能够与至少一台其他服务器进行通信的服务器的数量。

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/count-servers-that-communicate
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

  1. 定义空列表count_m、count_n,分别求得每一行、每一列出现元素1的个数,并存放到count_m、count_n中
  2. 定义变量sum为0,变量列表,判断当前元素所在位置count_m或count_n是否大于1,如果大于1,再判断当前元素是否为1,如果都满足,则说明该位置的服务器是可通信服务器,sum加1
  3. 返回sum

代码实现:

class Solution:
    def countServers(self, grid: List[List[int]]) -> int:
        count_m = list()
        count_n = list()
        #判断每一行出现元素1的次数,并存放在count_m 
        for x in range(len(grid)):
            count_x = grid[x].count(1)
            count_m.append(count_x)
        #判断每一列出现元素1的次数,并存放在count_n
        for y in range(len(grid[0])):
            count_y = 0
            for x1 in range(len(grid)):
                if grid[x1][y] == 1:
                    count_y += 1
            count_n.append(count_y)
        sum = 0
        #判断每个元素是否可以通信,如果可以,sum加1
        for y in range(len(grid)):
            for x in range(len(grid[y])):
                if count_m[y] > 1 or count_n[x] > 1:
                    if grid[y][x] == 1:
                        sum += 1
        return sum

9.爬楼梯(2020.1.9)

题目描述:

假设你正在爬楼梯。需要 n 阶你才能到达楼顶。

每次你可以爬 1 或 2 个台阶。你有多少种不同的方法可以爬到楼顶呢?

注意:给定 n 是一个正整数。

示例 1:

输入: 2
输出: 2
解释: 有两种方法可以爬到楼顶。
1.  1 阶 + 1 阶
2.  2 阶
示例 2:

输入: 3
输出: 3
解释: 有三种方法可以爬到楼顶。
1.  1 阶 + 1 阶 + 1 阶
2.  1 阶 + 2 阶
3.  2 阶 + 1 阶

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/climbing-stairs
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

  1. 假设爬上第n阶楼梯有f(n)中方法,经过分析我们发现,f(n) = f(n-1) + f(n-2)
  2. 我们使用动态规划的思想,定义包含n+1个元素的列表dp,dp[n] = dp[n-1] + dp[n-2]
  3. 使用for循环获取列表dp各元素的值,最后返回我们要求解的dp[n]

代码实现:

class Solution:
    def climbStairs(self, n: int) -> int:
        dp = [0]*(n+1)
        dp[1] = 1
        if n < 2:
            return 1
        dp[2] = 2
        for i in range(3,n+1):
            dp[i] = dp[i-1] + dp[i-2]
        return dp[n]

10.合并两个有序数组(2020.01.10)

题目描述:

给定两个有序整数数组 nums1 和 nums2,将 nums2 合并到 nums1 中,使得 num1 成为一个有序数组。

说明:

初始化 nums1 和 nums2 的元素数量分别为 m 和 n。
你可以假设 nums1 有足够的空间(空间大小大于或等于 m + n)来保存 nums2 中的元素。
示例:

输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6],       n = 3

输出: [1,2,2,3,5,6]

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

解题思路:

  1. 使用双指针解法,定义指针p1/p2都为0,定义变量num1_copy等于num1前m个元素
  2. 使用p1指向列表num1_copy,p2指向列表nums2,对比p1和p2所指元素的大小,将较小的赋值给nums1[p1+p2]
  3. 将nums1_copy,nums2剩余的元素添加到nums1中,最后将nums1前m+n个元素返回

代码实现:

class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        p1 = 0
        p2 = 0
        nums1_copy = nums1[:m]

        while p1<m and p2<n:
            if nums1_copy[p1] < nums2[p2]:
                nums1[p1+p2] = nums1_copy[p1]
                p1 += 1
            else:
                nums1[p1+p2] = nums2[p2]
                p2 += 1
        if p1<m:
            nums1[p1+p2:] = nums1_copy[p1:]
            return nums1[:m+n]
        if p2<n:
            nums1[p1+p2:] = nums2[p2:]
            return nums1[:m+n]

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 好的,我来用中文回复这个链接:https://leetcode-cn.com/tag/dynamic-programming/ 这个链接是 LeetCode 上关于动态规划的题目集合。动态规划是一种常用的算法思想,可以用来解决很多实际问题,比如最长公共子序列、背包问题、最短路径等等。在 LeetCode 上,动态规划也是一个非常重要的题型,很多题目都需要用到动态规划的思想来解决。 这个链接里包含了很多关于动态规划的题目,按照难度从简单到困难排列。每个题目都有详细的题目描述、输入输出样例、题目解析和代码实现等内容,非常适合想要学习动态规划算法的人来练习和提高自己的能力。 总之,这个链接是一个非常好的学习动态规划算法的资源,建议大家多多利用。 ### 回答2: 动态规划是一种算法思想,通常用于优化具有重叠子问题和最优子结构性质的问题。由于其成熟的数学理论和强大的实用效果,动态规划在计算机科学、数学、经济学、管理学等领域均有重要应用。 在计算机科学领域,动态规划常用于解决最优化问题,如背包问题、图像处理、语音识别、自然语言处理等。同时,在计算机网络和分布式系统中,动态规划也广泛应用于各种优化算法中,如链路优化、路由算法、网络流量控制等。 对于算法领域的程序员而言,动态规划是一种必要的技能和知识点。在LeetCode这样的程序员平台上,题目分类和标签设置十分细致和方便,方便程序员查找并深入学习不同类型的算法。 LeetCode的动态规划标签下的题目涵盖了各种难度级别和场景的问题。从简单的斐波那契数列、迷宫问题到可以用于实际应用的背包问题、最长公共子序列等,难度不断递进且话题丰富,有助于开发人员掌握动态规划的实际应用技能和抽象思维模式。 因此,深入LeetCode动态规划分类下的题目学习和练习,对于程序员的职业发展和技能提升有着重要的意义。 ### 回答3: 动态规划是一种常见的算法思想,它通过将问题拆分成子问题的方式进行求解。在LeetCode中,动态规划标签涵盖了众多经典和优美的算法问题,例如斐波那契数列、矩阵链乘法、背包问题等。 动态规划的核心思想是“记忆化搜索”,即将中间状态保存下来,避免重复计算。通常情况下,我们会使用一张二维表来记录状态转移过程中的中间值,例如动态规划求解斐波那契数列问题时,就可以定义一个二维数组f[i][j],代表第i项斐波那契数列中,第j个元素的值。 在LeetCode中,动态规划标签下有众多难度不同的问题。例如,经典的“爬楼梯”问题,要求我们计算到n级楼梯的方案数。这个问题的解法非常简单,只需要维护一个长度为n的数组,记录到达每一级楼梯的方案数即可。类似的问题还有“零钱兑换”、“乘积最大子数组”、“通配符匹配”等,它们都采用了类似的动态规划思想,通过拆分问题、保存中间状态来求解问题。 需要注意的是,动态规划算法并不是万能的,它虽然可以处理众多经典问题,但在某些场景下并不适用。例如,某些问题的状态转移过程比较复杂,或者状态转移方程中存在多个参数,这些情况下使用动态规划算法可能会变得比较麻烦。此外,动态规划算法也存在一些常见误区,例如错用贪心思想、未考虑边界情况等。 总之,掌握动态规划算法对于LeetCode的学习和解题都非常重要。除了刷题以外,我们还可以通过阅读经典的动态规划书籍,例如《算法竞赛进阶指南》、《算法与数据结构基础》等,来深入理解这种算法思想。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值