Leetcode 算法題04

感覺這裏開始的題目開始有難度,不再是想到什麼寫什麼也能通過,要理清思路

696. Count Binary Substrings

給一個字符串s,計算具有相同數字0和1的非空(連續)子字符串的數量,並且這些子字符串中的所有0和所有1都被連續分組。
發生多次的子字符串將被計數它們發生的次數。

Example 1:

Input: "00110011"
Output: 6
Explanation: There are 6 substrings that have equal number of consecutive 1's and 0's: "0011", "01", "1100", "10", "0011", and "01".

Notice that some of these substrings repeat and are counted the number of times they occur.
Also, "00110011" is not a valid substring because all the 0's (and 1's) are not grouped together.

Example 2:

Input: "10101"
Output: 4
Explanation: There are 4 substrings: "10", "01", "10", "01" that have equal number of consecutive 1's and 0's.
第一次又超時了,看來一般在循環中加循環是個很不好的習慣,下面是錯誤示例:

class Solution(object):
    def countBinarySubstrings(self, s):
        """
        :type s: str
        :rtype: int
        """
        counts = 0
        for i in range(len(s)-1):
            if s[i] != s[i+1]:
                count = 0
                for j in range(min(i+1,len(s)-i-1)):
                    if s[i-j] == s[i] and s[i+1+j] == s[i+1]:
                        count += 1
                    else:
                        break
                counts += count
        return counts
以下是思考後的代碼:

class Solution(object):
    def countBinarySubstrings(self, s):
        """
        :type s: str
        :rtype: int
        """
        num={'0':0,'1':0}
        count = 0
        for i in range(len(s)-1):
            if s[i] == s[i+1]:
                num[s[i]] += 1
            elif s[i] != s[i+1]:
                num[s[i]] += 1
                if num[s[i+1]] == 0:
                    pass
                else:
                    count += min(num['0'],num['1'])
                    num[s[i+1]] = 0
        num[s[-1]] += 1
        count += min(num['0'],num['1'])
        return count
大神的代碼:第一種方法思路和我一致,代碼簡潔一點

Here are some examples:

  • '00001111' => [4, 4] => min(4, 4) => 4
  • '00110' => [2, 2, 1] => min(2, 2) + min(2, 1) => 3
  • '10101' => [1, 1, 1, 1, 1] => 4
class Solution(object):
    def countBinarySubstrings(self, s):
        chunks, consecutive, res = [], 1, 0
        for i in range(1, len(s)):
            if s[i] == s[i - 1]:
                consecutive += 1
            else:
                chunks.append(consecutive)
                consecutive = 1
        chunks.append(consecutive)
        for i in range(1, len(chunks)):
            res += min(chunks[i], chunks[i - 1])
        return res

An alternative way is to find the positions where the bits flip and we can derive the chunks from the positions of the flips.

class Solution(object):
    def countBinarySubstrings(self, s):
        flips, res = [0], 0
        for i in range(1, len(s)):
            if s[i] != s[i - 1]:
                flips.append(i)
        flips.append(len(s))
        chunks = [a - b for (a, b) in zip(flips[1:], flips)]
        for i in range(1, len(chunks)):
            res += min(chunks[i], chunks[i - 1])
        return res

A compressed 3-liner version of the above will look like this:

class Solution(object):
    def countBinarySubstrings(self, s):
        flips = [0] + [i for i in range(1, len(s)) if s[i] != s[i - 1]] + [len(s)]
        chunks = [a - b for (a, b) in zip(flips[1:], flips)]
        return sum(min(a, b) for a, b in zip(chunks, chunks[1:]))
另一個大大神:思路清晰

First, I count the number of 1 or 0 grouped consecutively.
For example "0110001111" will be [1, 2, 3, 4].

Second, for any possible substrings with 1 and 0 grouped consecutively, the number of valid substring will be the minimum number of 0 and 1.
For example "0001111", will be min(3, 4) = 3, ("01", "0011", "000111")

def countBinarySubstrings(self, s):
        s = map(len, s.replace('01', '0 1').replace('10', '1 0').split())
        return sum(min(a, b) for a, b in zip(s, s[1:]))



690. Employee Importance

[1,5,[2,3]]分別代表職員id,重要值和其下屬id,給定所有職工信息與一個id,求這個id的職工重要值和其所有下屬重要值之和

Example 1:

Input: [[1, 5, [2, 3]], [2, 3, []], [3, 3, []]], 1
Output: 11
Explanation:
Employee 1 has importance value 5, and he has two direct subordinates: employee 2 and employee 3. They both have importa
奇怪的是,我第一份代碼在我自己環境下能跑,在leetcode裏卻會報錯

"""
# Employee info
class Employee(object):
    def __init__(self, id, importance, subordinates):
        # It's the unique id of each node.
        # unique id of this employee
        self.id = id
        # the importance value of this employee
        self.importance = importance
        # the id of direct subordinates
        self.subordinates = subordinates
"""
class Solution(object):
    def getImportance(self, employees, id):
        """
        :type employees: Employee
        :type id: int
        :rtype: int
        """
        def findid(employees, id):
            for i in employees:
                if i[0] == id:   #TypeError: 'Employee' object does not support indexing
                    return i
        ans = findid(employees, id)[1]
        for j in findid(employees, id)[2]:
            ans += findid(employees, j)[1]
        return ans
