ค้นหาคู่ขององค์ประกอบจากอาร์เรย์ที่มีผลรวมเท่ากับจำนวนที่กำหนด


122

กำหนดอาร์เรย์ของจำนวนเต็ม n และกำหนดจำนวน X ให้ค้นหาคู่ขององค์ประกอบที่ไม่ซ้ำกันทั้งหมด (a, b) ซึ่งผลรวมเท่ากับ X

ต่อไปนี้เป็นวิธีแก้ปัญหาของฉันมันคือ O (nLog (n) + n) แต่ฉันไม่แน่ใจว่าเหมาะสมหรือไม่

int main(void)
{
    int arr [10] = {1,2,3,4,5,6,7,8,9,0};
    findpair(arr, 10, 7);
}
void findpair(int arr[], int len, int sum)
{
    std::sort(arr, arr+len);
    int i = 0;
    int j = len -1;
    while( i < j){
        while((arr[i] + arr[j]) <= sum && i < j)
        {
            if((arr[i] + arr[j]) == sum)
                cout << "(" << arr[i] << "," << arr[j] << ")" << endl;
            i++;
        }
        j--;
        while((arr[i] + arr[j]) >= sum && i < j)
        {
            if((arr[i] + arr[j]) == sum)
                cout << "(" << arr[i] << "," << arr[j] << ")" << endl;
            j--;
        }
    }
}

3
วิธีแก้ปัญหา O (n) เป็นไปได้ถ้าคุณจับทุกอย่างเป็นชุด O (1) บางชนิดแทนที่จะจัดเรียงอาร์เรย์
อานนท์.

1
@Anon คุณสามารถบอกรายละเอียดเพิ่มเติมวิธีการสร้างชุดดังกล่าวได้อย่างไร?
Gin

3
ใช้แฮช ภาษาส่วนใหญ่จะมี O (1) HashSet ที่ตัดจำหน่ายที่ไหนสักแห่งในไลบรารีมาตรฐานของตน
อานนท์.

15
nit เล็กน้อย - O (nLog (n) + n) คือ O (nLog (n)) สัญกรณ์ Big O ยังคงรักษาเฉพาะคำที่โดดเด่นและลดเงื่อนไขลำดับที่ต่ำกว่าทั้งหมด
pjs

2
หมายเหตุ: การประเมินผลการลัดวงจรและปิดโดยหนึ่งที่อยู่: ควรจะเป็นwhile((arr[i] + arr[j]) <= sum && i < j) while( i < J && arr[i] + arr[j] <= sum )(คล้ายกับ subloop ที่สอง)
wildplasser

คำตอบ:


135
# Let arr be the given array.
# And K be the give sum


for i=0 to arr.length - 1 do
  hash(arr[i]) = i  // key is the element and value is its index.
end-for

for i=0 to arr.length - 1 do
  if hash(K - arr[i]) != i  // if Kth element exists and it's different then we found a pair
    print "pair i , hash(K - arr[i]) has sum K"
  end-if
end-for

26
คุณสามารถทำได้ในการวนซ้ำครั้งเดียวผ่านอาร์เรย์โดยใส่คำสั่ง if ของคุณจากลูปที่สองหลังจากการกำหนดแฮชในลูปแรก
Alexander Kondratskiy

4
หมายเหตุเล็กน้อย: สิ่งนี้ (เช่นเดียวกับข้อเสนอแนะของ Alexander) จะพิมพ์คู่บางคู่ไม่ว่าความเป็นเอกลักษณ์ของคู่จะถูกกำหนดโดยดัชนี (ตามที่นัยได้จากคำตอบนี้) หรือตามค่า (ตามที่ปรากฏใน OP) อาจจะมีค่อนข้างน้อย (O (n ^ 2)) arr=[1,2,1,2,1,2,1,...]คู่ที่ไม่ซ้ำกันโดยดัชนีเช่น เพื่อความไม่ซ้ำกันตามค่าดูเหมือนว่าตารางแฮชอื่นที่คีย์ด้วยคู่ค่าจะทำเคล็ดลับ ยังคงเป็นคำตอบที่สวยงามกะทัดรัดและสวยงาม +1
William

2
@codaddict แต่ถ้าอาร์เรย์มีขนาดใหญ่มากล่ะ? ฉันหมายถึงช่วงของค่าในนั้นมาก? ดังนั้นวิธีแก้แฮชจะใช้งานได้จริงน้อยลง วิธีอื่นและวิธีที่ดีที่สุดสำหรับวิธีเดียวกันนี้หรือไม่?
Prashant Singh

15
จะเกิดอะไรขึ้นถ้ามีรายการที่ซ้ำกัน?
zad

