题目链接:https://leetcode-cn.com/problems/contains-duplicate-iii/

题目描述:

给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 k。

示例:

示例 1:

输入: nums = [1,2,3,1], k = 3, t = 0
输出: true

示例 2:

输入: nums = [1,0,1,1], k = 1, t = 2
输出: true

示例 3:

输入: nums = [1,5,9,1,5,9], k = 2, t = 3
输出: false

思路:

这道题应该是 Hard 难度的(看通过率就知道了)

简单想法:维护一个长度为 k+1连续队列, 在这队列里一定任何两个数索引号相差 不会超过k,当队列存在两个数相差为t,那么返回为 true

简单想法代码如下,这个一定要理解,后面只是换了数据结构!

class Solution:
def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:
from collections import deque
import bisect
n = len(nums)
if n <= 1: return False
m = min(n, k + 1)
# 维护一个长度为 k + 1 队列
queue = sorted(nums[:m])
# 要删除数
to_del = deque()
to_del.extendleft(nums[:m])
# 先判断首先 k + 1 队列是否存在满足条件的
for i in range(1, m):
if queue[i] - queue[i - 1] <= t:
return True
for i in range(m, n):
# 移动队列
queue.remove(to_del.pop())
# 二分插入
loc = bisect.bisect_left(queue, nums[i])
queue.insert(loc, nums[i])
# 判断它在队列中左右两边数是否小于等于t
if (loc - 1 >= 0 and nums[i] - queue[loc - 1] <= t) or \
(loc + 1 <= k and queue[loc + 1] - nums[i] <= t):
return True
to_del.appendleft(nums[i])
return False

上面的代码也能过,但是极慢,为什么?

原因就是数组插入删除的时间复杂度为 \(O(n)\),有没有一种数据结构又能排好序,然而删除添加的时间复杂度有很少呢?\(log(n)\)

当然有了,那就是二叉排序树(BST)Python没有自带的库, Java里有 TreeSet