仔細看了代碼前一段,發現可能emoployees裏包含的是它定義的Employee類,不是list類,稍微改一下就好了,感慨小白基礎TT,不過確實這樣分類更好用,代碼也更易懂
    def getImportance(self, employees, id):
        """
        :type employees: Employee
        :type id: int
        :rtype: int
        """
        def findid(employees, id):
            for i in employees:
                if i.id == id:
                    return i
        ans = findid(employees, id).importance
        for j in findid(employees, id).subordinates:
            ans += findid(employees, j).importance
        return ans
但是又報錯,發現要求是所有下屬,包括下下屬,需要用遞歸,繼續改:

"""
# Employee info
class Employee(object):
    def __init__(self, id, importance, subordinates):
        # It's the unique id of each node.
        # unique id of this employee
        self.id = id
        # the importance value of this employee
        self.importance = importance
        # the id of direct subordinates
        self.subordinates = subordinates
"""
class Solution(object):
    def getImportance(self, employees, id):
        """
        :type employees: Employee
        :type id: int
        :rtype: int
        """
        def findid(employees, id):
            for i in employees:
                if i.id == id:
                    return i
        if findid(employees, id).subordinates == []:
            return findid(employees, id).importance
        else:
            ans = findid(employees, id).importance
            for sub in findid(employees, id).subordinates:
                ans += self.getImportance(employees,sub)
            return ans
大神的代碼:我決定看一遍樹

Simply convert the employees array/list into a map for easy lookup and then do a DFS traversal from the "root" employee node.

By Yang Shun

class Solution(object):
    def getImportance(self, employees, id):
        """
        :type employees: Employee
        :type id: int
        :rtype: int
        """
        # Time: O(n)
        # Space: O(n)
        emps = {employee.id: employee for employee in employees}
        dfs = lambda id: sum([dfs(sub_id) for sub_id in emps[id].subordinates]) + emps[id].importance
        return dfs(id)         

If you wanna make it more readable, it is 5-lines:

class Solution(object):
    def getImportance(self, employees, id):
        """
        :type employees: Employee
        :type id: int
        :rtype: int
        """
        # Time: O(n)
        # Space: O(n)
        emps = {employee.id: employee for employee in employees}
        def dfs(id):
            subordinates_importance = sum([dfs(sub_id) for sub_id in emps[id].subordinates])
            return subordinates_importance + emps[id].importance
        return dfs(id)

695. Max Area of Island

求最大島嶼面積,上下相連,斜着不相連

Example 1:

[[0,0,1,0,0,0,0,1,0,0,0,0,0],
 [0,0,0,0,0,0,0,1,1,1,0,0,0],
 [0,1,1,0,1,0,0,0,0,0,0,0,0],
 [0,1,0,0,1,1,0,0,1,0,1,0,0],
 [0,1,0,0,1,1,0,0,1,1,1,0,0],
 [0,0,0,0,0,0,0,0,0,0,1,0,0],
 [0,0,0,0,0,0,0,1,1,1,0,0,0],
 [0,0,0,0,0,0,0,1,1,0,0,0,0]]
Given the above grid, return 6. Note the answer is not 11, because the island must be connected 4-directionally.

Example 2:

[[0,0,0,0,0,0,0,0]]
Given the above grid, return 0.

我的代碼:想了我好久,今天一天都沒怎麼學別的了TT

class Solution(object):
    def maxAreaOfIsland(self, grid):
        """
        :type grid: List[List[int]]
        :rtype: int
        """
        def cal_point(grid,x,y,lists,around):
            if x != 0 and grid[y][x-1] == 1 and [x-1,y] not in lists:
                lists.append([x-1,y])
                around.append([x-1,y])
            if x != len(grid[0])-1 and grid[y][x+1] == 1 and [x+1,y] not in lists:
                lists.append([x+1,y])
                around.append([x+1,y])
            if y != 0 and grid[y-1][x] == 1 and [x,y-1] not in lists:
                lists.append([x,y-1])
                around.append([x,y-1])
            if y !=len(grid)-1 and grid[y+1][x] == 1 and [x,y+1] not in lists:
                lists.append([x,y+1])
                around.append([x,y+1])
            return lists,around
        
        def cal_area(grid,x,y):
            lists,around = cal_point(grid,x,y,[[x,y]],[])
            while True:
                if around == []:
                    return lists,len(lists)
                else:
                    lists,around = cal_point(grid,around[0][0],around[0][1],lists,around)
                    around.pop(0)
                    
        temp = []
        ans = 0
        for y in range(len(grid)):
            for x in range(len(grid[0])):
                if grid[y][x] == 1 and [x,y] not in temp:
                    lists , lens = cal_area(grid,x,y)
                    print(lists)
                    temp += lists
                    ans = max(ans,lens)
        return ans
大神的代碼,這個真的可以看出差距
 def maxAreaOfIsland(self, grid):
        m, n = len(grid), len(grid[0])

        def dfs(i, j):
            if 0 <= i < m and 0 <= j < n and grid[i][j]:
                grid[i][j] = 0
                return 1 + dfs(i - 1, j) + dfs(i, j + 1) + dfs(i + 1, j) + dfs(i, j - 1)
            return 0

        areas = [dfs(i, j) for i in range(m) for j in range(n) if grid[i][j]]
        return max(areas) if areas else 0

520. Detect Capital

判別字符大小寫是否正確,用正則表達式比較簡單,廖雪峯的教程:

https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386832260566c26442c671fa489ebc6fe85badda25cd000

Example 1:

Input: "USA"
Output: True

Example 2:

Input: "FlaG"
Output: False
我的代碼:

import re
class Solution(object):
    def detectCapitalUse(self, word):
        """
        :type word: str
        :rtype: bool
        """
        if re.match(r'^[A-Z]+$|^[a-z]+$|^[A-Z][a-z]+$', word):
            return True
        else:
            return False
大神的代碼:原來python還有這樣的函數!

def detectCapitalUse(self, word):
    return word.isupper() or word.islower() or word.istitle()

389. Find the Difference

給出一個字符串s,打亂並加入一個字符成爲字符串t,找出加入的新字符

Example:

Input:
s = "abcd"
t = "abcde"

Output:
e

Explanation:
'e' is the letter that was added.
我的代碼:開始以爲新加的字符不可以重複,結果來個‘aa'的測試,那麼進行生成列表排序相對比就好了

class Solution(object):
    def findTheDifference(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: str
        """
        list_s = [i for i in s]
        list_t = [j for j in t]
        list_s.sort()
        list_t.sort()           #這裏幾步可以用sorted(s)代替
        for i in range(len(s)):
            if list_s[i] != list_t[i]:
                return list_t[i]
        return list_t[-1]
大神的代碼:

Using XOR: 異或真的是個很有用的東西,先把每個字符通過ord換成獨一的數字,每個進行異或後就只剩下多的那個了

class Solution(object):
    def findTheDifference(self, s, t):
        return chr(reduce(operator.xor, map(ord, s + t)))

Using collections.Counter():這個collections需要導入,可以參考廖雪峯的教程:

https://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001411031239400f7181f65f33a4623bc42276a605debf6000

class Solution(object):
    def findTheDifference(self, s, t):
        return list((collections.Counter(t) - collections.Counter(s)))[0]

A 2-liner here using sorted():

class Solution(object):
    def findTheDifference(self, s, t):
        s, t = sorted(s), sorted(t)
        return t[-1] if s == t[:-1] else [x[1] for x in zip(s, t) if x[0] != x[1]][0]

258. Add Digits

將輸入的數字按位相加,反覆至結果爲一位數

For example:

Given num = 38, the process is like: 3 + 8 = 111 + 1 = 2. Since 2 has only one digit, return it.

我的代碼:

class Solution(object):
    def addDigits(self, num):
        """
        :type num: int
        :rtype: int
        """
        def numsum(n):
            return reduce(lambda x,y:x+y,[int(i) for i in str(n)])
        while num > 9:
            num = numsum(num)
        return num
大神的代碼:用了一個巧妙的辦法:

this method depends on the truth:

N=(a[0] * 1 + a[1] * 10 + ...a[n] * 10 ^n),and a[0]...a[n] are all between [0,9]

we set M = a[0] + a[1] + ..a[n]

and another truth is that:

1 % 9 = 1

10 % 9 = 1

100 % 9 = 1

so N % 9 = a[0] + a[1] + ..a[n]

means N % 9 = M

so N = M (% 9)

as 9 % 9 = 0,so we can make (n - 1) % 9 + 1 to help us solve the problem when n is 9.as N is 9, ( 9 - 1) % 9 + 1 = 9

class Solution(object):
def addDigits(self, num):
    """
    :type num: int
    :rtype: int
    """
    if num == 0 : return 0
    else:return (num - 1) % 9 + 1

448. Find All Numbers Disappeared in an Array

給一個由n個數字組成的序列(1<=數字<=n),其中有些數字出現2次,那麼1~n中會有數字缺失,找出這些缺失的數字,要求複雜度O(n)

Example:

Input:
[4,3,2,7,8,2,3,1]

Output:
[5,6]
我的代碼:知道用set就能通過了

class Solution(object):
    def findDisappearedNumbers(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        set1 = set(nums)
        set2 = set([i+1 for i in range(len(nums))])
        return list(set2-set1)
其他思路:

class Solution(object):
    def findDisappearedNumbers(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        # For each number i in nums,
        # we mark the number that i points as negative.
        # Then we filter the list, get all the indexes
        # who points to a positive number
        for i in xrange(len(nums)):
            index = abs(nums[i]) - 1
            nums[index] = - abs(nums[index])

        return [i + 1 for i in range(len(nums)) if nums[i] > 0]





發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章