笔记仓库

正常人的正常笔记集

LeetCode Weekly Contest 114

https://leetcode.com/contest/weekly-contest-114

Verifying an Alien Dictionary

原题地址 https://leetcode.com/contest/weekly-contest-114/problems/verifying-an-alien-dictionary/

In an alien language, surprisingly they also use english lowercase letters, but possibly in a different order. The order of the alphabet is some permutation of lowercase letters.

Given a sequence of words written in the alien language, and the order of the alphabet, return true if and only if the given words are sorted lexicographicaly in this alien language.

Example 1:

1
2
3
Input: words = ["hello","leetcode"], order = "hlabcdefgijkmnopqrstuvwxyz"
Output: true
Explanation: As 'h' comes before 'l' in this language, then the sequence is sorted.

Example 2:

1
2
3
Input: words = ["word","world","row"], order = "worldabcefghijkmnpqstuvxyz"
Output: false
Explanation: As 'd' comes after 'l' in this language, then words[0] > words[1], hence the sequence is unsorted.

Example 3:

1
2
3
Input: words = ["apple","app"], order = "abcdefghijklmnopqrstuvwxyz"
Output: false
Explanation: The first three characters "app" match, and the second string is shorter (in size.) According to lexicographical rules "apple" > "app", because 'l' > '∅', where '∅' is defined as the blank character which is less than any other character (More info).

Note:

  1. 1 <= words.length <= 100
  2. 1 <= words[i].length <= 20
  3. order.length == 26
  4. All characters in words[i] and order are english lowercase letters.

按照题意估计是让你重写strcmp,我太懒了,直接把order映射到正常字母序对应的字母,重写把words中所有词写一遍。比较不需要自己写排序,检验排序是否正确,检查每个词是否大于等于前面的词就可以了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Solution(object):
def isAlienSorted(self, words, order):
"""
:type words: List[str]
:type order: str
:rtype: bool
"""
d = {c: i for i, c in enumerate(order)}

cur = ''.join([chr(ord('a') + d[c]) for c in words[0]])

for w in words:
temp = ''.join([chr(ord('a') + d[c]) for c in w])
if temp < cur:
return False
cur = temp

return True

Array of Doubled Pairs

原题地址 https://leetcode.com/contest/weekly-contest-114/problems/array-of-doubled-pairs/

Given an array of integers A with even length, return true if and only if it is possible to reorder it such that A[2 * i + 1] = 2 * A[2 * i] for every 0 <= i < len(A) / 2.

Example 1:

1
2
Input: [3,1,3,6]
Output: false

Example 2:

1
2
Input: [2,1,2,6]
Output: false

Example 3:

1
2
3
Input: [4,-2,2,-4]
Output: true
Explanation: We can take two groups, [-2,-4] and [2,4] to form [-2,-4,2,4] or [2,4,-2,-4].

Example 4:

1
2
Input: [1,2,4,16,8,4]
Output: false

Note:

  1. 0 <= A.length <= 30000
  2. A.length is even
  3. -100000 <= A[i] <= 100000

先对A的所有元素计数,从最小的数开始找到足够的它的二倍数元素,然后删去,形成数对,如果不够则无法成立。如果能取完所有元素则成立。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution(object):
def canReorderDoubled(self, A):
"""
:type A: List[int]
:rtype: bool
"""
d = collections.Counter(A)
nums = sorted(d.keys(), key=abs)

for i in nums:
if d[i] == 0:
continue
if 2 * i in d and d[2 * i] >= d[i]:
d[2 * i] -= d[i]
else:
return False

Delete Columns to Make Sorted II

原题地址 https://leetcode.com/contest/weekly-contest-114/problems/delete-columns-to-make-sorted-ii/

We are given an array A of N lowercase letter strings, all of the same length.

Now, we may choose any set of deletion indices, and for each string, we delete all the characters in those indices.

For example, if we have an array A = ["abcdef","uvwxyz"] and deletion indices {0, 2, 3}, then the final array after deletions is ["bef","vyz"].

Suppose we chose a set of deletion indices D such that after deletions, the final array has its elements in lexicographic order (A[0] <= A[1] <= A[2] ... <= A[A.length - 1]).

Return the minimum possible value of D.length.

Example 1:

1
2
3
4
5
6
Input: ["ca","bb","ac"]
Output: 1
Explanation:
After deleting the first column, A = ["a", "b", "c"].
Now A is in lexicographic order (ie. A[0] <= A[1] <= A[2]).
We require at least 1 deletion since initially A was not in lexicographic order, so the answer is 1.

Example 2:

1
2
3
4
5
6
Input: ["xc","yb","za"]
Output: 0
Explanation:
A is already in lexicographic order, so we don't need to delete anything.
Note that the rows of A are not necessarily in lexicographic order:
ie. it is NOT necessarily true that (A[0][0] <= A[0][1] <= ...)

Example 3:

1
2
3
4
Input: ["zyx","wvu","tsr"]
Output: 3
Explanation:
We have to delete every column.

Note:

  1. 1 <= A.length <= 100
  2. 1 <= A[i].length <= 100

