python练习(十六)

  • Permutation in String
    • 题目
    • 思路与解答
    • 答案
  • Flatten Nested List Iterator
    • 题目
    • 思路与解答
    • 答案
  • Count and Say
    • 题目
    • 思路与解答
    • 答案
  • Majority Element
    • 题目
    • 思路与解答
    • 答案
  • Count Primes
    • 题目
    • 思路与解答
    • 答案

注意,答案只是代表是他人写的代码,正确,但不一定能通过测试(比如超时),列举出来只是它们拥有着独到之处,虽然大部分确实比我的好

Permutation in String

题目

Given two strings s1 and s2, write a function to return true if s2 contains the permutation of s1. In other words, one of the first string’s permutations is the substring of the second string.

思路与解答

python是多么的便利啊
…包含排列就行,不能用in,那我用字典呗

class Solution(object):
    def checkInclusion(self, s1, s2):
        """
        :type s1: str
        :type s2: str
        :rtype: bool
        """
        d = collections.defaultdict(int)
        for s in s1:
            d[s] -= 1
        l = len(s1)
        for k,v in enumerate(s2):
            if k < l:
                d[v] += 1
                if not d[v]:del d[v]

            else:
                d[v] += 1
                d[s2[k-l]] -= 1
                if not d[v]: del d[v]
                if not d[s2[k-l]] : del d[s2[k-l]]

            if not d: return True
        return False

答案

def checkInclusion(self, s1, s2):
    A = [ord(x) - ord('a') for x in s1]
    B = [ord(x) - ord('a') for x in s2]

    target = [0] * 26
    for x in A:
        target[x] += 1

    window = [0] * 26
    for i, x in enumerate(B):
        window[x] += 1
        if i >= len(A):
            window[B[i - len(A)]] -= 1
        if window == target:
            return True
    return False

我觉得这种是没我的好的(果然比我的慢)

class Solution(object):
    def checkInclusion(self, s1, s2):
        return len(self.minWindow(s2, s1)) == len(s1)

    # Copied&pasted old problem's solution
    def minWindow(self, s, t):
        need, missing = collections.Counter(t), len(t)
        i = I = J = 0
        for j, c in enumerate(s, 1):
            missing -= need[c] > 0
            need[c] -= 1
            if not missing:
                while i < j and need[s[i]] < 0:
                    need[s[i]] += 1
                    i += 1
                if not J or j - i <= J - I:
                    I, J = i, j
        return s[I:J]

我去这个比我的要慢一倍,但是思路有趣

Flatten Nested List Iterator

题目

Given a nested list of integers, implement an iterator to flatten it.

Each element is either an integer, or a list – whose elements may also be integers or other lists.

Example 1:
Given the list [[1,1],2,[1,1]],

By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,1,2,1,1].

Example 2:
Given the list [1,[4,[6]]],

By calling next repeatedly until hasNext returns false, the order of elements returned by next should be: [1,4,6].

思路与解答

脑子里有些骚操作?
题目要求死了,并不能骚起来。。。
本来想用yield的,后来发现不好用

才注意给了辅助函数了
。。。。。。mmp,辅助函数怎么不能调用???


    def __init__(self, nestedList):
        """
        Initialize your data structure here.
        :type nestedList: List[NestedInteger]
        """
        self.l = nestedList[::-1]

    def next(self):
        """
        :rtype: int
        """
        return self.l.pop().getInteger()

    def hasNext(self):
        """
        :rtype: bool
        """
        while True:
            if self.l[-1].isInetger():
                return True
            else:
                self.l += self.l.pop().getList()[::-1]
            if not self.l:
                return False

isInteger()这个函数我在复制名字的时候出错了?!
一定是该死的鼠标的问题

