nlogn
的复杂度下检查数组/列表中任意两个数的和是否等于给定的数字?nlogn
的复杂度下检查数组/列表中任意两个数的和是否等于给定的数字?我相信有更好的方法,但这里提供一个想法:
这两个操作的时间复杂度均为 O(n log n)
。
sum/2
处停止搜索即可(虽然不影响大 O,但还是:p)。 - Matthieu M.使用哈希表可以在 O(n)
的时间复杂度内完成。首先将数组中的所有数字作为键,频率作为值初始化哈希表。遍历数组中的每个数字,并检查是否存在于表中的 (sum - number)
。如果存在,则表示找到了一对匹配的数字。当你遍历完数组中的所有数字后,你就会得到一个列表,其中包含所有相加得到所需数字的数字对。
array = initial array
table = hash(array)
S = sum
for each n in array
if table[S-n] exists
print "found numbers" n, S-n
当n和table[S-n]两次引用同一个数字的情况可以通过额外的检查来处理,但复杂度仍然是O(n)
。
使用 哈希表。将每个数字与其索引一起插入到哈希表中。然后,设 S
是您想要的总和。对于初始数组中的每个数字 array[i]
,查看是否存在具有不同于 i
的索引的值 S - array[i]
在您的哈希表中。
平均情况下为 O(n)
,最坏情况下为 O(n^2)
,因此如果您担心最坏情况,请使用二分搜索解决方案。
O(1)
的时间复杂度(需要一些小心),或者你考虑了潜在的哈希冲突吗?无论如何,这似乎比使用二分查找还要好。 - Matthieu M.{1, 1, 1, ..., 1, 1, 1, ...}
。我们想让它们的和为20。您需要将同一位置上的所有1相加,然后对于每个1,您需要检查数组中是否存在19。假设值19映射到哈希表中与值1相同的位置。这意味着对于每个1,您将在哈希表中执行n次检查,从而导致二次时间复杂度。类似的例子也可以应用于使用3个值(一个占主导地位)有解的情况。 - IVlad1 => 8
。例如,当需要求和为2时,您可以添加一个额外的检查 - 如果当前数字等于目标数字(S-数组[i]),则其频率必须至少为2。 - Anurag假设我们想在数组A中找到两个数,它们相加等于N。
排序可以在O(n log n)时间内完成。搜索可以在线性时间内完成。
这是Java代码: 它甚至删除可能存在的重复值。时间复杂度为O(n^2)
private static int[] intArray = {15,5,10,20,25,30};
private static int sum = 35;
private static void algorithm()
{
Map<Integer, Integer> intMap = new Hashtable<Integer, Integer>();
for (int i=0; i<intArray.length; i++)
{
intMap.put(i, intArray[i]);
if(intMap.containsValue(sum - intArray[i]))
System.out.println("Found numbers : "+intArray[i] +" and "+(sum - intArray[i]));
}
System.out.println(intMap);
}
containsValue
在线性时间内运行,因此总运行时间为O(n^2)
。 - Ivaylo Toskovdef sum_in(numbers, sum_):
"""whether any two numbers from `numbers` form `sum_`."""
a = set(numbers) # O(n)
return any((sum_ - n) in a for n in a) # O(n)
例子:
>>> sum_in([200, -10, -100], 100)
True
[1]
和 [1, 1]
的情况。 - jfs正如我所提到的,拜访过的店铺的最佳用途是当我们有重复元素时,如果没有任何元素是重复的,它永远不会有帮助。
这是C语言的一个尝试。这不是标记为作业。
// Assumes a sorted integer array with no duplicates
void printMatching(int array[], int size, int sum)
{
int i = 0, k = size - 1;
int curSum;
while(i < k)
{
curSum = array[i] + array[k];
if(curSum == sum)
{
printf("Found match at indices %d, %d\n", i, k);
i++;k--;
}
else if(curSum < sum)
{
i++;
}
else
{
k--;
}
}
}
以下是一些测试输出,使用int a[] = { 3, 5, 6, 7, 8, 9, 13, 15, 17 };
Searching for 12..
Found match at indices 0, 5
Found match at indices 1, 3
Searching for 22...
Found match at indices 1, 8
Found match at indices 3, 7
Found match at indices 5, 6
Searching for 4..
Searching for 50..
搜索是线性的,因此为O(n)。如果使用其中一种好的排序算法,则在幕后进行的排序将为O(n*logn)。
由于大O背后的数学原理,加法项中的较小项将有效地从计算中消失,最终得到的结果为O(n logn)。
这个是O(n)的。
public static bool doesTargetExistsInList(int Target, int[] inputArray)
{
if (inputArray != null && inputArray.Length > 0 )
{
Hashtable inputHashTable = new Hashtable();
// This hash table will have all the items in the input array and how many times they appeard
Hashtable duplicateItems = new Hashtable();
foreach (int i in inputArray)
{
if (!inputHashTable.ContainsKey(i))
{
inputHashTable.Add(i, Target - i);
duplicateItems.Add(i, 1);
}
else
{
duplicateItems[i] = (int)duplicateItems[i] + 1;
}
}
foreach (DictionaryEntry de in inputHashTable)
{
if ((int)de.Key == (int)de.Value)
{
if ((int)duplicateItems[de.Key] > 1)
return true;
}
else if (inputHashTable.ContainsKey(de.Value))
{
return true;
}
}
}
return false;
}
A)时间复杂度 => 0(n Log n) 空间复杂度 => 0(n)。
B)时间复杂度 => 0(n^2) 空间复杂度 => 0(1)。
C)时间复杂度 => 0(n) 空间复杂度 => 0(n)
根据权衡选择方案A、B或C。
//***********************方案A*********************//
//如果数组中存在任意两对符合条件的元素,则此方案返回TRUE
func binarySearch(list: [Int], key: Int, start: Int, end: Int) -> Int? { //辅助函数
if end < start {
return -1
} else {
let midIndex = (start + end) / 2
if list[midIndex] > key {
return binarySearch(list: list, key: key, start: start, end: midIndex - 1)
} else if list[midIndex] < key {
return binarySearch(list: list, key: key, start: midIndex + 1, end: end)
} else {
return midIndex
}
}
}
func twoPairSum(sum : Int, inputArray: [Int]) -> Bool {
//仅当数组未排序时执行以下操作!
let sortedArray = inputArray.sorted()
for (currentIndex, value) in sortedArray.enumerated() {
if let indexReturned = binarySearch(list: sortedArray, key: sum - value, start: 0, end: sortedArray.count-1) {
if indexReturned != -1 && (indexReturned != currentIndex) {
return true
}
}
}
return false
}
//***********************方案B*********************//
//如果数组中存在任意两对符合条件的元素,则此方案返回这两对元素的索引
func twoPairSum(_ nums: [Int], _ target: Int) -> [Int] {
for currentIndex in 0..<nums.count {
for nextIndex in currentIndex+1..<nums.count {
if calculateSum(firstElement: nums[currentIndex], secondElement: nums[nextIndex], target: target) {
return [currentIndex, nextIndex]
}
}
}
return []
}
func calculateSum (firstElement: Int, secondElement: Int, target: Int) -> Bool {//辅助函数
return (firstElement + secondElement) == target
}
//*******************方案C*********************//
//如果数组中存在任意两对符合条件的元素,则此方案返回这两对元素的索引
func twoPairSum(_ nums: [Int], _ target: Int) -> [Int] {
var dict = [Int: Int]()
for (index, value) in nums.enumerated() {
dict[value] = index
}
for (index, value) in nums.enumerated() {
let otherIndex = dict[(target - value)]
if otherIndex != nil && otherIndex != index {
return [index, otherIndex!]
}
}
return []
}