算法高频笔试/面试题1-反转链表/最长递增子序列/最长回文子串/反转数字

1 反转链表

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]


输入:head = [1,2]
输出:[2,1]
示例 3:

输入:head = []
输出:[]

根据链表的定义,其每个节点都包含两个域,一个为信息域:存储元素,一个为链接域:存储下一节点的地址,最后一个节点的链接域指向一个空值。

每一步循环中,都将原列表中cur.next链接域存放的地址指向其前一个节点,直至cur=Null,pre指向最后一个节点。

循环后,原链表中,最后一个节点中指向的下一个节点为原倒数第二个节点,以此类推,原列表的第一个节点指向Null;pre即相当于头节点,返回pre,相当于将原链表反转

1、迭代需要三个指针,pre,cur,nxt,分别按顺序指向三个节点
2、三个指针的初始化:pre指向空节点,cur指向头结点head,nxt指向head.next; 因为head.next可能不存在,nxt在循环中定义,这样如果head为空就不会进入循环
3、迭代过程

  • nxt指向cur.next
  • cur.next指向pre
  • pre移动到cur位置
  • cur移动到nxt位置

4、当cur为空时,返回pre

在这里插入图片描述

class Solution:
    def reverseList(self, head: ListNode) -> ListNode:
        pre = None
        cur = head
        while cur:
            next_temp= cur.next #保存当前节点的下一个节点,防止丢失
            cur.next = pre #将当前节点的指针指向前一个节点,实现反转操作 next用来存放下一个节点的位置
            
            #指针存放地址(位置信息) pre cur的位置信息向前移
            pre = cur #将 pre 指针指向当前节点,为下一次迭代做准备
            cur = next_temp #将当前节点指针移动到下一个节点。
        return pre 

2 最长递增子序列

给你一个整数数组 nums ,找到其中最长严格递增子序列的长度。

子序列 是由数组派生而来的序列,删除(或不删除)数组中的元素而不改变其余元素的顺序。例如,[3,6,2,7] 是数组 [0,3,1,6,2,2,7] 的子序列。

示例 1:
输入:nums = [10,9,2,5,3,7,101,18]
输出:4
解释:最长递增子序列是 [2,3,7,101],因此长度为 4 。

示例 2:
输入:nums = [0,1,0,3,2,3]
输出:4

方法一:动态规划

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        n = len(nums)
        # 如果空数组,则直接返回0
        if n == 0: 
            return 0
        #长度为n的初始化数组dp,其中每个元素都被初始化为1
        #数组dp用来记录以每个元素结尾的最长递增子序列的长度
        dp = [1] * n
        #遍历数组nums中的每个元素(除了第一个元素)
        for i in range(1, n):
            #遍历当前元素之前的所有元素
            for j in range(i):
                #判断当前元素nums[i]是否大于前面的元素nums[j]
                if nums[i] > nums[j]:
                #更新数组dp中以当前元素结尾的最长递增子序列长度为dp[j]+1
                    dp[i] = max(dp[i], dp[j] + 1)
        return max(dp)

方法二:贪心+二分查找

class Solution:
    def lengthOfLIS(self, nums: List[int]) -> int:
        n = len(nums)
        if n == 0:
            return 0
        # 创建辅助数组tails,并将输入数组的第一个元素添加到tails中
        #这用来存储递增子序列的末尾元素的最小值
        tails = [nums[0]]
        #从索引1开始遍历输入数组nums的每个元素,因为第一个元素已经加入了tails数组
        for i in range(1, n):
            #如果当前元素nums[i]大于tails数组的最后一个元素,说明可以将当前元素加入到已有的递增子序列后面
            #因此将其添加到tails数组中
            if nums[i] > tails[-1]:
                tails.append(nums[i])  
            #如果当前元素nums[i]不大于tails数组的最后一个元素,则利用二分查找算法在tails数组中找到第一个大于等于nums[i]的元素
            #并用nums[i]替换它。这样可以保证tails数组始终是一个递增序列,且长度与最长递增子序列相同
            else:
                left, right = 0, len(tails) - 1
                while left < right:
                    mid = (left + right) // 2
                    if tails[mid] < nums[i]:
                        left = mid + 1
                    else:
                        right = mid
                tails[left] = nums[i]  # 使用二分查找找到第一个大于等于num的元素,并替换为num
        return len(tails)

3 最长回文子串

给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。

示例 2:
输入:s = “cbbd”
输出:“bb”

class Solution:
    def longestPalindrome(self, s: str) -> str:

        n = len(s)
        if n < 2:
            return s
 
        max_len = 1
        begin = 0
        # dp[i][j] 表示 s[i..j] 是否是回文串
        dp = [[False] * n for _ in range(n)]
        for i in range(n):
            dp[i][i] = True
 
        # 递推开始
        # 先枚举子串长度
        for L in range(2, n + 1):
            # 枚举左边界,左边界的上限设置可以宽松一些
            for i in range(n):
                # 由 L 和 i 可以确定右边界,即 j - i + 1 = L 得
                j = L + i - 1
                # 如果右边界越界,就可以退出当前循环
                if j >= n:
                    break
 
                if s[i] != s[j]:
                    dp[i][j] = False
                else:
                    if j - i < 3:
                        dp[i][j] = True
                    else:
                        dp[i][j] = dp[i + 1][j - 1]#只有dp[0][4]是True,dp[1][3]还是True……,这才是真正的回文串
                        # dp[i][j] = True #假如s="abaa",s[0]=s[4], d[0][4]=True,就被认为是回文串,跳入下一个环节
 
                # 只要 dp[i][L] == true 成立,就表示子串 s[i..L] 是回文,此时记录回文长度和起始位置
                if dp[i][j] and j - i + 1 > max_len:
                    max_len = j - i + 1
                    begin = i
        return s[begin:begin + max_len]


4 反转数字

首先,将数值 num 转换为字符串类型,通过 str(num)。

然后,通过切片操作 [::-1] 对字符串进行反向切片。这个切片操作的含义是从字符串结尾开始,以步长为 -1(即逆序)切片。这样,可以得到一个反转后的字符串。

最后,使用 int() 函数将反转后的字符串转换回整数类型。

int(str(num)[::-1])
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大西瓜的科研日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值