leetcode 004-006

这几天疯狂考试,具体的代码思路就不分析了,第四第五题都用自己的方法实现了,因为是暴力刚,被卡边界的过程挺惨的。说起来,这就是有思路和没思路的区别了。

更新:考完试,想起来还欠着这个。把之前没注意的都补上

leetcode 004

代码实现

class Solution:
    
    def delBothArrays(self, lst_nums, del_len):
        """
        :type lst_nums: list[list[int]]
        :type del_len: int
        :rtype: list[int]
        """
        nums1, nums2 = lst_nums
        for t in range(del_len):
            if len(nums1) == 0:
                nums2.pop()
            elif len(nums2) == 0:
                nums1.pop()
            else:
                if nums1[-1] >= nums2[-1]:
                    nums1.pop()
                else:
                    nums2.pop()
    
    def singleLstMedian(self, nums):
        """
        :type nums: List[int]
        :rtype: float
        """
        if len(nums) % 2:
            i = (len(nums)-1) // 2
            return nums[i]
        else:
            i = (len(nums)-2) // 2
            return (nums[i] + nums[i+1]) / 2
    
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        i = len(nums1) - 1
        j = len(nums2) - 1
        if i == -1:
            return self.singleLstMedian(nums2)
        elif j == -1:
            return self.singleLstMedian(nums1)
        if (i + j) % 2:
            del_len = (i + j + 1) // 2
            self.delBothArrays([nums1,nums2], del_len)
            if len(nums1) == 0:
                median = nums2[-1]
            elif len(nums2) == 0:
                median = nums1[-1]
            else:
                median = nums1[-1] if nums1[-1] >= nums2[-1] else nums2[-1]
        else:
            del_len = (i + j) // 2
            self.delBothArrays([nums1,nums2], del_len)
            if len(nums1) == 1:
                lst_new = nums1[-1:] + nums2[-2:]
            elif len(nums2) == 1:
                lst_new = nums1[-2:] + nums2[-1:]
            else:
                lst_new = nums1[-2:] + nums2[-2:]
            lst_new.sort()
            median = (lst_new[-1] + lst_new[-2]) / 2
        return median

上面是我自己的思路,简单来说就是将两个数组共同从后向前删去一半(或减一的一半)的数。需要注意的是,我这两个数组并没有合并。删完之后的两个数组,就会暴露出两个疑似中位数的值,最后比较出来就可以了。时间复杂度是O(m+n)。

而解答里的思路,怎么说非常的巧妙。具体的思路如下:

只需要保证 B[j-1]<A[i] 和 A[i-1]<B[j] ,就有max(left) < min(right)。同时 i 的检索使用了二分技巧,而 j 由 len(left) = len(right) 可以找到一个计算式:(j = frac{}m+n+1{2}-1)。需要注意的是,+1是非常重要的,这在总数为奇的情况下,会保证左边那堆数永远比右边的多一个。

解答代码如下:

class Solution:
    def findMedianSortedArrays(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: float
        """
        m, n = len(nums1), len(nums2)
        if m > n:
            m, n, nums1, nums2 = n, m, nums2, nums1
        imin, imax, half_len = 0, m, (m + n + 1) // 2
        while imin <= imax:
            i = (imin + imax) // 2
            j = half_len - i
            if i > 0 and nums1[i-1] > nums2[j]:
                imax = i - 1
            elif i < m and nums2[j-1] > nums1[i]:
                imin = i + 1
            else:
                if i == 0: max_left = nums2[j-1]
                elif j == 0: max_left = nums1[i-1]
                else: max_left = max(nums1[i-1], nums2[j-1])
                
                if (m + n) % 2 == 1:
                    return max_left
                
                if i == m: min_right = nums2[j]
                elif j == n: min_right = nums1[i]
                else: min_right = min(nums1[i], nums2[j])
                    
                return (max_left + min_right) / 2

leetcode 005

代码实现

class Solution:
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        if len(s) == 0 or len(s) == 1:
            return s
        lst_init = list(s)
        lst_cmp = []
        length = 0
        pos = 1
        is_odd = True
        pop_num = lst_init.pop()
        for i in range(len(s) - 1, 0, -1):
            lst_cmp.append(pop_num)
            offset = 1
            while True:     # 找出偶回文串
                if len(lst_cmp) < offset or len(lst_init) < offset:
                    break
                if lst_cmp[-offset] == lst_init[-offset]:
                    if offset > length:
                        length = offset
                        pos = i
                        is_odd = False
                    offset += 1
                else:
                    break
            pop_num = lst_init.pop()
            offset = 1
            while True:     # 找出奇回文串
                if len(lst_cmp) < offset or len(lst_init) < offset:
                    break
                if lst_cmp[-offset] == lst_init[-offset]:
                    if offset >= length: # 奇大于偶,但会导致不稳定
                        length = offset
                        pos = i
                        is_odd = True
                    offset += 1
                else:
                    break
        if not is_odd:
            right = pos + length
            left = pos - length
        else:
            if length == 0:
                return s[-1]  # 如果不规则,返回最后一个
            right = pos + length
            left = pos - 1 - length
        return s[left:right]

这道题我的解题思路其实是挺清晰的,简而言之就是用两个队列并排比较。代码看起来很复杂,其实时间复杂度为O(n^2),空间复杂度为O(n),算是还好。做的时候确实被很多边界卡得很厉害,等以后看看有没有办法简化。

看了下答案,竟然有三四种解法,之后一个个去琢磨。

leetcode 006

代码实现

这道题没有做出来。

class Solution:
    def convert(self, s, numRows):
        """
        :type s: str
        :type numRows: int
        :rtype: str
        """
        if numRows == 1 or numRows >= len(s):
            return s

        L = [''] * numRows
        index, step = 0, 1

        for x in s:
            L[index] += x
            if index == 0:
                step = 1
            elif index == numRows -1:
                step = -1
            index += step

        return ''.join(L)
原文地址:https://www.cnblogs.com/ChanWunsam/p/10230411.html