0%

leetcode contest 53 solution

本次题解包括

    1. Stickers to Spell Word
    1. Binary Number with Alternating Bits
    1. Number of Distinct Islands
    1. Max Area of Island

691. Stickers to Spell Word

We are given N different types of stickers. Each sticker has a lowercase English word on it.

You would like to spell out the given target string by cutting individual letters from your collection of stickers and rearranging them.

You can use each sticker more than once if you want, and you have infinite quantities of each sticker.

What is the minimum number of stickers that you need to spell out the target? If the task is impossible, return -1.

Example 1:

Input:

1
["with", "example", "science"], "thehat"

Output:

1
3

Explanation:

1
2
3
We can use 2 "with" stickers, and 1 "example" sticker.
After cutting and rearrange the letters of those stickers, we can form the target "thehat".
Also, this is the minimum number of stickers necessary to form the target string.

Example 2:

Input:

1
["notice", "possible"], "basicbasic"

Output:

1
-1

Explanation:

1
We can't form the target "basicbasic" from cutting letters from the given stickers.

Note:

  • stickers has length in the range [1, 50].
  • stickers consists of lowercase English words (without apostrophes).
  • target has length in the range [1, 15], and consists of lowercase English letters.
  • In all test cases, all words were chosen randomly from the 1000 most common US English words, and the target was chosen as a concatenation of two random words.
  • The time limit may be more challenging than usual. It is expected that a 50 sticker test case can be solved within 35ms on average.

题目地址:leetcode Stickers to Spell Word

题目大意:给定n个stickers,每个stickers可以使用无数次。现在要将stickers拼成target(就是拆分stickers中的字母来凑成target),求用最少的使用次数(使用同一个sticker两次次数算2)使得stickers可以组成target。

思路:

这题对时间要求很高。

要注意剪枝。很重要的一点就是只保留target的字符,然后去除被包含的所有stickers.

比如target为abc,stickers=['afg','abf']只保留stickers=['a','ab'],第一个被第二个包含,因此stickers=['ab'],这样能保证结果不差,而需要搜索的空间大大减少。

然后BFS即可。

python BFS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Solution:
def minStickers(self, stickers, target):
"""
:type stickers: List[str]
:type target: str
:rtype: int
"""
alphabet = [chr(i) for i in range(ord('a'), ord('z') + 1)]
target_cnt = collections.Counter(target)
stickers = [collections.Counter(s) & target_cnt for s in stickers]
for i in range(len(stickers) - 1, -1, -1):
if any(stickers[i] == (stickers[i] & stickers[j]) for j in range(len(stickers)) if i != j):
stickers.pop(i)

q = collections.deque()
q.append((0, target))
vis = {target}
while q:
step, pre = q.popleft()
pre_cnt = collections.Counter(pre)
for sticker in stickers:
cur = ''.join(c * max(0, pre_cnt.get(c, 0) - sticker.get(c, 0)) for c in alphabet)
if len(cur) == len(target): continue # the sticker should not use.
if not cur: return step + 1 # done
if cur not in vis:
q.append((step + 1, cur))
vis.add(cur)
return -1

DFS + 记忆化搜索超时了。。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
class Solution:
def minStickers(self, stickers, target):
"""
:type stickers: List[str]
:type target: str
:rtype: int
"""

def dfs(target, dp):
if not target: return 0
if target in dp: return dp[target]
target_cnt = collections.Counter(target)
ans = len(target) + 1
for sticker in stickers:
cur = ''.join(c * max(0, target_cnt.get(c, 0) - sticker.get(c, 0)) for c in alphabet)
if len(cur) == len(target): continue # the sticker should not use.
cnt = dfs(cur, dp)
if cnt != -1:
ans = min(ans, cnt + 1)
dp[target] = ans if ans != len(target) + 1 else -1
return dp[target]

alphabet = [chr(i) for i in range(ord('a'), ord('z') + 1)]
target_cnt = collections.Counter(target)
stickers = [collections.Counter(s) & target_cnt for s in stickers]
for i in range(len(stickers) - 1, -1, -1):
if any(stickers[i] == (stickers[i] & stickers[j]) for j in range(len(stickers)) if i != j):
stickers.pop(i)
dp = {}
return dfs(target, dp)

 


693. Binary Number with Alternating Bits

Given a positive integer, check whether it has alternating bits: namely, if two adjacent bits will always have different values.

Example 1:

1
2
3
4
Input: 5
Output: True
Explanation:
The binary representation of 5 is: 101

Example 2:

1
2
3
4
Input: 7
Output: False
Explanation
The binary representation of 7 is: 111.

Example 3:

1
2
3
4
Input: 11
Output: False
Explanation:
The binary representation of 11 is: 1011.

