[英]Most efficient way to find two integers that sum up to target value with specific conditions
我正在尋找一種有效的方法來打印出在某些條件下總和為目標值的兩個整數:
我編了一些意大利面條,在時間復雜度上似乎比兩個循環更有效,但是,它不包括排序。 我目前已經沒有想法了。
我的問題如下:
PS。 輸入和 output 將是大量整數,所以我想知道是否應該替換 System.out.println。
先感謝您。
編輯:我必須打印出所有對。 一個 int 可以是多對。 輸入可以增長到幾十萬個 int。
給定目標 12:示例輸入:2 10 0 8 4 12 8
示例 Output:0 12 2 10 4 8 4 8
public static void myFindPair(int[] arr, int target) {
// Key = difference, value = index
Map<Integer, Integer> map = new HashMap();
for (int i = 0; i < arr.length; i++) {
int difference = target - arr[i];
map.put(difference, i);
System.out.print(arr[i]);
}
for (int i = 0; i < arr.length; i++) {
if (map.containsKey(arr[i]) && map.get(arr[i]) != i) {
int first = arr[i];
int second = arr[map.get(arr[i])];
if (first < second) {
System.out.println(first + " " + second);
}
}
}
}
首先對數組進行排序。 如果arr
已排序並且arr[0] + arr[arr.length - 1] > target
,則arr[arr.length - 1]
不可能是一對; 您將其添加到盡可能小的值,但對於目標來說仍然太大。 同樣,如果arr[0] + arr[arr.length] < target
,則arr[0]
不可能是一對的一部分。 這導致了以下算法。
public /* return type */ findPair(int[] arr, int target)
{
Arrays.sort(arr);
int i = 0, j = arr.length - 1;
while (i < j) {
int sum = arr[i] + arr[j];
if (sum < target) i++;
else if (sum > target) j--;
else {
/* sum == target, so add arr[i] and arr[j] to a set of solutions. */
/* I'm assuming that the elements of arr are unique. */
i++;
j--;
}
}
return /* set of solutions */
}
這是您的問題的一種可能的解決方案:
讓輸入數組 A =
n
的長度設輸入范圍,即數組的最大元素=
k
算法:
Store the frequency of each element of the array A.
Use the frequency array to find pairs.
例子:
A = 2 10 0 8 4 12 8 4
這是對應的頻率數組:
element: 0 1 2 3 4 5 6 7 8 9 10 11 12
frequency: 1 0 1 0 2 0 0 0 2 0 1 0 1
使用頻率數組,我們可以很容易地找到目標總和為T
的升序對。
我們知道,如果a
和b
是數組A
的元素,其中a
<= b
並且它們成對,那么,
a + b = T
b = T - a
使用它,我們可以檢查a
> 0
的頻率和b
> 0
的頻率,那么這樣的一對是可能的。 這樣做我們可以找到O(k)
中的所有對,其中k
=輸入范圍。
解決方案代碼:
private static void printPair(int[] A, int targetSum)
{
//find the maximum element
int max = A[0];
for (int element: A) max = Math.max(max, element);
//Make a frequency array
int[] frequency = new int[max+1];
for (int element: A) frequency[element]++;
//Find pairs
for (int i = 0;i < frequency.length/2;i++)
{
if (targetSum - i < 0) break;
if (frequency[i] > 0 && frequency[targetSum-i] > 0)
{
while (Math.min(frequency[i], frequency[targetSum-i]) > 0)
{
System.out.print("Pair: " + i + "\t" + (targetSum - i));
System.out.println();
frequency[i]--;
frequency[targetSum - i]--;
}
}
}
}
里面還有一個 while 循環,因為如果數組中存在單對f
次,我們需要打印它f
次。
如果您使用更好的counting sort
實現,我發布的解決方案可以得到改進。 在我的解決方案中,我使用了:
輸入范圍,即數組的最大元素=
k
我是故意這樣做的,所以解決方案更容易理解。 但是,如果我們將范圍更改為:
新的輸入范圍,即數組最大元素-數組最小元素=
k
進行此更改也會使此解決方案適用於負數。
如果您使用此范圍,則需要對解決方案進行一些更改,如果您能理解我提供的解決方案,那么這些更改並不難。 您只需要更改訪問數組每個元素的頻率的方式。 這是改進計數排序的鏈接: https://www.geeksforgeeks.org/counting-sort/
解的時間復雜度:
該解決方案的時間復雜度為O(n+k)
。 這看起來像是線性時間復雜度。 但是,這取決於輸入。
認為:
A = 4 3 30 5 1
這里,
n = 5
k = 30
k
幾乎等於n^2
。 因此,解決方案的時間復雜度變為O(n + n^2)
= O(n^2)
。 因此,時間復雜度嚴格取決於可能的輸入類型。
我希望我對你有所幫助。 我沒有詳細介紹解決方案代碼,因為這樣做會使答案太長。 但是,如果您無法理解解釋、解決方案代碼或者您還希望我發布第二個可能的解決方案,請發表評論。 我很樂意幫助你。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.