2
ไม่hash(K - arr[i]) != iอย่างใดตรวจสอบทั้งการแสดงตนและการขาดการแข่งขันหรือไม่ ฉันคาดว่าจะมีการตรวจสอบการแสดงตนแยกต่างหาก
Joseph Garvin

184

วิธีแก้ปัญหานี้มี 3 วิธี:

ให้ผลรวมเป็น T และ n เป็นขนาดของอาร์เรย์

แนวทางที่ 1:
วิธีที่ไร้เดียงสาในการทำเช่นนี้คือการตรวจสอบชุดค่าผสมทั้งหมด (n เลือก 2) การค้นหาที่ละเอียดถี่ถ้วนนี้คือ O (n 2 )

แนวทางที่ 2: 
 วิธีที่ดีกว่าคือการจัดเรียงอาร์เรย์ สิ่งนี้ใช้เวลา O (n log n)
จากนั้นสำหรับแต่ละ x ในอาร์เรย์ A ให้ใช้การค้นหาแบบไบนารีเพื่อค้นหา Tx สิ่งนี้จะใช้เวลา O (nlogn)
ดังนั้นการค้นหาโดยรวมคือ O (n log n)

แนวทางที่ 3:
วิธีที่ดีที่สุดคือการแทรกทุกองค์ประกอบลงในตารางแฮช (โดยไม่ต้องเรียงลำดับ) สิ่งนี้ใช้ O (n) เป็นการแทรกเวลาคงที่
จากนั้นสำหรับทุกๆ x เราสามารถค้นหาส่วนเติมเต็มของมันได้ Tx ซึ่งก็คือ O (1)
เวลาทำงานโดยรวมของแนวทางนี้คือ O (n)


คุณสามารถอ้างอิงเพิ่มเติมได้ที่นี่ขอบคุณ



คุณจะสร้างตารางแฮชสำหรับองค์ประกอบของอาร์เรย์ได้อย่างไร
Satish Patel

อ้างอิงลิงค์ที่ฉันแชร์ เราสามารถมีอาร์เรย์คู่ขนานเพื่อจัดเก็บองค์ประกอบเป็นดัชนีหรือคุณสามารถเพิ่มองค์ประกอบลงในแฮชแท็กและใช้งานที่มีอยู่ ขออภัยที่ตอบกลับช้า
kinshuk4

11
คุณอาจได้รับผลบวกปลอมหากมีองค์ประกอบที่เท่ากับครึ่งหนึ่งของผลรวมเป้าหมาย
Florian F

2
@Florian_F คุณไม่สามารถเป็นกรณีพิเศษที่คุณมีองค์ประกอบที่เป็นครึ่งหนึ่งได้หรือไม่?
Joseph Garvin

1
@jazzz ฉันหมายถึง HashMap ที่นี่แม้ว่า HashSet จะทำเช่นกัน นี่คือการดำเนินการ - github.com/kinshuk4/AlgorithmUtil/blob/master/src/com/vaani/... หวังว่าจะช่วยได้
kinshuk4

64

การใช้งานใน Java: การใช้อัลกอริทึมของ codaddict (อาจแตกต่างกันเล็กน้อย)

import java.util.HashMap;

public class ArrayPairSum {


public static void main(String[] args) {        

    int []a = {2,45,7,3,5,1,8,9};
    printSumPairs(a,10);        

}


public static void printSumPairs(int []input, int k){
    Map<Integer, Integer> pairs = new HashMap<Integer, Integer>();

    for(int i=0;i<input.length;i++){

        if(pairs.containsKey(input[i]))
            System.out.println(input[i] +", "+ pairs.get(input[i]));
        else
            pairs.put(k-input[i], input[i]);
    }

}
}

สำหรับ input = {2,45,7,3,5,1,8,9}และถ้า Sum คือ10

คู่เอาต์พุต:

3,7 
8,2
9,1

หมายเหตุเกี่ยวกับการแก้ปัญหา:

  • เราวนซ้ำเพียงครั้งเดียวผ่านอาร์เรย์ -> O (n) เวลา
  • เวลาในการแทรกและค้นหาใน Hash คือ O (1)
  • เวลาโดยรวมคือ O (n) แม้ว่าจะใช้พื้นที่พิเศษในแง่ของแฮช

1
จะดีก็ต่อเมื่ออาร์เรย์อินพุตไม่ซ้ำกัน
เรนท

2
@ นเรน: มันไม่สร้างความแตกต่างแม้ว่าจะมีรายการที่ซ้ำกันในอาร์เรย์ที่กำหนดก็ตาม
abhishek08aug

