这是悦乐书的第254次更新,第267篇原创

01 看题和准备

今天介绍的是LeetCode算法题中Easy级别的第121题(顺位题号是532)。给定一个整数数组和一个整数k,您需要找到数组中唯一的k-diff对的数量。 这里k-diff对被定义为整数对(i,j),其中i和j都是数组中的数字,它们的绝对差是k。例如:

输入:[3,1,4,1,5],k = 2

输出:2

说明:数组中有两个2-diff对,(1,3)和(3,5)。虽然我们在输入中有两个1,但我们应该只返回唯一对的数量。

输入:[1,2,3,4,5],k = 1

输出:4

说明:数组中有四个1-diff对,(1,2),(2,3),(3,4)和(4,5)。

输入:[1,3,1,5,4],k = 0

输出:1

说明:数组中有一个0-diff对,(1,1)。

注意:

  • 对(i,j)和(j,i)计为同一对。

  • 数组的长度不会超过10,000。

  • 给定输入中的所有整数都属于以下范围:[-1e7, 1e7]。

本次解题使用的开发工具是eclipse,jdk使用的版本是1.8,环境是win7 64位系统,使用Java语言编写和测试。

02 第一种解法

暴力解法。先排序,然后使用两层循环,计算不同元素的绝对值,如果等于k,次数就加1。在外面第一层循环那里,如果前后元素相同,就跳过当前循环,进行下一次循环。在内层循环那里同样做了类似的判断,排除重复计算。

此解法的时间复杂度是O(n^2),空间复杂度是O(1)。

public int findPairs(int[] nums, int k) {
if (nums == null || nums.length == 0 || k < 0) {
return 0;
}
Arrays.sort(nums);
int count = 0;
for (int i=0; i<nums.length; i++) {
int n = nums[i];
if (i >= 1 && nums[i-1] == nums[i]) {
continue;
}
for (int j=i+1; j<nums.length; j++) {
if (j >= i+2 && nums[j-1] == nums[j]) {
continue;
}
if (Math.abs(n - nums[j]) == k) {
count++;
}
}
}
return count;
}

03 第二种解法

第一种解法时间复杂度太高了,得降低点。第一种解法,我们是做减法,求绝对值,来判断是否等于k,我们也可以做加法,拿当前元素加上k,然后看新元素是否存在于数组中。同时还要考虑重复的计算数据,因此参与计算的元素是唯一的,对此我们可以使用HashMap,已元素值作为key,该元素值出现次数为value。遍历key,如果key加上k后的值存在于map中,次数加1,另外如果k为0的时候,只需要判断每个key所对应的value是否大于等于2即可。

此解法的时间复杂度是O(n),最坏情况也可能是O(n^2),空间复杂度是O(n)。

public int findPairs2(int[] nums, int k) {
if (nums == null || nums.length == 0 || k < 0) {
return 0;
}
Map<Integer,Integer> map = new HashMap<Integer,Integer>();
for (int n : nums) {
map.put(n, map.getOrDefault(n, 0)+1);
}
int count = 0;
if (k == 0) {
for (Integer key: map.keySet()) {
if (map.get(key) >= 2) {
count++;
}
}
} else {
for (Integer key: map.keySet()) {
if (map.containsKey(key+k)) {
count++;
}
}
}
return count;
}

04 第三种解法

对于第二种解法,还可以将判断放在循环体里面。

public int findPairs3(int[] nums, int k) {
if (nums == null || nums.length == 0 || k < 0) {
return 0;
}
Map<Integer,Integer> map = new HashMap<Integer,Integer>();
for (int n : nums) {
map.put(n, map.getOrDefault(n, 0)+1);
}
int count = 0;
for (Map.Entry<Integer, Integer> entry : map.entrySet()) {
if (k == 0) {
if (entry.getValue() >= 2) {
count++;
}
} else {
if (map.containsKey(entry.getKey()+k)) {
count++;
}
}
}
return count;
}