Example 4:

1
2
3
4
Input: 10
Output: True
Explanation:
The binary representation of 10 is: 1010.

题目地址:leetcode Binary Number with Alternating Bits

题目大意:给定一个数字,判断其是否1和0交替出现

思路

方法一

直接移位判断

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution:
def hasAlternatingBits(self, n):
"""
:type n: int
:rtype: bool
"""
pre = n & 1
n = n >> 1
while n:
if n & 1 == pre:
return False
pre = n & 1
n >>= 1
return True

方法二:

位运算,如果一个数是交替出现的,那么t = n ^ (n >> 1)必全部为1. 因此 如果(t + 1) & t为0,那么说明为交替出现。

1
2
3
4
5
6
7
8
class Solution(object):
def hasAlternatingBits(self, n):
"""
:type n: int
:rtype: bool
"""
t = n ^ (n >> 1)
return (t + 1) & t == 0

 


695. Max Area of Island

Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water.

Find the maximum area of an island in the given 2D array. (If there is no island, the maximum area is 0.)

Example 1:

1
2
3
4
5
6
7
8
[[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:

1
[[0,0,0,0,0,0,0,0]]

Given the above grid, return 0.

Note: The length of each dimension in the given grid does not exceed 50.

题目地址:leetcode Max Area of Island

题目大意:给你一个二维数组,小岛用1表示,求小岛的个数。

思路

dfs即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Solution:
def maxAreaOfIsland(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""

def dfs(x, y, vis):
if vis[x][y]: return
vis[x][y] = True
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
if 0 <= nx < m and 0 <= ny < n and not vis[nx][ny]:
self.cur += 1
dfs(nx, ny, vis)
self.ans = max(self.ans, self.cur)

if not grid or not grid[0]: return 0
m = len(grid)
n = len(grid[0])
dx = [1, -1, 0, 0]
dy = [0, 0, 1, -1]
self.ans = 0
vis = [[False if grid[x][y] else True for y in range(n)] for x in range(m)]
for i in range(m):
for j in range(n):
if grid[i][j]:
self.cur = 1
dfs(i, j, vis)
return self.ans

 


694. Number of Distinct Islands

Given a non-empty 2D array grid of 0's and 1's, an island is a group of 1's (representing land) connected 4-directionally (horizontal or vertical.) You may assume all four edges of the grid are surrounded by water.

Count the number of distinct islands. An island is considered to be the same as another if and only if one island can be translated (and not rotated or reflected) to equal the other.

Example 1:

1
2
3
4
11000
11000
00011
00011

Given the above grid map, return 1.

Example 2:

1
2
3
4
11011
10000
00001
11011

Given the above grid map, return 3.

Notice that:

1
2
11
1

and

1
2
1
11

are considered different island shapes, because we do not consider reflection / rotation.

Note: The length of each dimension in the given grid does not exceed 50.

题目地址:leetcode Number of Distinct Islands

题目大意:和上面一题差不多。求独特的小岛的个数。独特的为不能经过平移得到的(即形状不同)

思路:

DFS,然后hash记录小岛形状。

平移的话可以记录各个小岛的每个点相对于该小岛的最左上角的偏移,然后最左上角移动到(0,0)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
class Solution:
def numDistinctIslands(self, grid):
"""
:type grid: List[List[int]]
:rtype: int
"""

def dfs(x, y, vis):
if vis[x][y]: return
self.cur.append([x, y])
vis[x][y] = True
for i in range(4):
nx = x + dx[i]
ny = y + dy[i]
if 0 <= nx < m and 0 <= ny < n and not vis[nx][ny]:
dfs(nx, ny, vis)

if not grid or not grid[0]: return 0
m = len(grid)
n = len(grid[0])
dx = [1, -1, 0, 0]
dy = [0, 0, 1, -1]
vis = [[False if grid[x][y] else True for y in range(n)] for x in range(m)]
ans = set()
for i in range(m):
for j in range(n):
if grid[i][j]:
self.cur = []
dfs(i, j, vis)
if self.cur:
for k in range(1, len(self.cur)):
self.cur[k][0] = self.cur[k][0] - self.cur[0][0]
self.cur[k][1] = self.cur[k][1] - self.cur[0][1]
self.cur[0] = [0, 0]
ans.add(':'.join([str(x) + ',' + str(y) for x, y in self.cur]))
return len(ans)

 

本文是leetcode如下的题解

    1. Stickers to Spell Word
    1. Binary Number with Alternating Bits
    1. Number of Distinct Islands
    1. Max Area of Island

更多题解可以查看: https://www.hrwhisper.me/leetcode-algorithm-solution/

请我喝杯咖啡吧~