1
มันไม่ได้ใช้สิ่งที่ codaddicts เขียนและสิ่งที่คุณทำแม้ว่ามันจะได้ผล แต่ก็ซับซ้อนโดยไม่จำเป็น มันไม่มีความหมายสำหรับput(k-input[i], input[i])(codaddicts ทำให้ดัชนีเป็นค่าที่มีประโยชน์) สิ่งที่คุณเขียนสามารถทำให้ง่ายขึ้นfor (i:input){ if (intSet.contains(sum-i) { print(i + "," + (sum-i) ); } else {intSet.add(i)}
Adrian Shum

1
โอเคขอบคุณ. เพื่อวัตถุประสงค์ในการอ้างอิงของบุคคลอื่นฉันเพิ่งสร้างเธรดอื่นขึ้นมาเพื่อให้ผู้ที่มีปัญหาในการวิเคราะห์วิธีการทำงานของโซลูชันนี้สามารถเข้าใจได้อย่างถูกต้อง นี่คือลิงค์: stackoverflow.com/questions/33274952/…
John

2
@ abhishek08 สิงหาคมสิ่งนี้จะใช้ไม่ได้สำหรับวันที่ {1, 1, 1}
jbakirov

8

โซลูชันใน java คุณสามารถเพิ่มองค์ประกอบ String ทั้งหมดใน ArrayList ของสตริงและส่งคืนรายการ ฉันแค่พิมพ์มันออกมา

void numberPairsForSum(int[] array, int sum) {
    HashSet<Integer> set = new HashSet<Integer>();
    for (int num : array) {
        if (set.contains(sum - num)) {
            String s = num + ", " + (sum - num) + " add up to " + sum;
            System.out.println(s);
        }
        set.add(num);
    }
}

4

การใช้งาน Python:

import itertools
list = [1, 1, 2, 3, 4, 5,]
uniquelist = set(list)
targetsum = 5
for n in itertools.combinations(uniquelist, 2):
    if n[0] + n[1] == targetsum:
        print str(n[0]) + " + " + str(n[1])

เอาท์พุท:

1 + 4
2 + 3

2
มองเข้าไป ... จะเป็นค่าใช้จ่ายในการค้นหาองค์ประกอบ
Nikhil Rupanawar

4

C ++ 11 ความซับซ้อนของเวลาทำงาน O (n):

#include <vector>
#include <unordered_map>
#include <utility>

std::vector<std::pair<int, int>> FindPairsForSum(
        const std::vector<int>& data, const int& sum)
{
    std::unordered_map<int, size_t> umap;
    std::vector<std::pair<int, int>> result;
    for (size_t i = 0; i < data.size(); ++i)
    {
        if (0 < umap.count(sum - data[i]))
        {
            size_t j = umap[sum - data[i]];
            result.push_back({data[i], data[j]});
        }
        else
        {
            umap[data[i]] = i;
        }
    }

    return result;
}

3

นี่คือวิธีแก้ปัญหาแม่มดคำนึงถึงรายการที่ซ้ำกัน มันเขียนด้วยจาวาสคริปต์และถือว่าอาร์เรย์ถูกจัดเรียง โซลูชันทำงานในเวลา O (n) และไม่ใช้หน่วยความจำเพิ่มเติมใด ๆ นอกเหนือจากตัวแปร

var count_pairs = function(_arr,x) {
  if(!x) x = 0;
  var pairs = 0;
  var i = 0;
  var k = _arr.length-1;
  if((k+1)<2) return pairs;
  var halfX = x/2; 
  while(i<k) {
    var curK = _arr[k];
    var curI = _arr[i];
    var pairsThisLoop = 0;
    if(curK+curI==x) {
      // if midpoint and equal find combinations
      if(curK==curI) {
        var comb = 1;
        while(--k>=i) pairs+=(comb++);
        break;
      }
      // count pair and k duplicates
      pairsThisLoop++;
      while(_arr[--k]==curK) pairsThisLoop++;
      // add k side pairs to running total for every i side pair found
      pairs+=pairsThisLoop;
      while(_arr[++i]==curI) pairs+=pairsThisLoop;
    } else {
      // if we are at a mid point
      if(curK==curI) break;
      var distK = Math.abs(halfX-curK);
      var distI = Math.abs(halfX-curI);
      if(distI > distK) while(_arr[++i]==curI);
      else while(_arr[--k]==curK);
    }
  }
  return pairs;
}

ฉันแก้ปัญหานี้ได้ในระหว่างการสัมภาษณ์ บริษัท ขนาดใหญ่ พวกเขาเอาไป แต่ไม่ใช่ฉัน ดังนั้นที่นี่จึงเหมาะสำหรับทุกคน

เริ่มต้นที่ทั้งสองด้านของอาร์เรย์และค่อยๆเดินเข้าด้านในให้แน่ใจว่าได้นับรายการที่ซ้ำกันหากมีอยู่

นับเฉพาะคู่เท่านั้น แต่สามารถทำใหม่ได้

  • หาคู่
  • หาคู่ <x
  • หาคู่> x

สนุก!


บรรทัดเหล่านี้ใช้ทำอะไร: if(distI > distK) while(_arr[++i]==curI); else while(_arr[--k]==curK);
Yuriy Chernyshov

เส้นเหล่านี้จะข้ามผ่านค่าที่ซ้ำกันจากด้านใดด้านหนึ่งและนับเป็นคู่หากเป็นส่วนหนึ่งของคู่ sum = N
Drone Brain

3

บน)

def find_pairs(L,sum):
    s = set(L)
    edgeCase = sum/2
    if L.count(edgeCase) ==2:
        print edgeCase, edgeCase
    s.remove(edgeCase)      
    for i in s:
        diff = sum-i
        if diff in s: 
            print i, diff


L = [2,45,7,3,5,1,8,9]
sum = 10          
find_pairs(L,sum)

ระเบียบวิธี: a + b = c ดังนั้นแทนที่จะมองหา (a, b) เรามองหา a = c - b


จะไม่ตื่นหากคุณมีข้อมูลที่ซ้ำกันเช่นนี้: [3, 4, 3, 2, 5] และ sum = 6
Anton Danilchenko

แก้ไขขอบทั้งหมดแล้วลอง
garg10 อาจ

2

การใช้งานใน Java: การใช้อัลกอริทึมของ codaddict:

import java.util.Hashtable;
public class Range {

public static void main(String[] args) {
    // TODO Auto-generated method stub
    Hashtable mapping = new Hashtable();
    int a[]= {80,79,82,81,84,83,85};
    int k = 160;

    for (int i=0; i < a.length; i++){
        mapping.put(a[i], i);
    }

    for (int i=0; i < a.length; i++){
        if (mapping.containsKey(k - a[i]) && (Integer)mapping.get(k-a[i]) != i){
            System.out.println(k-a[i]+", "+ a[i]);
        }
    }      

}

}

เอาท์พุท:

81, 79
79, 81

หากคุณต้องการคู่ที่ซ้ำกัน(เช่น 80,80) ให้ลบการแมป&& (จำนวนเต็ม) get (ka [i])! = iจากเงื่อนไข if และคุณก็พร้อมที่จะไป


สำหรับ C # นี่อาจจะใช้ได้ - int k = 16; int นับ = 0; int [] intArray = {5, 7, 11, 23,8,9,15,1,10,6}; สำหรับ (int i = 0; i <intArray.Length; i ++) {สำหรับ (int j = i; j <intArray.Length; j ++) {if ((k - intArray [i]) == intArray [j]) { นับ ++; }}} Console.WriteLine (count);
MukulSharma

2

เพิ่งเข้าร่วมคำถามนี้ใน HackerRank และนี่คือโซลูชัน 'Objective C'ของฉัน:

-(NSNumber*)sum:(NSArray*) a andK:(NSNumber*)k {
    NSMutableDictionary *dict = [NSMutableDictionary dictionary];
    long long count = 0;
    for(long i=0;i<a.count;i++){

        if(dict[a[i]]) {
            count++;
            NSLog(@"a[i]: %@, dict[array[i]]: %@", a[i], dict[a[i]]);
        }
        else{
            NSNumber *calcNum = @(k.longLongValue-((NSNumber*)a[i]).longLongValue);
            dict[calcNum] = a[i];
        }

    }
    return @(count);
}

หวังว่ามันจะช่วยใครบางคน


ไวยากรณ์ของโค้ดนั้นเข้าใจยากกว่าอัลกอริทึมนั่นเอง! :)
Rajendra Uppal

