簡體   English   中英

找到兩個整數的最有效方法,這些整數在特定條件下總和為目標值

[英]Most efficient way to find two integers that sum up to target value with specific conditions

我正在尋找一種有效的方法來打印出在某些條件下總和為目標值的兩個整數:

  • 第一個 int 應該小於該對的第二個 int
  • 打印應按該對中的第一個遞增

我編了一些意大利面條,在時間復雜度上似乎比兩個循環更有效,但是,它不包括排序。 我目前已經沒有想法了。

我的問題如下:

  1. 對 output 進行排序的最佳方法是什么?
  2. 除了我目前的解決方案,還有其他方法可以提高時間復雜度嗎?

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的升序對。

我們知道,如果ab是數組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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM