20 days team study | Tencent Featured 2.4.5 Questions

002 Add two numbers

Title description

给出两个 **非空** 的链表用来表示两个非负的整数。
其中,它们各自的位数是按照 **逆序** 的方式存储的,并且它们的每个节点只能存储 **一位** 数字。
如果,我们将这两个数相加起来,则会返回一个新的链表来表示它们的和。
您可以假设除了数字 0 之外,这两个数都不会以 0 开头。
示例 1:
输入:(2 -> 4 -> 3) + (5 -> 6 -> 4)
输出:7 -> 0 -> 8
原因:342 + 465 = 807

Problem solving method
Insert picture description here
python code

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


class Solution:
    def addTwoNumbers(self, l1: ListNode, l2: ListNode) -> ListNode:
        result = ListNode(0)
        l3 = result
        val = 0   # val是进位  cur是两数相加得到的个位数
        # 两条链表长度可能不相等,因此结束循环后,需要判断是否有未遍历完的链表,有则单独遍历,没有则进入下一步。
        while val or l1 or l2:  # 只要val,l1,l2有一个不为0或none均可执行
            # val=两数相加的和/10的除数  cur=两数相加的和/10的余数  比如7+8=15/10=1...5所以val=1,cur=5
            val, cur = divmod(val + (l1.val if l1 else 0) + (l2.val if l2 else 0), 10)
            l3.next = ListNode(cur)
            l3 = l3.next
            l1 = l1.next if l1 else None
            l2 = l2.next if l2 else None
        return result.next


def generateList(l: list) -> ListNode:
    prenode = ListNode(0)
    lastnode = prenode
    for val in l[::-1]:  # 逆序
        lastnode.next = ListNode(val)
        lastnode = lastnode.next
    return prenode.next


def printList(l: ListNode):
    while l:
        print("{}".format(l.val), end=' ')
        l = l.next
    print('')


if __name__ == "__main__":
    l1 = generateList([1, 5, 8])
    l2 = generateList([9, 1, 2, 8])
    printList(l1)
    printList(l2)
    s = Solution()
    sum = s.addTwoNumbers(l1, l2)
    printList(sum)

004 Find the median of two positive arrays

Title description

给定两个大小为 m 和 n 的有序数组 nums1 和 nums2。
请你找出这两个有序数组的中位数,并且要求算法的时间复杂度为 O(log(m + n))。
你可以假设 nums1 和 nums2 不会同时为空。
示例 1:
nums1 = [1, 3]
nums2 = [2]
则中位数是 2.0

Problem solving method

1. Violent solution
2. Combine two ordered arrays

当两个有序数组的中位数之和为奇数时,中位数只有一个,将它返回。
当两个有序数组的中位数之和为偶数时,中位数只有两个,返回合并、排序以后位于中间的两个数的平均数

3. Binary search

The main thing of this method is to find the dividing line of two ordered arrays, as shown in the figure below.
The standard is:
suppose the number of array 1 is m, and the number of array 2 is n
1. The number of elements on the left of the red line = (m+n+1)/2 (rounded down)
2. All on the left of the red line The value of each element of should be less than or equal to the value of all the elements on the right side of the red line (note that the value of the element is not the sum)

Even case
Odd cases

After the dividing line is determined, the median can be found directly:
1. When m+n is an odd number: return the maximum value of the left element of the dividing line
2. When m+n is an even number: return the maximum value of the left element of the dividing line Mean with the minimum of the right element

python code

Violent solution:

class Solution:
    def findMedianSortedArrays(self, nums1, nums2):
        m = len(nums1)
        n = len(nums2)
        nums1.extend(nums2)  # 合并
        nums1.sort()  # 排序
        print(m + n)
        if (m + n) & 1:  # 奇数 
            return nums1[(m + n - 1) >> 1]  #左移1位相当于乘以2, 右移1位相当于除以2
        else:            # 偶数
            return (nums1[(m + n - 1) >> 1] + nums1[(m + n) >> 1]) / 2

if __name__ == "__main__":
    s = Solution()
    A = [1, 5, 7, 8, 1, 2, 3]
    B = [2]
    print(s.findMedianSortedArrays(A, B))

Dichotomy solution:

import sys
class Solution(object):
    def findMedianSortedArrays(self, nums1, nums2):
        ls1, ls2 = len(nums1), len(nums2)
        if ls1 < ls2:
            return self.findMedianSortedArrays(nums2, nums1)
        l, r = 0, ls2 * 2
        while l <= r:
            mid2 = (l + r) >> 1
            mid1 = ls1 + ls2 - mid2
            L1 = -sys.maxsize - 1 if mid1 == 0 else nums1[(mid1 - 1) >> 1]
            L2 = -sys.maxsize - 1 if mid2 == 0 else nums2[(mid2 - 1) >> 1]
            R1 = sys.maxsize if mid1 == 2 * ls1 else nums1[mid1 >> 1]
            R2 = sys.maxsize if mid2 == 2 * ls2 else nums2[mid2 >> 1]
            if L1 > R2:
                l = mid2 + 1
            elif L2 > R1:
                r = mid2 - 1
            else:
                return (max(L1, L2) + min(R1, R2)) / 2.0


if __name__ == '__main__':
    # begin
    s = Solution()
    print(s.findMedianSortedArrays([1, 2, 3, 4], [5, 6, 7, 8, 9]))

005 The longest palindrome substring

Title description

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。

Problem solving method
1. Violent solution
Insert picture description here

2. Center diffusion method

There are two possibilities for the central location:
Insert picture description here
Insert picture description here

3. Dynamic programming

python code

Center development method:

class Solution:
    def longestPalindrome(self, s: str) -> str:
        size = len(s)
        if size < 2:
            return s

        # 至少是 1
        max_len = 1
        res = s[0]

        for i in range(size):
            palindrome_odd, odd_len = self.__center_spread(s, size, i, i)
            palindrome_even, even_len = self.__center_spread(s, size, i, i + 1)

            # 当前找到的最长回文子串
            cur_max_sub = palindrome_odd if odd_len >= even_len else palindrome_even
            if len(cur_max_sub) > max_len:
                max_len = len(cur_max_sub)
                res = cur_max_sub

        return res

    def __center_spread(self, s, size, left, right):
        """
        left = right 的时候,此时回文中心是一个字符,回文串的长度是奇数
        right = left + 1 的时候,此时回文中心是一个空隙,回文串的长度是偶数
        """
        i = left
        j = right

        while i >= 0 and j < size and s[i] == s[j]:
            i -= 1
            j += 1
        return s[i + 1:j], j - i - 1


if __name__ == '__main__':
    # begin
    s = Solution()
    print(s.longestPalindrome("qbcaacb"))

Guess you like

Origin blog.csdn.net/weixin_42326479/article/details/112474773