1

นี่คือการนำ O (n * lg n) มาใช้โดยใช้การค้นหาไบนารีภายในลูป

#include <iostream>

using namespace std;

bool *inMemory;


int pairSum(int arr[], int n, int k)
{
    int count = 0;

    if(n==0)
        return count;
    for (int i = 0; i < n; ++i)
    {
        int start = 0;
        int end = n-1;      
        while(start <= end)
        {
            int mid = start + (end-start)/2;
            if(i == mid)
                break;
            else if((arr[i] + arr[mid]) == k && !inMemory[i] && !inMemory[mid])
            {
                count++;
                inMemory[i] = true;
                inMemory[mid] = true;
            }
            else if(arr[i] + arr[mid] >= k)
            {
                end = mid-1;
            }
            else
                start = mid+1;
        }
    }
    return count;
}


int main()
{
    int arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    inMemory = new bool[10];
    for (int i = 0; i < 10; ++i)
    {
        inMemory[i] = false;
    }
    cout << pairSum(arr, 10, 11) << endl;
    return 0;
}


1

ทางออกที่ดีจาก Codeaddict ฉันมีเสรีภาพในการใช้งานเวอร์ชันนี้ใน Ruby:

def find_sum(arr,sum)
 result ={}
 h = Hash[arr.map {|i| [i,i]}]
 arr.each { |l| result[l] = sum-l  if h[sum-l] && !result[sum-l]  }
 result
