首页 > 代码库 > 周刷题第二期总结(Longest Substring Without Repeating Characters and Median of Two Sorted Arrays)

周刷题第二期总结(Longest Substring Without Repeating Characters and Median of Two Sorted Arrays)

这周前面刷题倒是蛮开心,后面出了很多别的事情和问题就去忙其他的,结果又只完成了最低目标。

 

Lonest Substring Without Repeating Characters:

Given a string, find the length of the longest substring without repeating characters.

Examples:

Given "abcabcbb", the answer is "abc", which the length is 3.

Given "bbbbb", the answer is "b", with the length of 1.

Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.

 

首先这是个中等难度的题,拿到这个题我最先想到的是做一根指针在头部,当遇到第二个与头部指针指向的字符相同的时候就将指针向前拨。当时我想尽可能将问题简化成两个相同字符之间的不一样字符长度的问题。后来仔细想了一下发现,大方向倒不是有很大的错误,但是边界条件很多,包括连续遇到两个相同字符时候需要做的处理,没有两个相同字符需要做的处理等。试了一下自己的想法,写了代码下面贴上ac代码:

class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        longest = head = 0
        visited = [False for _ in xrange(256)]
        for index, char in enumerate(s):
            if visited[ord(char)]:
                while s[head] != char:
                    visited[ord(s[head])] = False
                    head += 1
                head += 1
            else:
                visited[ord(char)] = True

            longest = max(longest, index - head + 1)
        return longest    

下面还是再次讲解一下正确的解题的思路。

1. 首先比较难懂的就是初始化了一个ascii表256个字符的东西,这个东西保证每个可能会出现的字符都可以被记载上,一旦出现就将其置为True。当然你也可以使用字典实现这个功能,这里就不赘述了。

2. 然后开启循环,依次对字符串进行遍历。

3. 看下当前char对应的ascii表里的数字为止的索引有没有被出现过。

4. 如果有出现过,那么开启循环并判断头部位置的字符是否等于循环的字符。这里提一下为什么要做这个判断。因为在判断字符串的时候可能出现连续的两个相同的字符,比如‘bba‘,‘bba‘进入循环的时候head地方和循环到的char将会是相等的所以直接让head+1 这个时候head是1 index是1 然后做longest计算的时候就可以得到正确的1位的答案。

5. 如果有第二次出现的字符,且head对应位置的字符与char不相等是什么情况呢。例如‘bapoiubcbd‘ 当遇到第二个b的时候会进入循环,这个时候head指针指向b于是head开始指向a。到这里为止都很正常,但是马上紧接着出现了第三个b这个时候我们在此进入循环,这个时候我们要做的是将指针一口气移动到第二个b的位置,并且清楚中间所有出现过的字符,为什么?开始介绍这个道题的时候就已经说了,这道理自习分析一下,其实就是在找两个相同字符之间的最大长度(除开边界条件抽象此题的话)。所以在第三个b出现的时候,应该移动指针到第二个b处。并且将中间的过掉的字符都重新置为没有访问过,这样在下面才可以进行第二次计算longest的长度,用来和出现过的最长longest比较。

这道题其他就没有什么好说的了。

 

 Median of Two Sorted Arrays:

There are two sorted arrays nums1 and nums2 of size m and n respectively.

Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).

Example 1:
nums1 = [1, 3]
nums2 = [2]

The median is 2.0
Example 2:
nums1 = [1, 2]
nums2 = [3, 4]

The median is (2 + 3)/2 = 2.5

 

此题是一个求中位数的问题,我拿到题的时候看了一下难度hard有点奇怪,正常解不是特别复杂,但是题目里要求了时间复杂度,可能这才是hard的关键吧。我拿到这题的时候思考了一下,因为两个给予的数组都是排过序的,但是我没想太多。其实如果用python自带排序函数sorted的话,可以将两个数组合并,然后进行排序。之后转化成了一个求中位数问题,区分一下奇偶,最后可以ac。可见sorted函数的排序非常高效。

 

另外在网上看了一种方法,是将此题转化成一个求kth的问题。我其实还是转换了半天,此题如何转换成一个kth的问题?首先我们可以将 m n 想成一个数组,即使是乱序,当然如果他们不是乱序,直接可以使用上面提到的办法,使用m+n 偶数/2-1 基数+1/2。

可以使用partition的办法来找到kth,那么可以保证在选择的一个数前面或者后面一定是有序的,这样在确定了整个数组长度之后,就能知道中位数应该是第几个数。由这第几个数转化为一个求kth的问题。

class Solution:  
    def findKthSortedArrays(self, A, B, k):  
        if len(A) < len(B):  
            A, B = B, A
        if len(B) == 0:  
            return A[k - 1]  
        if k == 1:  
            return min(A[0], B[0])  
  
        pb = min(k / 2, len(B))  
        pa = k - pb  
        if A[pa - 1] > B[pb - 1]:  
            return self.findKthSortedArrays(A, B[pb:], k - pb)  
        elif A[pa - 1] < B[pb - 1]:  
            return self.findKthSortedArrays(A[pa:], B, k - pa)  
        else:  
            return A[pa - 1]  
  
    # @return a float  
    def findMedianSortedArrays(self, A, B):  
        if (len(A) + len(B)) % 2 == 1:  
            return self.findKthSortedArrays(A, B, (len(A) + len(B)) / 2 + 1)  
        else:  
            return (self.findKthSortedArrays(A, B, (len(A) + len(B)) / 2) +  
                self.findKthSortedArrays(A, B, (len(A) + len(B)) / 2 + 1)) / 2.0 

以上。

 

周刷题第二期总结(Longest Substring Without Repeating Characters and Median of Two Sorted Arrays)