刷题--9/7

发现了自己面试不上的原因,代码题刷的不够

在这里写博客激励自己每天刷题,刷题在精不在多,要的是长期坚持不懈,同级的软件工程的同学进了字节,看她的面经,在后端缓存,数据库,安全,消息队列,OS,计算机网络其实大差不差,只要能进入笔试,说明你的简历没什么大问题,然而我不能进大厂的原因感觉主要就是刷题了,她已经刷了300多道了,能坚持半年我也是自愧不如,双非本科进大厂确实不容易,我才只做了剑指offer的70题。

如果时间充足建议,一个标签一个标签的刷,比如说动态规划,递归,回溯,栈,队列这些,一个个逐个击破,但是我选择的是按照leetcod的顺序刷,雨露均沾,还有就是刷题在精不在多!!!即使不会,也要把题目给弄懂,建议是自己先想,至少题目得懂大概要怎么做,实在想不出来再看题解,看题解要进行理解,要做到不看题解也能写出代码,这能极大的提高对题目的理解程度
把前两天开始刷的题的题解都写博客吧
两数之和

链接:题目链接

题目描述

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。

示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]

解题思路–双指针

先将数组进行排序,再用双指针的方法,有可能找到10 = 5+5,返回的下标的的话,可能会重复,需要特殊处理
其实这题和剑指offer的有一题很像

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        temp=nums.copy()
        temp.sort()
        # 排序后用双指针
        i=0
        j=len(nums)-1
        while i<j:
            if (temp[i]+temp[j])>target:
                j=j-1
            elif (temp[i]+temp[j])<target:
                i=i+1
            else:
                break
        p=nums.index(temp[i])
        nums.pop(p)
        k=nums.index(temp[j])
        # 这里我们用了特殊处理
        if k>=p:
            k=k+1
        return [p,k]
两数相加

链接:题目链接

题目描述

给出两个 非空 的链表用来表示两个非负的整数。其中,它们各自的位数是按照 逆序 的方式存储的,并且它们的每个节点只能存储 一位 数字。

如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。

您可以假设除了数字 0 之外,这两个数都不会以 0 开头。

示例:

输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

解题思路–一般流程

创建一个链表来保存结果链表,用一个变量来保存进位情况
题目是低位到高位的链表,注意,如果是高位到低位是另一种解法

代码实现
class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        a = ListNode()
        # 结果链表
        l3 = a
        c = 0
        while l1 or l2:
            x = l1.val if l1 else 0
            y = l2.val if l2 else 0
            tmp = x+y
            # 要加上低位相加的进位
            if tmp + c<10:
                l3.next = ListNode(tmp+c)
                # 这里将进位给复位
                c = 0
            else:
                l3.next = ListNode(tmp+c-10)
                c = 1
            if l1:
                l1 = l1.next
            if l2:
                l2 = l2.next
            l3 = l3.next
        if c == 1:
            l3.next = ListNode(1)
        return a.next
无重复字符的最长子串–动态规划+hash

链接:题目链接

题目描述

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

示例 1:

输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。

解题思路

设置一个数组,用于保存当前字符上一次出现的位置下标,这题也和剑指offer的一题很像,如果字符一直是没有出现过的,则start一直是-1,如果字符之前出现过了,则start要进行更新为当前字符的下标

代码实现
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        start,res,dic = -1,0,{}
        
        for i,c in enumerate(s):
            if c in dic and dic[c] > start:
                start = dic[c]
                dic[c] = i
            else:
                dic[c] = i
                # 下面这行代码感觉有动态规划的思想
                res = max(res,i-start)
        return res
寻找两个正序数组的中位数–二分查找

链接:题目链接

题目描述

给定两个大小为 m 和 n 的正序(从小到大)数组 nums1 和 nums2。

请你找出这两个正序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。

你可以假设 nums1 和 nums2 不会同时为空。

示例 1:

nums1 = [1, 3]
nums2 = [2]

则中位数是 2.0
示例 2:

nums1 = [1, 2]
nums2 = [3, 4]

则中位数是 (2 + 3)/2 = 2.5

解题思路

这题咋一看感觉很简单,但是难就难在时间复杂度的限制
由于复杂度要求是log,所以一开始就想到用二分查找,细看这题的本质,其实质是找第k小的数字,如果nums1[k//2] < nums2[k//2],则说明不需要直接nums1的左半部分,直接划掉,这样往复,就可以找到第k小的数
中位数有两种情况,奇数个元素和偶数个元素
k1 = (len(nums1)+len(nums2) + 1)//2
k2 = (len(nums1)+len(nums2) + 2)//2
中位数:(k1+k2)/ 2,可以自己验证一下,是正确的

代码实现
class Solution:
    def findMedianSortedArrays(self, nums1: List[int], nums2: List[int]) -> float:
        k1 = ( len(nums1) + len(nums2) + 1 ) // 2
        k2 = ( len(nums1) + len(nums2) + 2 ) // 2
        def helper(nums1,nums2,k): #本质上是找第k小的数
            if(len(nums1) <len(nums2) ):
                nums1, nums2 = nums2 , nums1 #保持nums1比较长
            if(len(nums2)==0):
                return nums1[k-1] # 短数组空,直接返回
            if(k==1):
                return min(nums1[0],nums2[0])  #找最小数,比较数组首位
            t = min(k//2,len(nums2)) # 保证不上溢
            if( nums1[t-1]>=nums2[t-1] ):
                return helper(nums1 , nums2[t:],k-t)
            else:
                return helper(nums1[t:],nums2,k-t)
        return ( helper(nums1,nums2,k1) + helper(nums1,nums2,k2) ) /2
最长回文子串–动态规划,马拉车算法

链接:题目链接

题目描述

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。
示例 2:

输入: “cbbd”
输出: “bb”

解题思路
  • 动态规划的思路:如果一个字符串是回文串的话,那么将这个字符串去头去尾后的子串也是回文字符串,想到这里嘿嘿,遇事不决,动态规划,这题的转移方程也比较好求:s[i:j]表示i到j的子串是不是回文串,s[i:j] = s[i+1:j-1] && s[i] == s[j]
  • 还要考虑字符串长度为1或者2的情况,需要特判,相应的转移方程:
    • 长度为1:s[i:i] = True
    • 长度为2:s[i:i+1] = s[i] == s[i+1]
代码实现
class Solution:
    def longestPalindrome(self, s: str) -> str:
        n = len(s)
        # 创建二维数组
        dp = [[False] * n for _ in range(n)]
        ans = ""
        # 枚举子串的长度 l+1
        for l in range(n):
            # 枚举子串的起始位置 i,这样可以通过 j=i+l 得到子串的结束位置
            for i in range(n):
                j = i + l
                if j >= len(s):
                    break
                if l == 0:
                    dp[i][j] = True
                elif l == 1:
                    dp[i][j] = (s[i] == s[j])
                else:
                    dp[i][j] = (dp[i + 1][j - 1] and s[i] == s[j])
                if dp[i][j] and l + 1 > len(ans):
                    ans = s[i:j+1]
        return ans

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值