Leetcode刷题记录81-90,python语言

81 搜索旋转排序数组 II (左右指针)

定义函数search来搜索目标值在旋转排序数组中是否存在,参数为旋转排序数组nums和目标值target。
使用二分查找算法,在循环中不断缩小搜索范围。
初始化左右指针,分别指向数组的起始位置和末尾位置。
在循环中,计算中间元素的索引。
如果中间元素等于目标值,直接返回True。
如果左、中、右三个位置的元素值相等,则无法确定哪一部分是有序的,此时将左指针右移、右指针左移,缩小搜索范围。
如果左半段有序,则判断目标值是否在左半段范围内,若在,则将右指针移到中间元素左侧,否则将左指针移到中间元素右侧。
如果右半段有序,则判断目标值是否在右半段范围内,若在,则将左指针移到中间元素右侧,否则将右指针移到中间元素左侧。
循环结束后,若未找到目标值,则返回False。

class Solution:
    def search(self, nums: List[int], target: int) -> bool:

        left, right = 0, len(nums) - 1

        while left <= right:
            mid = (left + right) // 2 # //表示取整除法,4.5取4,中间位置的下标
            # 如果中间元素等于目标值,直接返回True
            if nums[mid] == target:
                return True
            
            # 处理左右两段分别有序的情况
            if nums[left] == nums[mid] == nums[right]: # 比如[2,5,6,2,2,2,2]这种,三个数一样则无法确定哪一部分是有序的,此时将左指针右移、右指针左移,缩小搜索范围。
                left += 1
                right -= 1
            elif nums[left] <= nums[mid]:
                # 左半段有序
                if nums[left] <= target < nums[mid]:
                    right = mid - 1
                else:
                    left = mid + 1
            else:
                # 右半段有序
                if nums[mid] < target <= nums[right]:
                    left = mid + 1
                else:
                    right = mid - 1
        
        return False

82 删除排序链表中的重复元素

定义了一个ListNode类来表示链表节点,每个节点包含一个值和一个指向下一个节点的指针。
定义了deleteDuplicates函数,用于删除链表中重复的节点,参数为链表的头节点head。
特殊情况处理:若链表为空或只有一个节点,直接返回原链表。
在链表头部添加一个虚拟头节点dummy,以便处理头节点重复的情况。
使用两个指针prev和head,其中prev指向当前已经确认不重复的节点,head用于遍历链表。
在循环中,若当前节点的值等于下一个节点的值,则开始遍历直到找到不重复的节点。
若找到不重复的节点,则将prev.next指向该节点,并更新prev和head。
若当前节点的值不等于下一个节点的值,则直接更新prev和head。
循环结束后,返回虚拟头节点dummy的下一个节点,即为去除重复节点后的新链表的头节点。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
        # 处理特殊情况,当链表为空或只有一个节点时,直接返回原链表 
        if not head or not head.next: # if not XXXX,表示 当XXXX为false时执行下面
            return head
        
        # 添加一个虚拟头节点,方便处理头节点重复的情况
        dummy = ListNode(0)
        dummy.next = head
        prev = dummy # 用prev来保存返回的结果那些不重复数字

        while head and head.next: # 两个都不为空
            # 如果当前节点的值等于下一个节点的值,则开始遍历找到不重复的节点
            if head.val == head.next.val:
                while head.next and head.val == head.next.val:  # 这里是说比如连续三四个重复数字,就用上while去跳过这些重复的,
                    head = head.next
                # 跳过重复的节点,貌似头结点跳了两次,跳过重复节点
                head = head.next
                prev.next = head
            else:
                # 如果当前节点的值不等于下一个节点的值,则更新prev和head
                prev = prev.next
                head = head.next
        
        return dummy.next

83 删除排序链表中的重复元素(一个节点,包括两部分data值和next指向)

可参考两篇链表文章,https://blog.csdn.net/charuiyu/article/details/86483930/ ; https://blog.csdn.net/Traceyfind/article/details/131901092
定义了一个ListNode类来表示链表节点,每个节点包含一个值和一个指向下一个节点的指针。
定义了deleteDuplicates函数,用于删除链表中重复的节点,参数为链表的头节点head。
特殊情况处理:若链表为空或只有一个节点,直接返回原链表。
使用两个指针prev和curr,其中prev指向当前已经确认不重复的节点,curr用于遍历链表。
在循环中,若当前节点值与上一个节点值相同,则将当前节点从链表中删除。
否则更新prev和curr的指向。
循环结束后,返回链表的头节点head。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def deleteDuplicates(self, head: Optional[ListNode]) -> Optional[ListNode]:
        if not head or not head.next:
            return head
        
        prev = head # prev是头结点了,他是一个值,不是输出链表,head是输出链表,所以最后return head
        curr = head.next

        while curr: # 当下一个节点不为空,
            # 如果当前节点值与上一个节点值相同,则将当前节点从链表中删除
            if prev.val == curr.val:
                prev.next = curr.next   
            else:
                # 否则更新prev和curr的指向
                prev = curr
            curr = curr.next
        
        return head

