Python每日一练(20230318)

目录

1. 排序链表  ★★

2. 最长连续序列  ★★

3. 扰乱字符串  ★★★

? 每日一练刷题专栏 ?

Golang每日一练 专栏

Python每日一练 专栏

C/C++每日一练 专栏

Java每日一练 专栏


文章来源地址https://uudwc.com/A/5Oze

1. 排序链表

给你链表的头结点 head ,请将其按 升序 排列并返回 排序后的链表 。

进阶:

  • 你可以在 O(nlogn) 时间复杂度和常数级空间复杂度下,对链表进行排序吗?

示例 1:

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

示例 2:

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

示例 3:

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

提示:

  • 链表中节点的数目在范围 [0, 5 * 10^4] 内
  • -10^5 <= Node.val <= 10^5

代码:

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution:
    def sortList(self, head: ListNode) -> ListNode:
        if head == None:
            return None
        else:
            return self.mergeSort(head)
    def mergeSort(self, head):
        if head.next == None:
            return head
        fast = head
        slow = head
        pre = None
        while fast != None and fast.next != None:
            pre = slow
            slow = slow.next
            fast = fast.next.next
        pre.next = None
        left = self.mergeSort(head)
        right = self.mergeSort(slow)
        return self.merge(left, right)
    def merge(self, left, right):
        tempHead = ListNode(0)
        cur = tempHead
        while left != None and right != None:
            if left.val <= right.val:
                cur.next = left
                cur = cur.next
                left = left.next
            else:
                cur.next = right
                cur = cur.next
                right = right.next
        if left != None:
            cur.next = left
        if right != None:
            cur.next = right
        return tempHead.next

class LinkList:
    def __init__(self):
        self.head = None
    def initList(self, data):
        if not data: return None
        self.head = ListNode(data[0])
        p = head = self.head
        for i in data[1:]:
            node = ListNode(i)
            p.next = node
            p = p.next
        return head
    def showList(self, head):
        if head:
            print(head.val, end = '->')
            self.showList(head.next)
        else:
            print('null')


if __name__ == '__main__':
    s = Solution()
    l = LinkList()
    head = l.initList([4,2,1,3])
    l.showList(head)
    head = s.sortList(head)
    l.showList(head)
    
    head = l.initList([-1,5,3,4,0])
    l.showList(head)
    head = s.sortList(head)
    l.showList(head)
    

输出:

4->2->1->3->null
1->2->3->4->null
-1->5->3->4->0->null
-1->0->3->4->5->null


2. 最长连续序列

给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。

请你设计并实现时间复杂度为 O(n) 的算法解决此问题。

示例 1:

输入:nums = [100,4,200,1,3,2]
输出:4
解释:最长数字连续序列是 [1, 2, 3, 4]。它的长度为 4。

示例 2:

输入:nums = [0,3,7,2,5,8,4,6,0,1]
输出:9

提示:

  • 0 <= nums.length <= 10^5
  • -10^9 <= nums[i] <= 10^9

代码:

class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

class Solution:
    def longestConsecutive(self, nums: list) -> int:
        hash_dict = {}
        max_length = 0
        for num in nums:
            if num not in hash_dict:
                pre_length = hash_dict.get(num - 1, 0)
                next_length = hash_dict.get(num + 1, 0)
                cur_length = pre_length + 1 + next_length
                if cur_length > max_length:
                    max_length = cur_length
                hash_dict[num] = cur_length
                hash_dict[num - pre_length] = cur_length
                hash_dict[num + next_length] = cur_length
        return max_length


if __name__ == '__main__':
    s = Solution()
    nums = [100,4,200,1,3,2]
    print(s.longestConsecutive(nums))
    
    nums = [0,3,7,2,5,8,4,6,0,1]
    print(s.longestConsecutive(nums))

输出:

4
9


3. 扰乱字符串

使用下面描述的算法可以扰乱字符串 s 得到字符串 t :

  1. 如果字符串的长度为 1 ,算法停止
  2. 如果字符串的长度 > 1 ,执行下述步骤:
    • 在一个随机下标处将字符串分割成两个非空的子字符串。即,如果已知字符串 s ,则可以将其分成两个子字符串 x 和 y ,且满足 s = x + y 。
    • 随机 决定是要「交换两个子字符串」还是要「保持这两个子字符串的顺序不变」。即,在执行这一步骤之后,s 可能是 s = x + y 或者 s = y + x 。
    • 在 x 和 y 这两个子字符串上继续从步骤 1 开始递归执行此算法。

给你两个 长度相等 的字符串 s1 和 s2,判断 s2 是否是 s1 的扰乱字符串。如果是,返回 true ;否则,返回 false 。

示例 1:

输入:s1 = "great", s2 = "rgeat"
输出:true
解释:s1 上可能发生的一种情形是:
"great" --> "gr/eat" // 在一个随机下标处分割得到两个子字符串
"gr/eat" --> "gr/eat" // 随机决定:「保持这两个子字符串的顺序不变」
"gr/eat" --> "g/r / e/at" // 在子字符串上递归执行此算法。两个子字符串分别在随机下标处进行一轮分割
"g/r / e/at" --> "r/g / e/at" // 随机决定:第一组「交换两个子字符串」,第二组「保持这两个子字符串的顺序不变」
"r/g / e/at" --> "r/g / e/ a/t" // 继续递归执行此算法,将 "at" 分割得到 "a/t"
"r/g / e/ a/t" --> "r/g / e/ a/t" // 随机决定:「保持这两个子字符串的顺序不变」
算法终止,结果字符串和 s2 相同,都是 "rgeat"
这是一种能够扰乱 s1 得到 s2 的情形,可以认为 s2 是 s1 的扰乱字符串,返回 true

示例 2:

输入:s1 = "abcde", s2 = "caebd"
输出:false

示例 3:

输入:s1 = "a", s2 = "a"
输出:true

提示:

  • s1.length == s2.length
  • 1 <= s1.length <= 30
  • s1 和 s2 由小写英文字母组成

代码:

class Solution(object):
    def isScramble(self, s1, s2, memo={}):
        if len(s1) != len(s2) or sorted(s1) != sorted(s2):
            return False
        if len(s1) <= len(s2) <= 1:
            return s1 == s2
        if s1 == s2:
            return True
        if (s1, s2) in memo:
            return memo[s1, s2]
        n = len(s1)
        for i in range(1, n):
            a = self.isScramble(s1[:i], s2[:i], memo) and self.isScramble(s1[i:], s2[i:], memo)
            if not a:
                b = self.isScramble(s1[:i], s2[-i:], memo) and self.isScramble(s1[i:], s2[:-i], memo)
            if a or b:
                memo[s1, s2] = True
                return True
        memo[s1, s2] = False
        return False

# %%
s = Solution()
print(s.isScramble(s1 = "great", s2 = "rgeat"))
print(s.isScramble(s1 = "abcde", s2 = "caebd"))
print(s.isScramble(s1 = "a", s2 = "a"))

输出:

True
False
True


? 每日一练刷题专栏 ?

 持续,努力奋斗做强刷题搬运工!

? 点赞,你的认可是我坚持的动力! 

? 收藏,你的青睐是我努力的方向! 

 评论,你的意见是我进步的财富!  

Golang每日一练 专栏

Python每日一练 专栏

C/C++每日一练 专栏

Java每日一练 专栏

原文地址:https://blog.csdn.net/boysoft2002/article/details/129555307

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请联系站长进行投诉反馈,一经查实,立即删除!

上一篇 2023年06月16日 04:35
三种方法求递归算法的时间复杂度(递推,master定理,递归树)
下一篇 2023年06月16日 04:35