378. 有序矩阵中第K小的元素
给定一个 n x n 矩阵,其中每行和每列元素均按升序排序,找到矩阵中第k小的元素。
请注意,它是排序后的第k小元素,而不是第k个元素。
示例:
matrix = [
[ 1, 5, 9],
[10, 11, 13],
[12, 13, 15]
],
k = 8,
返回 13。
说明:
你可以假设 k 的值永远是有效的, 1 ≤ k ≤ n2 。
class Solution:
def kthSmallest(self, matrix: List[List[int]], k: int) -> int:
list_matrix = []
for i in range(len(matrix)):
list_matrix += matrix[i]
heapq.heapify(list_matrix)
return [heapq.heappop(list_matrix) for _ in range(k)][-1]
剑指 Offer 48. 最长不含重复字符的子字符串
请从字符串中找出一个最长的不包含重复字符的子字符串,计算该最长子字符串的长度。
示例 1:
输入: “abcabcbb”
输出: 3
解释: 因为无重复字符的最长子串是 “abc”,所以其长度为 3。
示例 2:
输入: “bbbbb”
输出: 1
解释: 因为无重复字符的最长子串是 “b”,所以其长度为 1。
示例 3:
输入: “pwwkew”
输出: 3
解释: 因为无重复字符的最长子串是 “wke”,所以其长度为 3。
请注意,你的答案必须是 子串 的长度,“pwke” 是一个子序列,不是子串。
提示:
s.length <= 40000
def longest_sub_str_1(s):
if not s or len(s) == 0:
return 0
d = {}
p1,p2 = -1,0
max_len = 0
while p1 < len(s) and p2 < len(s):
if s[p2] in d:
p1 = max(p1, d[s[p2]])
d[s[p2]] = p2
max_len = max(p2 - p1, max_len)
p2 += 1
return max_len
#coding:utf-8
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param s string字符串
# @return int整型
#
class Solution:
def lengthOfLongestSubstring(self , s ):
# write code here
dic = {} # 存储当前字符上次出现的idx
max_n, last_max = 0, 0
for j in range(len(s)):
i = dic.get(s[j], -1) # 上次该字符出现的位置
if j - i > last_max: # 如果出现 dvdf 这种f第一次出现的情况,需要判断一下是否是大于前一个最长串
last_max += 1
else:
last_max = j - i
max_n = max(max_n, last_max)
dic[s[j]] = j
return max_n
670. 最大交换
一、题目
给定一个非负整数,你 至多 可以交换一次数字中的任意两位。返回你能得到的最大值。
二、示例
2.1> 示例 1 :
【输入】 2736
【输出】 7236
【解释】 交换数字2和数字7。
2.2> 示例 2 :
【输入】 9973
【输出】 9973
【解释】 不需要交换。
def maximum_swap(num):
num_list = list(str(num))
sorted_num_list = sorted(num_list, reverse=True)
lc, hc = None, None
for i in range(len(num_list)):
if num_list[i] != sorted_num_list[i]:
lc = num_list[i]
hc = sorted_num_list[i]
num_list[i] = hc
break
if lc is not None:
for i in range(len(num_list) - 1, -1, -1):
if num_list[i] == hc:
num_list[i] = lc
break
return int(''.join(num_list))
622. 设计循环队列
设计你的循环队列实现。 循环队列是一种线性数据结构,其操作表现基于 FIFO(先进先出)原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。
循环队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里,一旦一个队列满了,我们就不能插入下一个元素,即使在队列前面仍有空间。但是使用循环队列,我们能使用这些空间去存储新的值。
你的实现应该支持如下操作:
MyCircularQueue(k): 构造器,设置队列长度为 k 。
Front: 从队首获取元素。如果队列为空,返回 -1 。
Rear: 获取队尾元素。如果队列为空,返回 -1 。
enQueue(value): 向循环队列插入一个元素。如果成功插入则返回真。
deQueue(): 从循环队列中删除一个元素。如果成功删除则返回真。
isEmpty(): 检查循环队列是否为空。
isFull(): 检查循环队列是否已满。
示例:
MyCircularQueue circularQueue = new MycircularQueue(3); // 设置长度为3
circularQueue.enQueue(1); // 返回true
circularQueue.enQueue(2); // 返回true
circularQueue.enQueue(3); // 返回true
circularQueue.enQueue(4); // 返回false,队列已满
circularQueue.Rear(); // 返回3
circularQueue.isFull(); // 返回true
circularQueue.deQueue(); // 返回true
circularQueue.enQueue(4); // 返回true
circularQueue.Rear(); // 返回4
思路:
双指针法,start指向目前队列的头,end指向目前队列的尾,两者初始值都为-1,
插入元素时,如果是第一个元素,那么start end 都变成 0
如果不是第一个元素,队尾延长,end + 1,注意是循环的队列所以需要%最大长度
如果队列已经满了,就返回False
删除元素时,如果是最后一个元素,那么start end 都变成-1
如果不是最后一个元素,队头出队,start + 1, 同样注意循环
如果队列是空的,就返回Flase
返回队头,如果有队头,直接输出start指向的元素;否则按题目要求输出-1
返回队尾,如果有队尾,直接输出end指向的元素;否则按题目要求输出-1
检查是否Full,如果end的下一位是start,就代表已经full
检查是否Empty,如果start 和end 都是-1,就代表已经empty
class MyCircularQueue(object):
def __init__(self, k):
"""
Initialize your data structure here. Set the size of the queue to be k.
:type k: int
"""
self.queue = [""] * k
self.max_length = k
self.start = -1
self.end = -1
def enQueue(self, value):
"""
Insert an element into the circular queue. Return true if the operation is successful.
:type value: int
:rtype: bool
"""
if not self.isFull():
if self.start == -1:
self.start = 0
self.end = (self.end + 1) % self.max_length
self.queue[self.end] = value
return True
else:
return False
def deQueue(self):
"""
Delete an element from the circular queue. Return true if the operation is successful.
:rtype: bool
"""
if not self.isEmpty():
if self.start == self.end: # the last element
self.start, self.end = -1, -1
# self.end = -1
else:
self.start = (self.start + 1) % self.max_length
return True
else:
return False
def Front(self):
"""
Get the front item from the queue.
:rtype: int
"""
return -1 if self.isEmpty() else self.queue[self.start]
def Rear(self):
"""
Get the last item from the queue.
:rtype: int
"""
return -1 if self.isEmpty() else self.queue[self.end]
def isEmpty(self):
"""
Checks whether the circular queue is empty or not.
:rtype: bool
"""
return self.start == -1 and self.end == -1
def isFull(self):
"""
Checks whether the circular queue is full or not.
:rtype: bool
"""
return (self.end + 1) % self.max_length == self.start
# Your MyCircularQueue object will be instantiated and called as such:
# obj = MyCircularQueue(k)
# param_1 = obj.enQueue(value)
# param_2 = obj.deQueue()
# param_3 = obj.Front()
# param_4 = obj.Rear()
# param_5 = obj.isEmpty()
# param_6 = obj.isFull()
426. 将二叉搜索树转化为排序的双向链表
将一个二叉搜索树就地转化为一个已排序的双向循环链表。可以将左右孩子指针作为双向循环链表的前驱和后继指针。
为了让您更好地理解问题,以下面的二叉搜索树为例:
我们希望将这个二叉搜索树转化为双向循环链表。链表中的每个节点都有一个前驱和后继指针。对于双向循环链表,第一个节点的前驱是最后一个节点,最后一个节点的后继是第一个节点。
下图展示了上面的二叉搜索树转化成的链表。“head” 表示指向链表中有最小元素的节点。
写法一:用栈(非递归)
"""
# Definition for a Node.
class Node:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
"""
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
if not root:return
# 当一个中间节点
head = Node(-1, None, None)
# 记录为先前节点,找到下一个节点才能串起来
prev = head
# 中序遍历的非递归
stack = []
p = root
while p or stack:
while p:
stack.append(p)
p = p.left
p = stack.pop()
# 改变左右方向
prev.right = p
p.left = prev
# 改变先前节点
prev = p
p = p.right
# 将head 删掉
head.right.left = prev
prev.right = head.right
return head.right
写法二:递归
"""
# Definition for a Node.
class Node:
def __init__(self, val, left=None, right=None):
self.val = val
self.left = left
self.right = right
"""
class Solution:
def treeToDoublyList(self, root: 'Node') -> 'Node':
if not root:return
# 当一个中间节点
head = Node(-1, None, None)
# 记录为先前节点,找到下一个节点才能串起来
prev = head
# 中序遍历的递归
def inorder(root):
nonlocal prev
if not root:
return
inorder(root.left)
prev.right = root
root.left = prev
prev = prev.right
inorder(root.right)
inorder(root)
# 将head 删掉
head.right.left = prev
prev.right = head.right
return head.right
154. 寻找旋转排序数组中的最小值 II
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,4,4,5,6,7] 在变化后可能得到:
若旋转 4 次,则可以得到 [4,5,6,7,0,1,4]
若旋转 7 次,则可以得到 [0,1,4,4,5,6,7]
注意,数组 [a[0], a[1], a[2], …, a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], …, a[n-2]] 。
给你一个可能存在 重复 元素值的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。
示例 1:
输入:nums = [1,3,5]
输出:1
1
2
示例 2:
输入:nums = [2,2,2,0,1]
输出:0
1
2
提示:
n == nums.length
1 <= n <= 5000
-5000 <= nums[i] <= 5000
nums 原来是一个升序排序的数组,并进行了 1 至 n 次旋转
class Solution:
def findMin(self, nums: List[int]) -> int:
i = 0
while i < len(nums) - 1:
if nums[i] > nums[i+1]:
return nums[i+1]
i += 1
return nums[0]
260. 只出现一次的数字 III
题目描述
给定一个整数数组 nums,其中恰好有两个元素只出现一次,其余所有元素均出现两次。找出只出现一次的那两个元素。
示例:
输入: [1,2,1,3,2,5]
输出: [3,5]
注意:
结果输出的顺序并不重要,对于上面的例子, [5, 3] 也是正确答案。
你的算法应该具有线性时间复杂度。你能否仅使用常数空间复杂度来实现?
from collections import Counter
class Solution:
def singleNumber(self, nums: int) -> List[int]:
hashmap = Counter(nums)
return [x for x in hashmap if hashmap[x] == 1]