end

ในการอนุญาตให้มีคู่ที่ซ้ำกัน (1,5), (5,1) เราต้องลบ && !result[sum-l]คำสั่งออก


1

นี่คือรหัส Java สำหรับสามวิธี:
1. การใช้ Map O (n) สามารถใช้ HashSet ได้ที่นี่
2. จัดเรียงอาร์เรย์แล้วใช้ BinarySearch เพื่อค้นหาส่วนประกอบ O (nLog (n))
3. BruteForce แบบดั้งเดิมสองลูป O (n ^ 2)

public class PairsEqualToSum {

public static void main(String[] args) {
    int a[] = {1,10,5,8,2,12,6,4};
    findPairs1(a,10);
    findPairs2(a,10);
    findPairs3(a,10);

}


//Method1 - O(N) use a Map to insert values as keys & check for number's complement in map
    static void findPairs1(int[]a, int sum){
        Map<Integer, Integer> pairs = new HashMap<Integer, Integer>();
        for(int i=0; i<a.length; i++){
            if(pairs.containsKey(sum-a[i]))
                System.out.println("("+a[i]+","+(sum-a[i])+")");
            else
               pairs.put(a[i], 0);
        }
    }



//Method2 - O(nlog(n)) using Sort
static void findPairs2(int[]a, int sum){
        Arrays.sort(a);
        for(int i=0; i<a.length/2; i++){
            int complement = sum - a[i];
            int foundAtIndex = Arrays.binarySearch(a,complement);
            if(foundAtIndex >0 && foundAtIndex != i) //to avoid situation where binarySearch would find the original and not the complement like "5"
                System.out.println("("+a[i]+","+(sum-a[i])+")");
        }
 }

//Method 3 - Brute Force O(n^2)
static void findPairs3(int[]a, int sum){

    for(int i=0; i<a.length; i++){
        for(int j=i; j<a.length;j++){
            if(a[i]+a[j] == sum)
                System.out.println("("+a[i]+","+a[j]+")");
        }
    }
}

}

1

โปรแกรมอย่างง่ายใน java สำหรับอาร์เรย์ที่มีองค์ประกอบเฉพาะ:

import java.util.*;
public class ArrayPairSum {
    public static void main(String[] args) { 
        int []a = {2,4,7,3,5,1,8,9,5};
        sumPairs(a,10);  
    }

    public static void sumPairs(int []input, int k){
      Set<Integer> set = new HashSet<Integer>();    
      for(int i=0;i<input.length;i++){

        if(set.contains(input[i]))
            System.out.println(input[i] +", "+(k-input[i]));
        else
            set.add(k-input[i]);
       }
    }
}

1

ข้อมูลโค้ด Java อย่างง่ายสำหรับการพิมพ์คู่ด้านล่าง:

    public static void count_all_pairs_with_given_sum(int arr[], int S){
        if(arr.length < 2){
        return;
    }        
    HashSet values = new HashSet(arr.length);
    for(int value : arr)values.add(value);
    for(int value : arr){
        int difference = S - value;
    if(values.contains(difference) && value<difference){
        System.out.printf("(%d, %d) %n", value, difference);
        }
    }
    }

1

อีกวิธีหนึ่งใน Swift: แนวคิดคือการสร้างแฮชที่เก็บค่าของ (sum - currentValue) และเปรียบเทียบกับค่าปัจจุบันของลูป ความซับซ้อนคือ O (n)

func findPair(list: [Int], _ sum: Int) -> [(Int, Int)]? {
    var hash = Set<Int>() //save list of value of sum - item.
    var dictCount = [Int: Int]() //to avoid the case A*2 = sum where we have only one A in the array
    var foundKeys  = Set<Int>() //to avoid duplicated pair in the result.

    var result = [(Int, Int)]() //this is for the result.
    for item in list {

        //keep track of count of each element to avoid problem: [2, 3, 5], 10 -> result = (5,5)
        if (!dictCount.keys.contains(item)) {
            dictCount[item] = 1
        } else {
            dictCount[item] = dictCount[item]! + 1
        }

        //if my hash does not contain the (sum - item) value -> insert to hash.
        if !hash.contains(sum-item) {
            hash.insert(sum-item)
        }

        //check if current item is the same as another hash value or not, if yes, return the tuple.
        if hash.contains(item) &&
            (dictCount[item] > 1 || sum != item*2) // check if we have item*2 = sum or not.
        {
            if !foundKeys.contains(item) && !foundKeys.contains(sum-item) {
                foundKeys.insert(item) //add to found items in order to not to add duplicated pair.
                result.append((item, sum-item))
            }
        }
    }
    return result
}