但是可以自己实现,网上找到的代码,大家感兴趣研究一下,(哭!不想看,后面还有一个桶排序要看一下啊!

from collections import deque

class BSTNode:

    def __init__(self, dlnode):
self.ptr = dlnode
self.l = None
self.r = None class BST: def __init__(self, head):
self.root = BSTNode(head) def insert(self, dlnode): def insertHelper(root, dlnode, min_, max_):
if dlnode.v <= root.ptr.v:
if not root.l:
root.l = BSTNode(dlnode)
if min_:
min_ = min_.ptr
return min_, root.ptr
return insertHelper(root.l, dlnode, min_, root)
else:
if not root.r:
root.r = BSTNode(dlnode)
if max_:
max_ = max_.ptr
return root.ptr, max_
return insertHelper(root.r, dlnode, root, max_) return insertHelper(self.root, dlnode, None, None) def delNode(self, node):
tmp, prev = self.root, None
while tmp and node != tmp.ptr:
prev = tmp
if node.v <= tmp.ptr.v:
tmp = tmp.l
else:
tmp = tmp.r if tmp == None:
return f'Something went wrong, Node {node} not found...'
else:
if tmp.l and tmp.r:
tmp2, prev2 = tmp.r, None
while tmp2.l:
prev2 = tmp2
tmp2 = tmp2.l if prev2:
prev2.l = tmp2.r if prev:
if prev.l == tmp:
prev.l = tmp2
elif prev.r == tmp:
prev.r = tmp2
else:
return 'Something went wrong.'
else:
self.root = tmp2 tmp2.l = tmp.l
if tmp2 != tmp.r:
tmp2.r = tmp.r
elif tmp.l:
if prev:
if prev.l == tmp:
prev.l = tmp.l
elif prev.r == tmp:
prev.r = tmp.l
else:
return 'Something went wrong.'
else:
self.root = tmp.l
elif tmp.r:
if prev:
if prev.l == tmp:
prev.l = tmp.r
elif prev.r == tmp:
prev.r = tmp.r
else:
return 'Something went wrong.'
else:
self.root = tmp.r
else:
if prev:
if prev.l == tmp:
prev.l = None
elif prev.r == tmp:
prev.r = None
else:
return 'Something went wrong.'
else:
self.root = tmp.r del tmp def popByorder(self):
def inorderPop(root):
nodes = [] if root.l:
nodes += inorderPop(root.l)
nodes += [root.ptr]
if root.r:
nodes += inorderPop(root.r) return nodes return inorderPop(self.root) def __str__(self):
def inorder(root):
s = '' if root.l:
s += inorder(root.l)
s += f' -> {root.ptr.v}'
if root.r:
s += inorder(root.r) return s return 'BST' + inorder(self.root) class DLNode: def __init__(self, v):
self.v = v
self.next = None
self.prev = None class DList: def __init__(self, v):
self.head = DLNode(v) if isinstance(v, int) else v
self.tail = self.head def append(self, node):
if self.head == self.tail:
self.head.next = node
self.tail.next = node
node.prev = self.tail
self.tail = node def insert(self, l, m, r):
if l and r:
l.next = m
m.next = r
r.prev = m
m.prev = l
elif l:
self.tail = m
l.next = m
m.prev = l
elif r:
self.head = m
m.next = r
r.prev = m def delHead(self):
tmp = self.head
self.head = self.head.next
self.head.prev = None
del tmp def delTail(self):
tmp = self.tail
self.tail = self.tail.prev
self.tail.next = None
del tmp def delNode(self, d):
if d == self.head:
self.delHead()
elif d == self.tail:
self.delTail()
else:
d.prev.next = d.next
d.next.prev = d.prev
del d def __str__(self):
s = f'{self.head.v}'
tmp = self.head.next
while tmp:
s += f' -> {tmp.v}'
tmp = tmp.next
return s class Solution:
def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:
if not nums or k == 0:
return False n = len(nums)
m = DLNode(nums[0])
bst = BST(m)
toDel = deque([m])
for x in nums[1:k + 1]:
m = DLNode(x)
_, _ = bst.insert(m)
toDel.append(m) for i, m in enumerate(bst.popByorder()):
if i == 0:
dl = DList(m)
else:
dl.append(m) i, j = dl.head, dl.head.next
while j:
if j.v - i.v <= t:
return True
i = i.next
j = j.next if k < n:
for x in nums[k + 1:]:
d = toDel.popleft()
bst.delNode(d)
m = DLNode(x)
l, r = bst.insert(m)
if (l and m.v - l.v <= t) or (r and r.v - m.v <= t):
return True
toDel.append(m)
return False

是的,还有一种思路,桶排序[1]

大家自行用例子模拟,感觉一下!

时间复杂度:\(O(n)\)

class Solution:
def containsNearbyAlmostDuplicate(self, nums: List[int], k: int, t: int) -> bool:
from collections import OrderedDict
n = len(nums)
if n <= 1 or k < 1 or t < 0: return False
queue = OrderedDict()
for n in nums:
key = n if not t else n // t
for m in [queue.get(key-1), queue.get(key), queue.get(key+1)]:
if m is not None and abs(n - m) <= t:
return True
if len(queue) == k:
queue.popitem(False)
queue[key] = n
return False

  1. https://leetcode.com/problems/contains-duplicate-iii/discuss/61756/Python-OrderedDict ↩︎

[LeetCode]220. 存在重复元素 III的更多相关文章

  1. Java实现 LeetCode 220 存在重复元素 III(三)

    220. 存在重复元素 III 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最 ...

  2. Leetcode 220.存在重复元素III

    存在重复元素III 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ. ...

  3. 220. 存在重复元素 III

    题目: 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ. 示例 1: ...

  4. 【每日算法】存在重复元素 III

    题目描述 这是 LeetCode 上的 220. 存在重复元素 III, 难度为 [中等] 给你一个整数数组 nums 和两个整数 k 和 t .请你判断是否存在 两个不同下标 i 和 j,使得 ab ...

  5. LeetCode:存在重复元素【217】

    LeetCode:存在重复元素[217] 题目描述 给定一个整数数组,判断是否存在重复元素. 如果任何值在数组中出现至少两次,函数返回 true.如果数组中每个元素都不相同,则返回 false. 示例 ...

  6. leetcode——217. 存在重复元素

    leetcode--217. 存在重复元素 题目描述:给定一个整数数组,判断是否存在重复元素. 如果存在一值在数组中出现至少两次,函数返回 true .如果数组中每个元素都不相同,则返回 false ...

  7. [LeetCode] 220. Contains Duplicate III 包含重复元素 III

    Given an array of integers, find out whether there are two distinct indices i and j in the array suc ...

  8. [LeetCode]-217.存在重复元素-简单

    217. 存在重复元素 给定一个整数数组,判断是否存在重复元素. 如果存在一值在数组中出现至少两次,函数返回 true .如果数组中每个元素都不相同,则返回 false . 示例 1: 输入: [1, ...

  9. Leetcode 217.存在重复元素 By Python

    给定一个整数数组,判断是否存在重复元素. 如果任何值在数组中出现至少两次,函数返回 true.如果数组中每个元素都不相同,则返回 false. 示例 1: 输入: [1,2,3,1] 输出: true ...

随机推荐

  1. 51 nod 1127最短的包含字符串(尺取法)

    1127 最短的包含字符串   收藏  关注 给出一个字符串,求该字符串的一个子串S,S包含A-Z中的全部字母,并且S是所有符合条件的子串中最短的,输出S的长度.如果给出的字符串中并不包括A-Z中的全 ...

  2. 「SDOI2017」硬币游戏

    题目链接 问题分析 首先一个显然的做法就是建出AC自动机,然后高斯消元.但是这样的复杂度是\(O(n^3m^3)\)的. 我们发现其实只需要求AC自动机上\(n\)个状态的概率,而其余的概率是没有用的 ...

  3. [LOJ3106][TJOI2019]唱、跳、rap和篮球:DP+生成函数+NTT+容斥原理

    分析 令\(f(i)\)表示共\(i\)组同学讨论cxk的位置的方案数(不考虑其他位置上的人的爱好),这个数组可以很容易地通过依次考虑每个位置是否是四个人中最后一个人的位置来递推求解,时间复杂度\(O ...

  4. TreeMap元素必须实现Comparable接口

    纠正一下,TreeMap实现一定顺序是通过Comparable接口的,而他实现元素不重复也是完全通过compareTo,而不是hashCode和equals,因为debug不会走到hashCode和e ...

  5. extentsreport testng美化报告生成

    一:主要内容 优化testng测试报告,使用extentsreport 解决extentsreport打开后加载不出来样式的问题 二:报告效果 先上图,看下testng extentsreport报告 ...

  6. navicat常用快捷键与SQL基本使用

    一.Navicat常用快捷键 1,Ctrl+q就会弹出一个sql输入窗口 2,Ctrl+r就执行sql了 3,按f6会弹出一个命令窗口 4,Ctrl+/ 注释 5,Ctrl +Shift+/ 解除注释 ...

  7. IDEA全局配置

    进入全局设置界面: 取消每次启动IDEA就默认打开上一次最后关闭的项目 编译器代码字体设置: 控制台字体大小和颜色设置 同一个文件代码里面的各个不同方法之间显示分割线 代码自动提示不区分大小写 格式化 ...

  8. RedHat 5下安装gcc编译环境的具体步骤

    RedHat 5下安装gcc编译环境的具体步骤 在RHEL5系统中默认不安装linux系统中的开发编译环境(gcc),此软件包安装时依赖其他包较多 在以前使用RHEL4时可以通过如下命令安装: rpm ...

  9. Spring容器启动源码分析

    1. 前言 最近搭建的工程都是基于SpringBoot,简化配置的感觉真爽.但有个以前的项目还是用SpringMvc写的,看到满满的配置xml文件,却有一种想去深入了解的冲动.折腾了好几天,决心去写这 ...

  10. 在IOS系统中微信浏览器input输入框输入值无效

    [contenteditable="true"], input, textarea { -webkit-user-select: auto!important; -khtml-us ...