05 第四种解法

使用HashSet。使用两个HashSet,同样分为两种情况:k等于0和K不等于0。

如果k等于0时,对数组进行遍历,如果当前元素不存在于set1中,就添加进set1,如果存在set1中,就去判断是否存在于set2中,如果不存在,次数就加1,并将元素添加进set2中。

如果k不等于0,遍历数组,将当前元素添加进set1,将当前元素加上k后再添加进set2,然后使用retainAll方法,将set1中不包含set2元素的元素剔除掉(也就是两set的交集),最后count等于set1中元素的个数。

public int findPairs4(int[] nums, int k) {
if (nums == null || nums.length == 0 || k < 0) {
return 0;
}
Set<Integer> set1 = new HashSet<Integer>();
Set<Integer> set2 = new HashSet<Integer>();
int count = 0;
if (k == 0) {
for (int n : nums) {
if (!set1.contains(n)) {
set1.add(n);
} else {
if (!set2.contains(n)){
count++;
}
set2.add(n);
}
}
} else {
for (int n : nums) {
set1.add(n);
set2.add(n + k);
}
set1.retainAll(set2);
count = set1.size();
}
return count;
}

06 第五种解法

使用双指针。还是先将数据排序,定义左右两个指针,分别从0开始,如果左右指针相等,说明是循环的第一次或者重复了,就需要将右指针往后移动一位。如果左指针所指向元素加上k后等于右指针的元素,那么次数加1,接着要判断,如果右指针所指向位置后面的元素和当前元素相等,那么右指针继续往后移动。如果左指针所指向元素加上k后小于右指针的元素,说明左边的元素小了,左指针向前移动。如果左指针所指向元素加上k后大于右指针的元素,说明右边的元素小了,右指针向前移动。

此解法的时间复杂度是O(n log(n)),空间复杂度是O(1)。

public int findPairs5(int[] nums, int k) {
if (nums == null || nums.length == 0 || k < 0) {
return 0;
}
Arrays.sort(nums);
int count = 0;
int start = 0, end = 0;
while (end < nums.length) {
if (start == end) {
end++;
} else if (nums[start] + k == nums[end]) {
count++;
while (end + 1 < nums.length && nums[end] == nums[end + 1]) {
end++;
}
end++;
} else if (nums[start] + k < nums[end]) {
start++;
} else if (nums[start] + k > nums[end]) {
end++;
}
}
return count;
}

07 小结

此题的测试用例中,k出现了负值,所以在特殊情况判断中,还需要判断k小于0,这也是本题不严谨的一个地方。

算法专题目前已日更超过三个月,算法题文章121+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。

以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!

LeetCode算法题-K-diff Pairs in an Array(Java实现)的更多相关文章

  1. LeetCode算法题-Intersection of Two Arrays II(Java实现)

    这是悦乐书的第208次更新,第220篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第76题(顺位题号是350).给定两个数组,编写一个函数来计算它们的交集.例如: 输入: ...

  2. LeetCode算法题-Intersection of Two Linked Lists(Java实现)

    这是悦乐书的第178次更新,第180篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第37题(顺位题号是160).编写程序以找到两个单链表交叉的节点.例如: 以下两个链表: ...

  3. LeetCode算法题-Minimum Distance Between BST Nodes(Java实现-四种解法)

    这是悦乐书的第314次更新,第335篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第183题(顺位题号是783).给定具有根节点值的二叉搜索树(BST),返回树中任何两个 ...

  4. LeetCode算法题-Binary Number with Alternating Bits(Java实现)

    这是悦乐书的第292次更新,第310篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第160题(顺位题号是693).给定正整数,检查它是否具有交替位:即它的二进制数的任意两 ...

  5. LeetCode算法题-Trim a Binary Search Tree(Java实现)

    这是悦乐书的第284次更新,第301篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第152题(顺位题号是669).给定二叉搜索树以及L和R的最低和最高边界,修剪树以使其所 ...

  6. LeetCode算法题-Maximum Product of Three Numbers(Java实现)

    这是悦乐书的第275次更新,第291篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第143题(顺位题号是628).给定一个整数数组,从其中找出三个数,使得乘积最大.例如: ...

  7. LeetCode算法题-Construct String from Binary Tree(Java实现)

    这是悦乐书的第273次更新,第288篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第141题(顺位题号是606).构造一个字符串,该字符串由二叉树中的括号和整数组成,并具 ...

  8. LeetCode算法题-Maximum Depth of N-ary Tree(Java实现)

    这是悦乐书的第261次更新,第274篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第128题(顺位题号是559).给定n-ary树,找到它的最大深度.最大深度是从根节点到 ...

  9. LeetCode算法题-Convert BST to Greater Tree(Java实现)

    这是悦乐书的第255次更新,第268篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第122题(顺位题号是538).给定二进制搜索树(BST),将其转换为更大树,使原始BS ...

  10. LeetCode算法题-Minimum Absolute Difference in BST(Java实现)

    这是悦乐书的第253次更新,第266篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第120题(顺位题号是530).给定具有非负值的二叉搜索树,找到任意两个节点的值之间的最 ...

随机推荐

  1. NDK开发入门终极教程

    0 前言 同NDK技术的渊源始于3年前,使用so文件的时候了解到NDK技术,并且C语言一直是强项,就鼓捣起NDK开发.在AndroidStduio还没推广的年代,基于eclipse搭建NDK开发环境需 ...

  2. Java如何在运行时识别类型信息?

    在日常的学习工作当中,有一些知识是我们在读书的时候就能够习得:但有一些知识不是的,需要在实践的时候才能得到真知——这或许就是王阳明提倡的“知行合一”. 在Java中,并不是所有的类型信息都能在编译阶段 ...

  3. Windows提权与开启远程连接

    1.提权: 建立普通用户:net user 帐户 密码 /add 提权成管理员:net localgroup administrators 帐户 /add 更改用户密码:net user 帐户 密码 ...

  4. 在.NET中使用Redis

    dll文件 namespace RedisDemo { public partial class RedisPage : System.Web.UI.Page { protected void Pag ...

  5. Qt之自定义托盘(二)

    上一篇文章讲述了自定义Qt托盘,不过不是使用QSystemTrayIcon这个类,而是我们自己完全自定义的一个类,我们只需要处理这个类的鼠标hover.鼠标左键点击.鼠标右键点击和鼠标左键双击,就可以 ...

  6. JAVA实现接口监控报警系统

    公司一内部系统需要添加一个接口和定时任务监控机制,针对了系统出现的定时任务没有执行,定时任务执行异常出错,对外传送的数据接口异常出错,对内的系统数据互传异常出错等问题进行设计,目的是为了能够让用户没发 ...

  7. UPC:ABS

    问题 G: ABS 时间限制: 1 Sec  内存限制: 128 MB提交: 537  解决: 186[提交] [状态] [讨论版] [命题人:admin] 题目描述 We have a deck c ...

  8. 【ASP.NET Core快速入门】(十五)MVC开发:ReturnUrl实现、Model后端验证 、Model前端验证

    ReturnUrl实现 我们要实现returnUrl,我们需要在注册(Register)方法中接收传进的returnUrl并给它默认值null,然后将它保存在ViewData里面 然后我们定义一个内部 ...

  9. Java开发知识之Java中的Map结构

    Java开发知识之Java中的Map结构 一丶Map接口 Map没有实现Collection接口,提供的是Key 到Value的映射. Map中.不能包含相同的Key,每个Key只能映射一个Value ...

  10. linux 制作不用密碼可立即登入的 ssh 用戶

    机器环境: 192.167.33.48 clent 用户:server 192.167.33.47 server 用户:server 1.客户端 生成密钥 ssh-keygen 2. 查看密钥文件权限 ...