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])