905. 按奇偶排序数组
- 题目难度
Easy
给定一个非负整数数组 A
,返回一个由 A
的所有偶数元素组成的数组,后面跟 A
的所有奇数元素。
你可以返回满足此条件的任何数组作为答案。
示例:
输入:[3,1,2,4]
输出:[2,4,3,1]
输出 [4,2,3,1],[2,4,1,3] 和 [4,2,1,3] 也会被接受。
提示:
1 <= A.length <= 5000
0 <= A[i] <= 5000
思路:
没有空间复杂度要求的话,可以开两个数组,一个存储偶数,另一个存储奇数,然后一边遍历原数组一边统计,遍历后把偶数数组和奇数数组连接起来输出即可。
如果要求不另开数组,在原数组上操作的话,那么需要用双指针遍历。双指针遍历有两种方法:一种是双指针同向遍历,初始状态都指在数组左端,后面指针不断加一,遇到偶数就交换到前面去,再把前面指针加一,指导后面指针遍历完数组结束;另外一种是双指针相向遍历,初始状态是第一个指针指在数组左端,第二个指针指在数组右端,当两个指针没有相遇时,右边指针向左寻找偶数,左边指针向右寻找奇数,然后交换指针所指的两个元素,直到两个指针相遇为止。
时间复杂度
空间复杂度
代码:
有辅助数组的算法
class Solution:
def sortArrayByParity(self, A):
"""
:type A: List[int]
:rtype: List[int]
"""
ans1 = []
ans2 = []
for i in A:
if i % 2 == 0:
ans1.append(i)
else:
ans2.append(i)
return ans1 + ans2
双指针同向遍历
class Solution:
def sortArrayByParity(self, A):
"""
:type A: List[int]
:rtype: List[int]
"""
i = 0
for j in range(len(A)):
if A[j] % 2 == 0:
A[i], A[j] = A[j], A[i]
i += 1
return A
双指针相向遍历
class Solution(object):
def sortArrayByParity(self, A):
"""
:type A: List[int]
:rtype: List[int]
"""
l = len(A)
i, j = 0, l-1
while i < j:
while A[i] % 2 == 0 and i < j:
i += 1
while A[j] % 2 == 1 and i < j:
j -= 1
A[i], A[j] = A[j], A[i]
return A
904. 水果成篮
- 题目难度
Medium
在一排树中,第 i
棵树产生 tree[i]
型的水果。
你可以从你选择的任何树开始,然后重复执行以下步骤:
- 把这棵树上的水果放进你的篮子里。如果你做不到,就停下来。
- 移动到当前树右侧的下一棵树。如果右边没有树,就停下来。
请注意,在选择一颗树后,你没有任何选择:你必须执行步骤 1,然后执行步骤 2,然后返回步骤 1,然后执行步骤 2,依此类推,直至停止。
你有两个篮子,每个篮子可以携带任何数量的水果,但你希望每个篮子只携带一种类型的水果。
用这个程序你能收集的水果总量是多少?
示例 1:
输入:[1,2,1]
输出:3
解释:我们可以收集 [1,2,1]。
示例 2:
输入:[0,1,2,2]
输出:3
解释:我们可以收集 [1,2,2].
如果我们从第一棵树开始,我们将只能收集到 [0, 1]。
示例 3:
输入:[1,2,3,2,2]
输出:4
解释:我们可以收集 [2,3,2,2].
如果我们从第一棵树开始,我们将只能收集到 [1, 2]。
示例 4:
输入:[3,3,3,1,2,1,1,2,3,3,4]
输出:5
解释:我们可以收集 [1,2,1,1,2].
如果我们从第一棵树或第八棵树开始,我们将只能收集到 4 个水果。
提示:
1 <= tree.length <= 40000
0 <= tree[i] < tree.length
思路:
顺序遍历或者倒序遍历都可以。以从后往前的倒序遍历为例,用fruit
数组表示两个水果种类代号,将tree[len(tree)-1]
加入到fruit
中,然后指针从最后一棵树开始,往前遍历寻找另一种不同水果。如果找不到,说明只有一种水果,直接返回len(tree)
。如果找到了,将第二种水果加入到fruit
中,用start
和stop
数组表示两个水果在区间的起始位置和结束位置,则每扫描一个区间,最大长度为max(stop)-min(start)
,继续扫描下个区间,这时要判断篮子里保存哪个水果,所以需要比较两个水果的起始位置,保留start
值较小的那种类型的水果,将另一种水果用当前指针新发现的水果替换,保留水果的stop
值还要用被替换水果的start
值更新,即stop[0] = min(stop[0], start[1] - 1)
。
时间复杂度
空间复杂度
代码:
倒序遍历
class Solution:
def totalFruit(self, tree):
"""
:type tree: List[int]
:rtype: int
"""
l_tree = len(tree)
if l_tree <= 2:
return l_tree
ans = 2
l = l_tree - 1
fruit = [tree[l], tree[l]]
start = [l, l]
stop = [l, l]
# find the other fruit
i = l
while i >= 0 and tree[i] == fruit[0]:
i -= 1
# only one kind of fruit
if i < 0:
return l_tree
else:
fruit[1] = tree[i]
start[0] = i + 1
start[1] = i
stop[1] = i
i -= 1
while i >= 0:
while i >= 0:
if tree[i] == fruit[0]:
start[0] = i
elif tree[i] == fruit[1]:
start[1] = i
else:
break
i -= 1
ans = max(ans, stop[0] - i)
if start[0] > start[1]:
fruit = fruit[::-1]
start = start[::-1]
stop = stop[::-1]
stop[0] = min(stop[0], start[1] - 1)
fruit[1] = tree[i]
start[1] = i
stop[1] = i
ans = max(ans, stop[0] - i)
return ans
顺序遍历
class Solution:
def totalFruit(self, tree):
"""
:type tree: List[int]
:rtype: int
"""
ans = 0
to_end = 1
start = 0
found = {tree[0]}
for i in range(1, len(tree)):
if tree[i] in found:
to_end += 1
elif len(found) < 2:
found.add(tree[i])
to_end += 1
else:
ans = max(to_end, ans)
to_end = i - start + 1
found = {tree[i], tree[i-1]}
# 这里更新两种水果的分界点
if tree[i] != tree[i-1]:
start = i
return max(to_end, ans)
907. 子数组的最小值之和
- 题目难度
Medium
给定一个整数数组 A
,找到 min(B)
的总和,其中 B
的范围为 A
的每个(连续)子数组。
由于答案可能很大,因此返回答案模 10^9 + 7。
示例:
输入:[3,1,2,4]
输出:17
解释:
子数组为 [3],[1],[2],[4],[3,1],[1,2],[2,4],[3,1,2],[1,2,4],[3,1,2,4]。
最小值为 3,1,2,4,1,1,2,1,1,1,和为 17。
提示:
1 <= A <= 30000
1 <= A[i] <= 30000
思路:
考虑从A
中的每个元素A[i]
,如果求出包含A[i]
并以A[i]
为最小元素的所有子数组个数n[i]
,则元素A[i]
对答案ans
的贡献为n[i]*A[i]
,那么我们可以先求包含A[i]
并以A[i]
为最小元素的最长子数组,如果A[i]
左边第一个小于A[i]
的元素为A[left]
,A[i]
右边第一个小于A[i]
的元素为A[right]
,则包含A[i]
并以A[i]
为最小元素的最长子数组为A[left+1:right]
,满足以A[i]
为最小元素的所有子数组个数n[i] = (i-left)*(right-i)
。我们用left[i]
表示A[i]
左边第一个小于A[i]
元素的位置,用right[i]
表示A[i]
右边第一个小于A[i]
元素的位置,left
数组初始值为-1
,right
数组初始值为len(A)
,求解left
和right
可以用单调栈来实现,可以两遍遍历,也可以一遍遍历,更优化的写法还可以一边遍历一边求解ans
。
时间复杂度
空间复杂度
代码:
class Solution:
def sumSubarrayMins(self, A):
"""
:type A: List[int]
:rtype: int
"""
len_A = len(A)
if len_A == 0:
return 0
if len_A == 1:
return A[0]
ans = 0
left = [0] * len_A
right = [0] * len_A
stack = []
for i in range(len_A):
while stack and A[stack[-1]] > A[i]:
stack.pop()
if not stack:
left[i] = -1
else:
left[i] = stack[-1]
stack.append(i)
stack = []
for i in range(len_A - 1, -1, -1):
while stack and A[stack[-1]] >= A[i]:
stack.pop()
if not stack:
right[i] = len_A
else:
right[i] = stack[-1]
stack.append(i)
for i in range(len_A):
ans += (i - left[i]) * (right[i] - i) * A[i]
ans %= 1000000007
return ans
一遍遍历
class Solution:
def sumSubarrayMins(self, A):
"""
:type A: List[int]
:rtype: int
"""
ans = 0
A = [float('-inf')] + A + [float('-inf')]
stack = []
for i, a in enumerate(A):
while stack and A[stack[-1]] > a:
cur = stack.pop()
ans += A[cur] * (i-cur) * (cur-stack[-1])
stack.append(i)
return ans % (10**9 + 7)
906. 超级回文数
- 题目难度
Hard
如果一个正整数自身是回文数,而且它也是一个回文数的平方,那么我们称这个数为超级回文数。
现在,给定两个正整数 L
和 R
(以字符串形式表示),返回包含在范围 [L, R]
中的超级回文数的数目。
示例:
输入:L = "4", R = "1000"
输出:4
解释:
4,9,121,以及 484 是超级回文数。
注意 676 不是一个超级回文数: 26 * 26 = 676,但是 26 不是回文数。
提示:
1 <= len(L) <= 18
1 <= len(R) <= 18
-
L
和R
是表示[1, 10^18)
范围的整数的字符串。 int(L) <= int(R)
思路:
从1产生回文数,把产生的回文数平方,判断平方后是不是回文数并在[L, R]
内。
由于超级回文数的个数十分有限,所以也可以打表解决。
时间复杂度
空间复杂度
代码:
class Solution:
def superpalindromesInRange(self, L, R):
"""
:type L: str
:type R: str
:rtype: int
"""
def is_circle(num):
s = str(num)
return s == s[::-1]
def create_circle(num):
s = str(num)
first = int(s + s[::-1])
second = int(s[:-1] + s[::-1])
return first, second
l = int(math.sqrt(int(L)))
r = int(math.sqrt(int(R))) + 1
# print(l, r)
ans = 0
for num in range(1, 100000):
# print(num)
big, small = create_circle(num)
# print(big, small)
if l <= small < r:
if is_circle(small * small):
ans += 1
if l <= big < r:
if is_circle(big * big):
ans += 1
if small > r:
break
return ans
打表
class Solution:
DATA2 = [1,
4,
9,
121,
484,
10201,
12321,
14641,
40804,
44944,
1002001,
1234321,
4008004,
100020001,
102030201,
104060401,
121242121,
123454321,
125686521,
400080004,
404090404,
10000200001,
10221412201,
12102420121,
12345654321,
40000800004,
1000002000001,
1002003002001,
1004006004001,
1020304030201,
1022325232201,
1024348434201,
1210024200121,
1212225222121,
1214428244121,
1232346432321,
1234567654321,
4000008000004,
4004009004004,
100000020000001,
100220141022001,
102012040210201,
102234363432201,
121000242000121,
121242363242121,
123212464212321,
123456787654321,
400000080000004,
10000000200000001,
10002000300020001,
10004000600040001,
10020210401202001,
10022212521222001,
10024214841242001,
10201020402010201,
10203040504030201,
10205060806050201,
10221432623412201,
10223454745432201,
12100002420000121,
12102202520220121,
12104402820440121,
12122232623222121,
12124434743442121,
12321024642012321,
12323244744232321,
12343456865434321,
12345678987654321,
40000000800000004,
40004000900040004,
1000000002000000001,
1000220014100220001,
1002003004003002001,
1002223236323222001,
1020100204020010201,
1020322416142230201,
1022123226223212201,
1022345658565432201,
1210000024200000121,
1210242036302420121,
1212203226223022121,
1212445458545442121,
1232100246420012321,
1232344458544432321,
1234323468643234321]
def superpalindromesInRange(self, L, R):
"""
:type L: str
:type R: str
:rtype: int
"""
start = int(L)
end = int(R)
index = 0
for i in self.DATA2:
if end>=i>=start:
index+=1
return index
网友评论