class NestedIterator(object):

    def __init__(self, nestedList):
        """
        Initialize your data structure here.
        :type nestedList: List[NestedInteger]
        """
        self.l = nestedList[::-1]

    def next(self):
        """
        :rtype: int
        """
        return self.l.pop().getInteger()

    def hasNext(self):
        """
        :rtype: bool
        """
        while True:
            if not self.l:
                return False
            if self.l[-1].isInteger():
                return True
            else:
                self.l += self.l.pop().getList()[::-1]

判断为空要放到最前面去判断,不然会超出数列

答案

class NestedIterator(object):

    def __init__(self, nestedList):
        """
        Initialize your data structure here.
        :type nestedList: List[NestedInteger]
        """
        self.stack = nestedList[::-1]

    def next(self):
        """
        :rtype: int
        """
        return self.stack.pop().getInteger()

    def hasNext(self):
        """
        :rtype: bool
        """
        while self.stack:
            top = self.stack[-1]
            if top.isInteger():
                return True
            self.stack = self.stack[:-1] + top.getList()[::-1]
        return False

唔。。可以不用while True

class NestedIterator(object):

    def __init__(self, nestedList):
        self.stack = [[nestedList, 0]]

    def next(self):
        self.hasNext()
        nestedList, i = self.stack[-1]
        self.stack[-1][1] += 1
        return nestedList[i].getInteger()

    def hasNext(self):
        s = self.stack
        while s:
            nestedList, i = s[-1]
            if i == len(nestedList):
                s.pop()
            else:
                x = nestedList[i]
                if x.isInteger():
                    return True
                s[-1][1] += 1
                s.append([x.getList(), 0])
        return False

唔。。。。

    def __init__(self, nestedList):
        def gen(nestedList):
            for x in nestedList:
                if x.isInteger():
                    yield x.getInteger()
                else:
                    for y in gen(x.getList()):
                        yield y
        self.gen = gen(nestedList)

    def next(self):
        return self.value

    def hasNext(self):
        try:
            self.value = next(self.gen)
            return True
        except StopIteration:
            return False

生成器方案,我本来也有想到这个思路,但是不会写。。。。

Count and Say

题目

The count-and-say sequence is the sequence of integers with the first five terms as following:

  1. 1
  2. 11
  3. 21
  4. 1211
  5. 111221
    1 is read off as “one 1” or 11.
    11 is read off as “two 1s” or 21.
    21 is read off as “one 2, then one 1” or 1211.
    Given an integer n, generate the nth term of the count-and-say sequence.

Note: Each term of the sequence of integers will be represented as a string.

Example 1:

Input: 1
Output: “1”
Example 2:

Input: 4
Output: “1211”

思路与解答

??????
啥意思
去搜了遍描述,这题有意思。。。不过真的是easy的吗?

class Solution(object):
    def countAndSay(self, n):
        s = ['1']
        result = '1'

        for i in range(n-1):
            start = 0
            temp = []
            while start < len(s):
                count = 1
                next = start + 1
                while next < len(s) and s[start] == s[next]:
                    next += 1
                    count += 1
                temp.append(str(count))
                temp.append(s[start])
                start = next
            result = ''.join(temp)
            s = temp
        return result

答案

解决方案1 ...使用正则表达式

def countAndSay(self, n):
    s = '1'
    for _ in range(n - 1):
        s = re.sub(r'(.)\1*', lambda m: str(len(m.group(0))) + m.group(1), s)
    return s
解决方案2 ...使用正则表达式

def countAndSay(self, n):
    s = '1'
    for _ in range(n - 1):
        s = ''.join(str(len(group)) + digit
                    for group, digit in re.findall(r'((.)\2*)', s))
    return s
解决方案3 ...使用groupby

def countAndSay(self, n):
    s = '1'
    for _ in range(n - 1):
        s = ''.join(str(len(list(group))) + digit
                    for digit, group in itertools.groupby(s))
    return s

……

Majority Element

题目

Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.

You may assume that the array is non-empty and the majority element always exist in the array.

Credits:
Special thanks to @ts for adding this problem and creating all test cases.

思路与解答

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        d,l = collections.defaultdict(int),len(nums)/2
        for num in nums:
            d[num] += 1
            if d[num] > l:
                return num

答案

return sorted(num)[len(num)/2]

很棒的思路,即使不够快

# two pass + dictionary
def majorityElement1(self, nums):
    dic = {}
    for num in nums:
        dic[num] = dic.get(num, 0) + 1
    for num in nums:
        if dic[num] > len(nums)//2:
            return num

# one pass + dictionary
def majorityElement2(self, nums):
    dic = {}
    for num in nums:
        if num not in dic:
            dic[num] = 1
        if dic[num] > len(nums)//2:
            return num
        else:
            dic[num] += 1 

# TLE
def majorityElement3(self, nums):
    for i in xrange(len(nums)):
        count = 0
        for j in xrange(len(nums)):
            if nums[j] == nums[i]:
                count += 1
        if count > len(nums)//2:
            return nums[i]

# Sotring            
def majorityElement4(self, nums):
    nums.sort()
    return nums[len(nums)//2]

# Bit manipulation    
def majorityElement5(self, nums):
    bit = [0]*32
    for num in nums:
        for j in xrange(32):
            bit[j] += num >> j & 1
    res = 0
    for i, val in enumerate(bit):
        if val > len(nums)//2:
            # if the 31th bit if 1, 
            # it means it's a negative number 
            if i == 31:
                res = -((1<<31)-res)
            else:
                res |= 1 << i
    return res

# Divide and Conquer
def majorityElement6(self, nums):
    if not nums:
        return None
    if len(nums) == 1:
        return nums[0]
    a = self.majorityElement(nums[:len(nums)//2])
    b = self.majorityElement(nums[len(nums)//2:])
    if a == b:
        return a
    return [b, a][nums.count(a) > len(nums)//2]

# the idea here is if a pair of elements from the
# list is not the same, then delete both, the last 
# remaining element is the majority number
def majorityElement(self, nums):
    count, cand = 0, 0
    for num in nums:
        if num == cand:
            count += 1
        elif count == 0:
            cand, count = num, 1
        else:
            count -= 1
    return cand

可以有一万种方法来解这道题

Count Primes

题目

Count the number of prime numbers less than a non-negative number, n.

思路与解答

题目不太好懂啊
prime numbers 是质数,好吧。。

class Solution(object):
    def countPrimes(self, n):
        """
        :type n: int
        :rtype: int
        """
        if n < 3:return 0
        res = 1
        for i in xrange(3,n):
            for x in xrange(2,i):
                if not i%x:
                    break
            else:      
                res += 1
        return res

超时了,应该是有什么快速方法吧

        if n < 3:return 0
        res = 1
        l =[2]
        for i in xrange(3,n):
            for x in l:
                if not i%x:
                    break
            else: 
                l.append(i)
                res += 1
        return res

修改办,依然超时
不知道如何优化了

答案

def countPrimes(self, n):
    if n <= 2:
        return 0
    res = [True] * n
    res[0] = res[1] = False
    for i in xrange(2, n):
        if res[i] == True:
            for j in xrange(i, (n-1)/i+1):
                res[i*j] = False
    return sum(res)

900+ms版

        if n < 3:
            return 0
        arr = [True] * n
        arr[0] = arr[1] = False
        for i in range(2, int(n ** 0.5) + 1):
            if arr[i]:
                arr[i*i:n:i] = [False] * ((n - 1) // i - i + 1)
        return arr.count(True)  

200+ms版!
还有这么骚气的操作?
埃拉托斯特尼筛法
证明:
利用反证法:假设这样筛出来的N是合数,且不能被小于等于其平方根的所有素数整除,那么N一定能被大于其平方根小于其本身的某个素数整除.记该素数为M,则√N

暂时不更了

你可能感兴趣的:(学习之旅)