当时第一次做944. Delete Columns to Make Sorted的时候看错题,当成这一题来理解了,所以这个改编也不是很复杂。

A的第i列已经是严格的升序时,后面不需要再排就已经满足lexicographic order了;当A的第i列不满足字母排序,那么第i列必须被删除,然后继续从第i+1列开始检查;如果满足非递减,但存在一些相等的情况,那么只需要把这些相等的行单独找出来按照相同的第i列分组,接下来从第i+1开始只需要检查相同的分组的元素的第i+1列是否令组内元素满足lexicographic order……

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
37
38
39
40
41
class Solution(object):
def minDeletionSize(self, A):
"""
:type A: List[str]
:rtype: int
"""
def is_sorted(arr, i):
cur = [arr[0]]
tier = []
for s in arr[1:]:
if s[i] < cur[-1][i]:
return False, []
elif s[i] == cur[-1][i]:
cur.append(s)
else:
tier.append(cur)
cur = [s]
if len(cur) > 1:
tier.append(cur)
return True, tier

tier = [A]
n = len(A[0])
res = 0

for i in range(n):
temp_tier = []
d = True
if not tier:
return res
for t in tier:
d, l = is_sorted(t, i)
if not d:
res += 1
break
else:
temp_tier += l
if d:
tier = temp_tier

return res

Tallest Billboard

原题地址 https://leetcode.com/contest/weekly-contest-114/problems/tallest-billboard/

You are installing a billboard and want it to have the largest height. The billboard will have two steel supports, one on each side. Each steel support must be an equal height.

You have a collection of rods which can be welded together. For example, if you have rods of lengths 1, 2, and 3, you can weld them together to make a support of length 6.

Return the largest possible height of your billboard installation. If you cannot support the billboard, return 0.

Example 1:

1
2
3
Input: [1,2,3,6]
Output: 6
Explanation: We have two disjoint subsets {1,2,3} and {6}, which have the same sum = 6.

Example 2:

1
2
3
Input: [1,2,3,4,5,6]
Output: 10
Explanation: We have two disjoint subsets {2,3,5} and {4,6}, which have the same sum = 10.

Example 3:

1
2
3
Input: [1,2]
Output: 0
Explanation: The billboard cannot be supported, so we return 0.

Note:

  1. 0 <= rods.length <= 20
  2. 1 <= rods[i] <= 1000
  3. The sum of rods is at most 5000.

把它当成背包问题。放在第一个分组则乘以1,放在第二个分组乘以-1,不取用则系数为0,最后相加结果为0,[1,2,3,4,5,6]写为0*1+1*2+1*3-1*4+1*5-1*6,数组最大和为max_sumdp[i][j]表示前i个数的和能否取到j-max_sum,如果能取到,这样的取法里面所有的正数最大和为max_abs[i][j],那么第i+1个数可以取正或负,dp[i+1][j]=dp[i][j-rods[i]]|dp[i][j]|dp[i+1][j+rods[i]],相应的更新max_abs

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
class Solution(object):
def tallestBillboard(self, rods):
"""
:type rods: List[int]
:rtype: int
"""
n = len(rods)
max_sum = sum(rods)
dp = [[False] * (2 * max_sum + 1) for _ in range(n + 1)]
max_abs = [[0] * (2 * max_sum + 1) for _ in range(n + 1)]
res = 0

for i in range(n + 1):
dp[i][max_sum] = True
for i in range(n):
for j in range(max_sum * 2 + 1):
if j - rods[i] >= 0 and dp[i][j - rods[i]]:
dp[1 + i][j] = True
max_abs[1 + i][j] = max(max_abs[1 + i]
[j], max_abs[i][j - rods[i]])
if j + rods[i] <= max_sum * 2 and dp[i][j + rods[i]]:
dp[i + 1][j] = True
max_abs[i + 1][j] = max(max_abs[i + 1]
[j], max_abs[i][j + rods[i]] + rods[i])
if dp[i][j]:
dp[1 + i][j] = True
max_abs[i + 1][j] = max(max_abs[i + 1][j], max_abs[i][j])
res = max(res, max_abs[i + 1][max_sum])
return res

这样做有些浪费。

相应的参考了一下别人的做法,通过交换分组可以发现j的取值是对称的,因此只要保存两组数之间的差值k,以及取这个差值时绝对值和较小的那组数的和min_abs,增加一个可以取的r时,k+r的值一定为正,保持它的min_abs不变即可,如果k>r那么差值为k-r时较小的那组数会再加上r且小于较大的,min_abs应该在原来的基础上加上r;如果r>k那么差值为r-k时,原来最小的那组数再加上k就是另一组数的和,而原来最小的那组数在加上r后变成较大的了,所以这时min_abs应该再加上k,最后返回差值为0min_abs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Solution(object):
def tallestBillboard(self, rods):
"""
:type rods: List[int]
:rtype: int
"""
max_abs = {0: 0}

for r in rods:
for k, v in max_abs.items():
max_abs[k + r] = max(max_abs.get(k + r, 0), v)
max_abs[abs(k - r)] = max(max_abs.get(abs(k - r), 0),
v + min(r, k))
return max_abs[0]