//test:
let a = findPair([2,3,5,4,1,7,6,8,9,5,3,3,3,3,3,3,3,3,3], 14) //will return (8,6) and (9,5)

1

โซลูชันของฉัน - Java - ไม่มีรายการที่ซ้ำกัน

    public static void printAllPairSum(int[] a, int x){
    System.out.printf("printAllPairSum(%s,%d)\n", Arrays.toString(a),x);
    if(a==null||a.length==0){
        return;
    }
    int length = a.length;
    Map<Integer,Integer> reverseMapOfArray = new HashMap<>(length,1.0f);
    for (int i = 0; i < length; i++) {
        reverseMapOfArray.put(a[i], i);
    }

    for (int i = 0; i < length; i++) {
        Integer j = reverseMapOfArray.get(x - a[i]);
        if(j!=null && i<j){
            System.out.printf("a[%d] + a[%d] = %d + %d = %d\n",i,j,a[i],a[j],x);
        }
    }
    System.out.println("------------------------------");
}

0

สิ่งนี้จะพิมพ์คู่และหลีกเลี่ยงรายการที่ซ้ำกันโดยใช้การจัดการแบบบิต

public static void findSumHashMap(int[] arr, int key) {
    Map<Integer, Integer> valMap = new HashMap<Integer, Integer>();
    for(int i=0;i<arr.length;i++)
        valMap.put(arr[i], i);

    int indicesVisited = 0; 
    for(int i=0;i<arr.length;i++) {
        if(valMap.containsKey(key - arr[i]) && valMap.get(key - arr[i]) != i) {
            if(!((indicesVisited & ((1<<i) | (1<<valMap.get(key - arr[i])))) > 0)) {
                int diff = key-arr[i];
                System.out.println(arr[i] + " " +diff);
                indicesVisited = indicesVisited | (1<<i) | (1<<valMap.get(key - arr[i]));
            }
        }
    }
}

0

ฉันข้ามการผลิตบิตและเปรียบเทียบค่าดัชนี ค่านี้น้อยกว่าค่าการวนซ้ำ (i ในกรณีนี้) สิ่งนี้จะไม่พิมพ์คู่ที่ซ้ำกันและองค์ประกอบอาร์เรย์ที่ซ้ำกันด้วย

public static void findSumHashMap(int[] arr, int key) {
    Map<Integer, Integer> valMap = new HashMap<Integer, Integer>();
    for (int i = 0; i < arr.length; i++) {
        valMap.put(arr[i], i);
    }
    for (int i = 0; i < arr.length; i++) {
        if (valMap.containsKey(key - arr[i])
                && valMap.get(key - arr[i]) != i) {
            if (valMap.get(key - arr[i]) < i) {
                int diff = key - arr[i];
                System.out.println(arr[i] + " " + diff);
            }
        }
    }
}

0

ใน C #:

        int[] array = new int[] { 1, 5, 7, 2, 9, 8, 4, 3, 6 }; // given array
        int sum = 10; // given sum
        for (int i = 0; i <= array.Count() - 1; i++)
            if (array.Contains(sum - array[i]))
                Console.WriteLine("{0}, {1}", array[i], sum - array[i]);

คำตอบนี้จะมีประโยชน์มากขึ้นหากคุณอธิบายลำดับการเติบโตของโซลูชันของคุณ
Thomas

0

โซลูชันเดียวสามารถเป็นได้ แต่ไม่เหมาะสมที่สุด (ความซับซ้อนของรหัสนี้คือ O (n ^ 2)):

public class FindPairsEqualToSum {

private static int inputSum = 0;

public static List<String> findPairsForSum(int[] inputArray, int sum) {
    List<String> list = new ArrayList<String>();
    List<Integer> inputList = new ArrayList<Integer>();
    for (int i : inputArray) {
        inputList.add(i);
    }
    for (int i : inputArray) {
        int tempInt = sum - i;
        if (inputList.contains(tempInt)) {
            String pair = String.valueOf(i + ", " + tempInt);
            list.add(pair);
        }
    }
    return list;
   }
}

0

โค้ดเวอร์ชัน python อย่างง่ายที่ค้นหาผลรวมคู่ของศูนย์และสามารถแก้ไขเพื่อค้นหา k:

def sumToK(lst):
    k = 0  # <- define the k here
    d = {} # build a dictionary 

# build the hashmap key = val of lst, value = i
for index, val in enumerate(lst):
    d[val] = index

# find the key; if a key is in the dict, and not the same index as the current key
for i, val in enumerate(lst):
    if (k-val) in d and d[k-val] != i:
        return True

