一、找出中枢整数
给你一个正整数 n ,找出满足下述条件的 中枢整数 x :
1和x之间的所有元素之和等于x和n之间所有元素之和。
返回中枢整数 **x 。如果不存在中枢整数,则返回 -1 。题目保证对于给定的输入,至多存在一个中枢整数。
示例 1:
输入: n = 8
输出: 6
解释: 6 是中枢整数,因为 1 + 2 + 3 + 4 + 5 + 6 = 6 + 7 + 8 = 21 。
示例 2:
输入: n = 1
输出: 1
解释: 1 是中枢整数,因为 1 = 1 。
示例 3:
输入: n = 4
输出: -1
解释: 可以证明不存在满足题目要求的整数。
提示:
1 <= n <= 1000
解析
因为n的范围不大,所以可以直接暴力计算,当然也可以用数学的方法,1到x的求和公式等于x到n的求和公式,得出来的结果是x等于根号下n*(n+1)/2,如果开根号之后是整数,就是结果,不是整数,就返回-1
代码
class Solution:
def pivotInteger(self, n: int) -> int:
if n == 1:
return 1
l = [i for i in range(1, n+1)]
for x in range(len(l)):
if sum(l[:x+1]) == sum(l[x:]):
return x+1
return -1
二、追加字符以获得子序列
给你两个仅由小写英文字母组成的字符串 s 和 t 。
现在需要通过向 s 末尾追加字符的方式使 t 变成 s 的一个 子序列 ,返回需要追加的最少字符数。
子序列是一个可以由其他字符串删除部分(或不删除)字符但不改变剩下字符顺序得到的字符串。
示例 1:
输入: s = "coaching", t = "coding"
输出: 4
解释: 向 s 末尾追加字符串 "ding" ,s = "coachingding" 。
现在,t 是 s ("coachingding") 的一个子序列。
可以证明向 s 末尾追加任何 3 个字符都无法使 t 成为 s 的一个子序列。
示例 2:
输入: s = "abcde", t = "a"
输出: 0
解释: t 已经是 s ("abcde") 的一个子序列。
示例 3:
输入: s = "z", t = "abcde"
输出: 5
解释: 向 s 末尾追加字符串 "abcde" ,s = "zabcde" 。
现在,t 是 s ("zabcde") 的一个子序列。
可以证明向 s 末尾追加任何 4 个字符都无法使 t 成为 s 的一个子序列。
提示:
1 <= s.length, t.length <= 10^5s和t仅由小写英文字母组成
解析
题目要求是在s的结尾追加字符,以使得t变成s的一个子序列。遍历t的每一个字符的时候,如果它在s当中出现,并且出现的位置大于上一个字符出现的位置即可,当发现t里的某一个字符没有在s里出现,那么从这个字符开始,后边的所有字符都需要被追加到s后面。
当然也可以反过来,在层遍历s,跟t的一个字符进行比较,当发现相等的时候,下一次比较的目标值就是t的下一个字符,直到s结束,t里还剩下多少个字符,就需要补充多少个
代码
class Solution:
def appendCharacters(self, s: str, t: str) -> int:
i = 0
length = len(t)
for c in s:
if i < length and c == t[i]:
i += 1
return length - i
三、从链表中移除节点
给你一个链表的头节点 head 。
对于列表中的每个节点 node ,如果其右侧存在一个具有 严格更大 值的节点,则移除 node 。
返回修改后链表的头节点 **head **。
示例 1:
输入: head = [5,2,13,3,8]
输出: [13,8]
解释: 需要移除的节点是 5 ,2 和 3 。
- 节点 13 在节点 5 右侧。
- 节点 13 在节点 2 右侧。
- 节点 8 在节点 3 右侧。
示例 2:
输入: head = [1,1,1,1]
输出: [1,1,1,1]
解释: 每个节点的值都是 1 ,所以没有需要移除的节点。
提示:
- 给定列表中的节点数目在范围
[1, 10^5]内 1 <= Node.val <= 10^5
解析
这题目本身没什么难度,就是找到一个严格降序的链表即可,注意,题目没有要求是在原链表上操作,因此可以简单的把各个节点的值取出来,放到一个数组里,在数组里进行个钟操作即可,复杂程度迅速降低。
代码
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def removeNodes(self, head: Optional[ListNode]) -> Optional[ListNode]:
vals = []
while head:
vals.append(head.val)
head = head.next
vals = vals[::-1]
m = 0
t = []
for v in vals:
if v >= m:
m = v
t.append(v)
t = t[::-1]
nodes = [ListNode(val=x) for x in t]
for i in range(1, len(nodes)):
nodes[i-1].next = nodes[i]
return nodes[0]
原地操作的版本
# Definition for singly-linked list.
# class ListNode:
# def __init__(self, val=0, next=None):
# self.val = val
# self.next = next
class Solution:
def reverseNodes(self, head: ListNode) -> ListNode:
if not head:
return None
if not head.next:
return head
head.hold = 1
headNode = self.reverseNodes(head.next)
headNode.hold = 1
head.next.next = head
head.next = None
head.hold = 1
return headNode
def reverseBackNodes(self, head: ListNode) -> ListNode:
if not head:
return None
if not head.next:
return head
headNode = self.reverseBackNodes(head.next)
head.next.next = head
head.next = None
return headNode
def printNode(self, head):
while head:
print("print", head.val, head.hold)
# if head.hold == 1:
# print(head.val)
head = head.next
def checkNode(self, head):
if not head:
return None
if head.hold:
return head
else:
return head.next
head.next = self.checkNode(head.next)
if head.next:
print("check", head.next.val, head.next.hold)
return head
def removeNodes(self, head: Optional[ListNode]) -> Optional[ListNode]:
reverseHead = self.reverseNodes(head)
# self.printNode(reverseHead)
current_max = 0
start = reverseHead
while start and start.val > 0:
if start.val >= current_max:
start.hold = 1
current_max = start.val
else:
start.hold = 0
# print(start.val, start.hold)
start = start.next
reverseBack = self.reverseBackNodes(reverseHead)
newHead = None
tmp = reverseBack
while tmp:
if tmp.hold == 1:
newHead = tmp
break
else:
tmp = tmp.next
print("从newHead开始: %s" % newHead.val)
stack = []
# stack.append(newHead)
tmp = newHead
while tmp:
if tmp.hold:
if not stack:
stack.append(tmp)
else:
stack[-1].next = tmp
stack.append(tmp)
tmp = tmp.next
return stack[0]
四、统计中位数为 K 的子数组
给你一个长度为 n 的数组 nums ,该数组由从 1 到 n 的 不同 整数组成。另给你一个正整数 k 。
统计并返回 num 中的 中位数 等于 k 的非空子数组的数目。
注意:
-
数组的中位数是按 递增 顺序排列后位于 中间 的那个元素,如果数组长度为偶数,则中位数是位于中间靠 左 的那个元素。
- 例如,
[2,3,1,4]的中位数是2,[8,4,3,5,1]的中位数是4。
- 例如,
-
子数组是数组中的一个连续部分。
示例 1:
输入: nums = [3,2,1,4,5], k = 4
输出: 3
解释: 中位数等于 4 的子数组有:[4]、[4,5] 和 [1,4,5] 。
示例 2:
输入: nums = [2,3,1], k = 3
输出: 1
解释: [3] 是唯一一个中位数等于 3 的子数组。
提示:
n == nums.length1 <= n <= 10^51 <= nums[i], k <= nnums中的整数互不相同
解析
这道题难度并不大,有一个细节需要注意,题目要找的是中位数,不是平均数,中位数是一定存在于这个子数组中的,而平均数不一定。在初看此题的时候,这里理解有误,比如1,2,4,5 的中位数应该是2,我给理解成了3,所以在算3,1,2,4,5且k为3的时候,总比答案多一个值。
当考虑到中位数必须存在于子数组之中的时候,题目就变得简单了。
先找到这个k的位置,如果要使得子数组的中位数是k,则整体上,比k大的个数要等于比k小的个数,或者比k大的个数减去比k小的个数,差值为1.
中位数只需要比较大小,不看具体值是多少。
代码
class Solution:
def countSubarrays(self, nums: List[int], k: int) -> int:
pos = nums.index(k)
cnt = defaultdict(int)
cnt[0] = 1 # i=pos 的时候 c 是 0,直接记到 cnt 中,这样下面不是大于就是小于
c = 0
for i in range(pos + 1, len(nums)):
c += 1 if nums[i] > k else -1
cnt[c] += 1
ans = cnt[0] + cnt[1] # i=pos 的时候 c 是 0,直接加到答案中,这样下面不是大于就是小于
c = 0
for i in range(pos - 1, -1, -1):
c += 1 if nums[i] < k else -1
ans += cnt[c] + cnt[c + 1]
return ans