86 分割链表

定义了一个ListNode类来表示链表节点,每个节点包含一个值和一个指向下一个节点的指针。
定义了partition函数,用于按照给定的值x将链表分割成两部分,小于x的节点在前,大于等于x的节点在后,参数为链表的头节点head和分割值x。
创建了两个虚拟头节点before_head和after_head,分别用于存储小于x的节点和大于等于x的节点。
创建了两个指针before和after,分别指向前半部分链表和后半部分链表的最后一个节点。
遍历原链表,根据节点值的大小将节点连接到相应的链表中。
若节点值小于x,则将该节点连接到前半部分链表中,并更新before指针。
否则将该节点连接到后半部分链表中,并更新after指针。
遍历结束后,将后半部分链表的最后一个节点指向None,前半部分链表的最后一个节点指向后半部分链表的头节点。
返回前半部分链表的头节点。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def partition(self, head: Optional[ListNode], x: int) -> Optional[ListNode]:
         # 创建两个虚拟头节点,分别用于存储小于x的节点和大于等于x的节点
        before_head = ListNode(0)
        after_head = ListNode(0)

        # 创建两个指针,分别指向前半部分链表和后半部分链表
        before = before_head
        after = after_head

        # 遍历原链表,根据节点值的大小将节点连接到相应的链表中
        while head: # 当head不为空
            if head.val < x:
                before.next = head
                before = before.next # 更新before指针
            else:
                after.next = head
                after = after.next # 更新指针
            head = head.next

        # 将前半部分链表与后半部分链表连接起来
        after.next = None
        before.next = after_head.next # 虚拟节点0的下一个节点

        return before_head.next # 虚拟节点0的下一个节点

88 合并两个有序数组

定义了merge函数,用于将两个有序数组合并为一个有序数组,参数为两个有序数组nums1和nums2,以及它们的长度m和n。
定义两个指针p1和p2,分别指向nums1和nums2的末尾。
从后往前遍历数组,将较大的元素放入nums1的末尾。
如果nums1已经遍历完毕,则将nums2中剩余的元素放入nums1中。
如果nums2已经遍历完毕,则退出循环。
如果当前nums1中指针p1所指的元素大于等于nums2中指针p2所指的元素,则将nums1中指针p1所指的元素放入nums1的末尾,并将指针p1向前移动。
否则将nums2中指针p2所指的元素放入nums1的末尾,并将指针p2向前移动。
循环结束后,nums1包含合并后的有序数组。

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.
        """
         # 定义两个指针,分别指向nums1和nums2的末尾
        p1 = m - 1
        p2 = n - 1

        # 从后往前遍历数组,将较大的元素放入nums1的末尾
        for i in range(m + n - 1, -1, -1): # 类似倒着取数 5 4 3 2 1 0;是总个数之和
            if p1 < 0: # nums1指针index,小于零 ;如果nums1已经遍历完毕,则将nums2中剩余的元素放入nums1中。
                nums1[i] = nums2[p2] # 则将nums2中剩余的元素放入nums1中。
                p2 -= 1 # nums2指针继续走
            elif p2 < 0:
                break # 结束整个for i循环
            elif nums1[p1] >= nums2[p2]: # 在i当前位置,确定出填充的数字
                nums1[i] = nums1[p1]
                p1 -= 1
            else:
                nums1[i] = nums2[p2]
                p2 -= 1

89 格雷编码

class Solution:
    def grayCode(self, n: int) -> List[int]:
        result = []  # 创建一个空列表用于存储格雷编码
        for i in range(2**n):  # 对于0到2的n次方之间的每一个数
            result.append(i ^ (i >> 1))  # 将当前数i与右移一位的i异或,并将结果添加到结果列表中
        return result  # 返回格雷编码序列
        

90 子集 II

class Solution:
    def subsetsWithDup(self, nums: List[int]) -> List[List[int]]:
        nums.sort()  # 首先对nums进行排序,以便处理重复元素
        result = [[]]  # 初始化结果为一个空列表(空集是任何集合的子集)
        start = 0  # 初始化起始索引为0
        for i in range(len(nums)):  # 对于nums中的每一个元素
            if i == 0 or nums[i] != nums[i-1]:  # 如果是第一个元素或者当前元素与上一个元素不相同
                start = 0  # 更新起始索引为0, start主要是用来在result前几个小列表中重新添加元素, 元素不一样就要start从零
            size = len(result)  # 获取当前结果列表的长度
            for j in range(start, size):  # 遍历结果列表中的每一个子集, 遍历每个小列表,在下面重新添加元素到之前小列表中,。相同元素的话,start就不能上一次加的[1,2]重复,不能[1] + [2]这样, 即start不能从0取
                result.append(result[j] + [nums[i]])  # 将当前元素加入到子集中形成新的子集
            start = size  # 更新起始索引为当前结果列表的长度
        return result  # 返回最终的子集列表
  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值