return False

ความซับซ้อนของเวลาทำงานของฟังก์ชันคือ O (n) และ Space: O (n) เช่นกัน


0
 public static int[] f (final int[] nums, int target) {
    int[] r = new int[2];
    r[0] = -1;
    r[1] = -1;
    int[] vIndex = new int[0Xfff];
    for (int i = 0; i < nums.length; i++) {
        int delta = 0Xff;
        int gapIndex = target - nums[i] + delta;
        if (vIndex[gapIndex] != 0) {
            r[0] = vIndex[gapIndex];
            r[1] = i + 1;
            return r;
        } else {
            vIndex[nums[i] + delta] = i + 1;
        }
    }
    return r;
}

0

สารละลายน้อยกว่า o (n) จะเป็น =>

function(array,k)
          var map = {};
          for element in array
             map(element) = true;
             if(map(k-element)) 
                 return {k,element}

จะล้มเหลวสำหรับปัจจัยการผลิตบางอย่าง นอกจากนี้คุณต้องคืนเงินจำนวนหนึ่งที่ไม่ใช่ปารีส
Aviad

0

วิธีแก้ปัญหาใน Python โดยใช้การทำความเข้าใจรายการ

f= [[i,j] for i in list for j in list if j+i==X];

O (น2 )

ยังให้คำสั่งสองคู่ - (a, b) และ (b, a) ด้วย


คุณอาจพูดถึงภาษาว่าคู่ (a, b) และ (b, a) ไม่ซ้ำกันหรือไม่และคำถามนี้ตอบคำถามอะไร (คำถามไม่มีคำที่ชัดเจน - I am not sure … Thanks for comments) คุณอาจแสดงว่าแทงที่ความซับซ้อนใกล้ O (n²) มากขึ้น
greybeard

0

ฉันทำได้ใน O (n) แจ้งให้เราทราบเมื่อคุณต้องการคำตอบ โปรดทราบว่ามันเกี่ยวข้องกับการข้ามอาร์เรย์เพียงครั้งเดียวโดยไม่มีการเรียงลำดับ ฯลฯ ... ฉันควรพูดถึงด้วยว่ามันใช้ประโยชน์จากการสับเปลี่ยนของการเพิ่มและไม่ใช้แฮช แต่ทำให้เสียหน่วยความจำ


ใช้ระบบ; ใช้ System.Collections.Generic;

/ * มีแนวทาง O (n) โดยใช้ตารางการค้นหา วิธีการนี้คือการจัดเก็บค่าใน "bin" ที่สามารถค้นหาได้ง่าย (เช่น O (1)) หากเป็นตัวเลือกสำหรับผลรวมที่เหมาะสม

เช่น,

สำหรับแต่ละ a [k] ในอาร์เรย์เราเพียงแค่ใส่ไว้ในอาร์เรย์อื่นที่ตำแหน่ง x - a [k]

สมมติว่าเรามี [0, 1, 5, 3, 6, 9, 8, 7] และ x = 9

เราสร้างอาร์เรย์ใหม่

ค่าดัชนี

9 - 0 = 9     0
9 - 1 = 8     1
9 - 5 = 4     5
9 - 3 = 6     3
9 - 6 = 3     6
9 - 9 = 0     9
9 - 8 = 1     8
9 - 7 = 2     7

จากนั้นค่าเดียวที่สำคัญคือค่าที่มีดัชนีในตารางใหม่

ดังนั้นสมมติว่าเมื่อเราถึง 9 หรือเท่ากับเราจะดูว่าอาร์เรย์ใหม่ของเรามีดัชนี 9 - 9 = 0 หรือไม่เนื่องจากเรารู้ว่าค่าทั้งหมดที่มีจะเพิ่มเป็น 9 (โปรดสังเกตในสาเหตุนี้ชัดเจนมีเพียง 1 เป็นไปได้ แต่อาจมีค่าดัชนีหลายค่าซึ่งเราจำเป็นต้องจัดเก็บ)

ดังนั้นสิ่งที่เราทำได้อย่างมีประสิทธิภาพก็คือการเลื่อนผ่านอาร์เรย์เพียงครั้งเดียว เนื่องจากการเพิ่มเป็นการสับเปลี่ยนเราจะได้ผลลัพธ์ที่เป็นไปได้ทั้งหมด

ตัวอย่างเช่นเมื่อเราถึง 6 เราจะได้ดัชนีในตารางใหม่เป็น 9 - 6 = 3 เนื่องจากตารางมีค่าดัชนีนั้นเราจึงรู้ค่า

นี่คือการแลกเปลี่ยนความเร็วสำหรับหน่วยความจำเป็นหลัก * /

