这里是狗蛋的算法江湖,这里的一切都需要用一个叫做算力的东西兑换,而兑换的方式则是做出相应的算法题,这是一个刷题者的故事也是狗蛋儿的算法江湖。蛋儿的算法江湖系列文章关注右侧公众号,回复 狗蛋儿 查看更新哦~
狗蛋儿的算法江湖第一篇 狗蛋儿偷鸡
唉~,真是世风日下,人心不古啊…
暮色降临,帽儿山十里外的一个羊肠小道上,传来了一声悠长的叹息…
顺着羊肠小道走来的是一个生的白白胖胖的,十二三岁模样的少年,
想我程狗蛋,一生算法无双,受人尊敬,今天不就是没有使用算力兑换,偷了寡妇翠花一只鸡么,就把我赶了粗来,这说明什么,这说么,,我偷鸡的手段还不够高明啊…
事情是这样的…
呔,那狗蛋!!竟然偷我鸡,快拿出算力来解除这道题,不然我就把你赶出富贵儿村。
看题!!
给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标。
你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。
示例:
给定 nums = [2, 7, 11, 15], target = 9
因为 nums[0] + nums[1] = 2 + 7 = 9
所以返回 [0, 1]
程狗蛋儿:啊啊啊!!我不会,迪杰斯特拉老爷爷快救我,救我!!
狗蛋儿,你又惹祸了?罢了,,罢了。
方法一:暴力法
暴力法很简单。遍历每个元素 xx,并查找是否存在一个值与 target - xtarget−x 相等的目标元素。
for (int i = 0; i < nums.length; i++) {
for (int j = i + 1; j < nums.length; j++) {
if (nums[j] == target - nums[i]) {
return new int[] { i, j };
}
}
}
throw new IllegalArgumentException("No two sum solution");
}
复杂度分析:
时间复杂度:O(n^2)O(n 2 ), 对于每个元素,我们试图通过遍历数组的其余部分来寻找它所对应的目标元素,这将耗费 O(n)O(n) 的时间。因此时间复杂度为 O(n^2)O(n 2 )。
空间复杂度:O(1)O(1)。
方法二:两遍哈希表
为了对运行时间复杂度进行优化,我们需要一种更有效的方法来检查数组中是否存在目标元素。如果存在,我们需要找出它的索引。保持数组中的每个元素与其索引相互对应的最好方法是什么?哈希表。
通过以空间换取速度的方式,我们可以将查找时间从 O(n)O(n) 降低到 O(1)O(1)。哈希表正是为此目的而构建的,它支持以 近似 恒定的时间进行快速查找。我用“近似”来描述,是因为一旦出现冲突,查找用时可能会退化到 O(n)O(n)。但只要你仔细地挑选哈希函数,在哈希表中进行查找的用时应当被摊销为 O(1)O(1)。
一个简单的实现使用了两次迭代。在第一次迭代中,我们将每个元素的值和它的索引添加到表中。然后,在第二次迭代中,我们将检查每个元素所对应的目标元素(target - nums[i]target−nums[i])是否存在于表中。注意,该目标元素不能是 nums[i]nums[i] 本身!
public int[] twoSum(int[] nums, int target) {Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
map.put(nums[i], i);
}
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement) && map.get(complement) != i) {
return new int[] { i, map.get(complement) };
}
}
throw new IllegalArgumentException("No two sum solution");
}
复杂度分析:
时间复杂度:O(n)O(n), 我们把包含有 nn 个元素的列表遍历两次。由于哈希表将查找时间缩短到 O(1)O(1) ,所以时间复杂度为 O(n)O(n)。
空间复杂度:O(n)O(n), 所需的额外空间取决于哈希表中存储的元素数量,该表中存储了 nn 个元素。
方法三:一遍哈希表
事实证明,我们可以一次完成。在进行迭代并将元素插入到表中的同时,我们还会回过头来检查表中是否已经存在当前元素所对应的目标元素。如果它存在,那我们已经找到了对应解,并立即将其返回。
Map<Integer, Integer> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
int complement = target - nums[i];
if (map.containsKey(complement)) {
return new int[] { map.get(complement), i };
}
map.put(nums[i], i);
}
throw new IllegalArgumentException("No two sum solution");
}
复杂度分析:
时间复杂度:O(n)O(n), 我们只遍历了包含有 nn 个元素的列表一次。在表中进行的每次查找只花费 O(1)O(1) 的时间。
空间复杂度:O(n)O(n), 所需的额外空间取决于哈希表中存储的元素数量,该表最多需要存储 nn 个元素。
寡妇翠花,你不不是凭自己的实力搞定的,这次先饶过你,以后不许回富贵儿村了。
程狗蛋背着小手,哼着小曲儿,继续走在羊肠小道上,还好我狗蛋儿有实力,每次做算法题都是靠着自己的实力赢得了尊敬的,
想到这里,狗蛋儿擦了擦嘴角的油,感到越发的得意,,我狗蛋儿能吃到鸡,完全靠自己的天资无双啊…,
走着走着,夜色渐渐的降临了,帽儿山上的夜晚静凄凄的,突然一声尖叫打破了帽儿山的宁静…
欲知后事如何右侧关注回复 狗蛋儿,或者坐等明天更新~