哈希表与索引和统计
Posted Al_tair
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了哈希表与索引和统计相关的知识,希望对你有一定的参考价值。
哈希表与索引和统计
大家好呀,我是小笙!
哈希表与索引
1. 两数之和
给定一个整数数组
nums
和一个整数目标值target
,请你在该数组中找出 和为目标值target
的那 两个 整数,并返回它们的数组下标。你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。
你可以按任意顺序返回答案。
示例 1:
输入:nums = [2,7,11,15], target = 9 输出:[0,1] 解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。
示例 2:
输入:nums = [3,2,4], target = 6 输出:[1,2]
示例 3:
输入:nums = [3,3], target = 6 输出:[0,1]
提示:
2 <= nums.length <= 104
-109 <= nums[i] <= 109
-109 <= target <= 109
- 只会存在一个有效答案
**进阶:**你可以想出一个时间复杂度小于
O(n2)
的算法吗?
class Solution
public int[] twoSum(int[] nums, int target)
HashMap<Integer,Integer> find = new HashMap<>();
int n = nums.length;
for(int i=0;i<n;i++)
if(find.containsKey(target-nums[i]) && find.get(target-nums[i])!=i)
return new int[]i, find.get(target-nums[i]);
find.put(nums[i],i);
return new int[0];
167.两数之和 II - 输入有序数组
给定一个已按照 非递减顺序排列 的整数数组
numbers
,请你从数组中找出两个数满足相加之和等于目标数target
。函数应该以长度为
2
的整数数组的形式返回这两个数的下标值*。*numbers
的下标 从 1 开始计数 ,所以答案数组应当满足1 <= answer[0] < answer[1] <= numbers.length
。你可以假设每个输入 只对应唯一的答案 ,而且你 不可以 重复使用相同的元素。
示例 1:
输入:numbers = [2,7,11,15], target = 9 输出:[1,2] 解释:2 与 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2 。
示例 2:
输入:numbers = [2,3,4], target = 6 输出:[1,3]
示例 3:
输入:numbers = [-1,0], target = -1 输出:[1,2]
提示:
2 <= numbers.length <= 3 * 104
-1000 <= numbers[i] <= 1000
numbers
按 非递减顺序 排列-1000 <= target <= 1000
- 仅存在一个有效答案
class Solution
public int[] twoSum(int[] numbers, int target)
HashMap<Integer,Integer> find = new HashMap<>();
int n = numbers.length;
for(int i=0;i<n;i++)
if(find.containsKey(target-numbers[i]) && find.get(target-numbers[i]) != i)
if(i<find.get(target-numbers[i]))
return new int[]i+1,find.get(target-numbers[i])+1;
else
return new int[]find.get(target-numbers[i])+1,i+1;
find.put(numbers[i],i);
return new int[0];
599.两个列表的最小索引总和
假设Andy和Doris想在晚餐时选择一家餐厅,并且他们都有一个表示最喜爱餐厅的列表,每个餐厅的名字用字符串表示。
你需要帮助他们用最少的索引和找出他们共同喜爱的餐厅。 如果答案不止一个,则输出所有答案并且不考虑顺序。 你可以假设总是存在一个答案。
示例 1:
输入: ["Shogun", "Tapioca Express", "Burger King", "KFC"] ["Piatti", "The Grill at Torrey Pines", "Hungry Hunter Steakhouse", "Shogun"] 输出: ["Shogun"] 解释: 他们唯一共同喜爱的餐厅是“Shogun”。
示例 2:
输入: ["Shogun", "Tapioca Express", "Burger King", "KFC"] ["KFC", "Shogun", "Burger King"] 输出: ["Shogun"] 解释: 他们共同喜爱且具有最小索引和的餐厅是“Shogun”,它有最小的索引和1(0+1)。
提示:
- 两个列表的长度范围都在 [1, 1000]内。
- 两个列表中的字符串的长度将在[1,30]的范围内。
- 下标从0开始,到列表的长度减1。
- 两个列表都没有重复的元素。
class Solution
public String[] findRestaurant(String[] list1, String[] list2)
if(list1 == null || list2 == null) return null;
HashMap<String,Integer> map = new HashMap<>(); // list1数组值 and 该数组下标
ArrayList<String> value = new ArrayList<>(); // 输出的String数组值
int m = list1.length,n = list2.length,MIN = Integer.MAX_VALUE;
for(int i=0;i<m;i++)
map.put(list1[i],i);
for(int i=0;i<n;i++)
if(map.containsKey(list2[i]))
if((i+map.get(list2[i]))<MIN)
value.clear();
MIN = i+map.get(list2[i]);
value.add(list2[i]);
else if((i+map.get(list2[i]))==MIN)
value.add(list2[i]);
return value.toArray(new String[value.size()]);
// 执行用时:8 ms, 在所有 Java 提交中击败了82.29%的用户
// 内存消耗:39.1 MB, 在所有 Java 提交中击败了26.04%的用户
219.存在重复元素 II
给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。
示例 1:
输入: nums = [1,2,3,1], k = 3 输出: true
示例 2:
输入: nums = [1,0,1,1], k = 1 输出: true
示例 3:
输入: nums = [1,2,3,1,2,3], k = 2 输出: false
class Solution
public boolean containsNearbyDuplicate(int[] nums, int k)
HashMap<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++)
Integer index = map.get(nums[i]); // 精华Integer 默认赋值null 区别于 int没有默认
if (index == null)
map.put(nums[i], i);
else if (i - index <= k)
return true;
else
map.put(nums[i], i);
return false;
220.存在重复元素 III
给你一个整数数组
nums
和两个整数k
和t
。请你判断是否存在 两个不同下标i
和j
,使得abs(nums[i] - nums[j]) <= t
,同时又满足abs(i - j) <= k
。如果存在则返回
true
,不存在返回false
。示例 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
提示:
0 <= nums.length <= 2 * 104
-231 <= nums[i] <= 231 - 1
0 <= k <= 104
0 <= t <= 231 - 1
class Solution
public boolean containsNearbyAlmostDuplicate(int[] nums, int k, int t)
// 1. 使用有序集合来维护大小为k的滑动窗口
int n = nums.length;
TreeSet<Long> set = new TreeSet<Long>(); // long为了防止溢出
// 2. 处理逻辑:遍历每个元素,滑动窗口包含了nums[i]的前k个元素,检查是否落在了[nums[i] - t,nums[i] + t]的区间内
for (int i = 0; i < n; i++)
// 2.1 判断有序集合中是否存在符合条件的元素
Long ceiling = set.ceiling((long) nums[i] - (long) t); // ceiling():方法返回在这个集合中大于或者等于给定元素的最小元素,如果不存在这样的元素,返回null.
if (ceiling != null && ceiling <= (long) nums[i] + (long) t) // 存在这样一对元素就直接返回
return true;
// 2.2 不存在的话暂时添加到有序集合中
set.add((long) nums[i]);
// 2.3 维护大小为k的滑动窗口,删除超出范围的最早的元素
if (i >= k)
set.remove((long) nums[i - k]);
// 3. 都不满足返回false
return false;
哈希表与统计
594.最长和谐子序列
和谐数组是指一个数组里元素的最大值和最小值之间的差别 正好是
1
。现在,给你一个整数数组
nums
,请你在所有可能的子序列中找到最长的和谐子序列的长度。数组的子序列是一个由数组派生出来的序列,它可以通过删除一些元素或不删除元素、且不改变其余元素的顺序而得到。
示例 1:
输入:nums = [1,3,2,2,5,2,3,7] 输出:5 解释:最长的和谐子序列是 [3,2,2,2,3]
示例 2:
输入:nums = [1,2,3,4] 输出:2
示例 3:
输入:nums = [1,1,1,1] 输出:0
提示:
1 <= nums.length <= 2 * 104
-109 <= nums[i] <= 109
class Solution
public int findLHS(int[] nums)
int MAX = 0;
HashMap<Integer,Integer> map = new HashMap<>();
int n = nums.length;
for(int i = 0;i < n;i++)
if(map.containsKey(nums[i]))
map.replace(nums[i],map.get(nums[i]),map.get(nums[i])+1);
else
map.put(nums[i],1);
for(int num:map.keySet())
if(map.containsKey(num+1))
MAX = Math.max(MAX,map.get(num)+map.get(num+1));
return MAX;
350.两个数组的交集 II
给你两个整数数组
nums1
和nums2
,请你以数组形式返回两数组的交集。返回结果中每个元素出现的次数,应与元素在两个数组中都出现的次数一致(如果出现次数不一致,则考虑取较小值)。可以不考虑输出结果的顺序。示例 1:
输入:nums1 = [1,2,2,1], nums2 = [2,2] 输出:[2,2]
示例 2:
输入:nums1 = [4,9,5], nums2 = [9,4,9,8,4] 输出:[4,9]
提示:
1 <= nums1.length, nums2.length <= 1000
0 <= nums1[i], nums2[i] <= 1000
进阶:
- 如果给定的数组已经排好序呢?你将如何优化你的算法?
- 如果
nums1
的大小比nums2
小,哪种方法更优?- 如果
nums2
的元素存储在磁盘上,内存是有限的,并且你不能一次加载所有的元素到内存中,你该怎么办?
class Solution
public int[] intersect(int[] nums1, int[] nums2)
int m = nums1.length,n = nums2.length;
if(m*n == 0) return null;
HashMap<Integer,Integer> map = new HashMap<>();
ArrayList<Integer> list = new ArrayList<>();
for(int i=0;i<m;i++)
if(!map.containsKey(nums1[i]))
map.put(nums1[i],1);
else
map.replace(nums1[i],map.get(nums1[i]),map.get(nums1[i])+1);
for(int i=0;i<n;i++)
if(map.containsKey(nums2[i]) && map.get(nums2[i])!=0)
list.add(nums2[i]);
map.replace(nums2[i],map.get(nums2[i]),map.get(nums2[i])-1);
return list.stream().mapToInt(Integer::intValue).toArray();
以上是关于哈希表与索引和统计的主要内容,如果未能解决你的问题,请参考以下文章