namespace sum
{
    class Program
    {
        static void Main(string[] args)
        {
            int num = 25;
            int X = 10;
            var arr = new List<int>();
            for(int i = 0; i <= num; i++) arr.Add((new Random((int)(DateTime.Now.Ticks + i*num))).Next(0, num*2));
            Console.Write("["); for (int i = 0; i < num - 1; i++) Console.Write(arr[i] + ", "); Console.WriteLine(arr[arr.Count-1] + "] - " + X);
            var arrbrute = new List<Tuple<int,int>>();
            var arrfast = new List<Tuple<int,int>>();

            for(int i = 0; i < num; i++)
            for(int j = i+1; j < num; j++)
                if (arr[i] + arr[j] == X) 
                    arrbrute.Add(new Tuple<int, int>(arr[i], arr[j]));




            int M = 500;
            var lookup = new List<List<int>>();
            for(int i = 0; i < 1000; i++) lookup.Add(new List<int>());
            for(int i = 0; i < num; i++)        
            {
                // Check and see if we have any "matches"
                if (lookup[M + X - arr[i]].Count != 0)
                {
                    foreach(var j in lookup[M + X - arr[i]])
                    arrfast.Add(new Tuple<int, int>(arr[i], arr[j])); 
                }

                lookup[M + arr[i]].Add(i);

            }

            for(int i = 0; i < arrbrute.Count; i++)
                Console.WriteLine(arrbrute[i].Item1 + " + " + arrbrute[i].Item2 + " = " + X);
            Console.WriteLine("---------");
            for(int i = 0; i < arrfast.Count; i++)
                Console.WriteLine(arrfast[i].Item1 + " + " + arrfast[i].Item2 + " = " + X);

            Console.ReadKey();
        }
    }
}

โดยพื้นฐานแล้วเพื่อหลีกเลี่ยงการแฮชเราต้องสร้างตารางที่สามารถยอมรับการแทรกแบบสุ่มในดัชนีที่กำหนดเองได้ ดังนั้นฉันจึงใช้ M เพื่อให้แน่ใจว่ามีองค์ประกอบเพียงพอและจัดสรรชุดที่ต่อเนื่องกันไว้ล่วงหน้าแม้ว่าส่วนใหญ่จะไม่ถูกใช้ ชุดแฮชจะดูแลเรื่องนี้โดยตรง
AbstractDissonance

คุณกำลังใช้ชุดแฮชที่มีฟังก์ชันแฮชอย่างง่ายและมีขนาดมากกว่าค่าสูงสุดของฟังก์ชันแฮชของคุณหรือไม่?
Chris Hopman

นอกจากนี้ยังอาจใช้ฟังก์ชันระบุตัวตนสำหรับฟังก์ชันแฮชของคุณ ณ จุดนี้ด้วย นั่นคือใส่ [k] ที่ a [k] -th "bin"
Chris Hopman

เนื่องจากมีการใช้ [k] และ X - a [k] ดัชนีและฉันใช้อาร์เรย์จึงหมายความว่าดัชนีต่ำสุดไม่สามารถเป็น 0 ได้ดังนั้นฉันจึงเพิ่มตัวเลขจำนวนมากเพื่อเลื่อนขึ้น ถ้าใครสามารถสร้างฟังก์ชันแฮชที่ใช้งานได้ตามอำเภอใจพวกเขาสามารถใช้รายการง่ายๆโดยไม่ต้องทำการขยับนี้ การเปลี่ยนตำแหน่ง + การจัดสรรล่วงหน้าช่วยหลีกเลี่ยงการสร้างแฮช (หรืออาจคิดว่าเป็นแฮชที่ง่ายมาก (และเร็ว)
AbstractDissonance

-1

โซลูชัน Javascript:

var sample_input = [0, 1, 100, 99, 0, 10, 90, 30, 55, 33, 55, 75, 50, 51, 49, 50, 51, 49, 51];
var result = getNumbersOf(100, sample_input, true, []);

function getNumbersOf(targetNum, numbers, unique, res) {
    var number = numbers.shift();

    if (!numbers.length) {
        return res;
    }

    for (var i = 0; i < numbers.length; i++) {
        if ((number + numbers[i]) === targetNum) {
            var result = [number, numbers[i]];
            if (unique) {
              if (JSON.stringify(res).indexOf(JSON.stringify(result)) < 0) {
                res.push(result);                
              }
            } else {
              res.push(result);
            }
            numbers.splice(numbers.indexOf(numbers[i]), 1);
            break;
        }
    }
    return getNumbersOf(targetNum, numbers, unique, res);
}

น่าทึ่งมาก .... คุณกำลังใช้ Stringify (O (n) เวลาและช่องว่าง) การวนซ้ำแต่ละครั้ง ..
Aviad


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.