Amazon Online Assessment (OA) - Two Sum - Unique Pairs
Write a function that takes a list of numbers and a target number, and then returns the number of unique pairs that add up to the target number.
[X, Y] and [Y, X] are considered the same pair, and not unique.
Examples
Example 1:
Input: [1, 1, 2, 45, 46, 46], target = 47
Output: 2
Explanation:
1 + 46 = 47
2 + 45 = 47
Example 2:
Input: [1, 1], target = 2
Output: 1
Explanation:
1 + 1 = 2
Example 3:
Input: [1, 5, 1, 5], target = 6
Output: 1
Explanation:
[1, 5] and [5, 1] are considered the same, therefore there is only one unique pair that adds up to 6.
Try it yourself
Solution
Prereq: Two sum
Explanation
Implement a regular solution for the two-sum problem, but use a set to check for and discard duplicates.
Implementation
1def two_sum_unique_pairs(nums: list[int], target: int) -> int:
2 seen = set()
3 complement = set()
4 for num in nums:
5 if target - num in complement:
6 pair = (num, target - num) if num < target - num else (target - num, num)
7 seen.add(pair)
8 complement.add(num)
9 return len(seen)
10
11if __name__ == "__main__":
12 nums = [int(x) for x in input().split()]
13 target = int(input())
14 res = two_sum_unique_pairs(nums, target)
15 print(res)
161import java.util.Arrays;
2import java.util.HashSet;
3import java.util.List;
4import java.util.Scanner;
5import java.util.Set;
6import java.util.stream.Collectors;
7
8class Solution {
9 public static int twoSumUniquePairs(List<Integer> nums, int target) {
10 Set<Integer> seen = new HashSet<>();
11 Set<Integer> complement = new HashSet<>();
12 int ans = 0;
13 for (Integer num : nums) {
14 if (complement.contains(target - num) && !seen.contains(num)) {
15 // (num, target - num) is a pair that sums to the target
16 ans++;
17 // mark num and target - num as seen so that when we see (target - num, num) it won't be counted again
18 seen.add(num);
19 seen.add(target - num);
20 }
21 complement.add(num);
22 }
23 return ans;
24 }
25
26 public static List<String> splitWords(String s) {
27 return s.isEmpty() ? List.of() : Arrays.asList(s.split(" "));
28 }
29
30 public static void main(String[] args) {
31 Scanner scanner = new Scanner(System.in);
32 List<Integer> nums = splitWords(scanner.nextLine()).stream().map(Integer::parseInt).collect(Collectors.toList());
33 int target = Integer.parseInt(scanner.nextLine());
34 scanner.close();
35 int res = twoSumUniquePairs(nums, target);
36 System.out.println(res);
37 }
38}
391using System;
2using System.Collections.Generic;
3using System.Linq;
4
5class Solution
6{
7 public static int TwoSumUniquePairs(List<int> nums, int target)
8 {
9 var seen = new HashSet<(int, int)>();
10 var complement = new HashSet<int>();
11 foreach (int num in nums)
12 {
13 if (complement.Contains(target - num))
14 {
15 var pair = num < target - num ? (num, target - num) : (target - num, num);
16 seen.Add(pair);
17 }
18 complement.Add(num);
19 }
20 return seen.Count;
21 }
22
23 public static List<string> SplitWords(string s)
24 {
25 return string.IsNullOrEmpty(s) ? new List<string>() : s.Trim().Split(' ').ToList();
26 }
27
28 public static void Main()
29 {
30 List<int> nums = SplitWords(Console.ReadLine()).Select(int.Parse).ToList();
31 int target = int.Parse(Console.ReadLine());
32 int res = TwoSumUniquePairs(nums, target);
33 Console.WriteLine(res);
34 }
35}
361"use strict";
2
3function twoSumUniquePairs(nums, target) {
4 const seen = new Set();
5 const complement = new Set();
6 for (const num of nums) {
7 if (complement.has(target - num)) {
8 const pair = num < target - num ? `${num},${target - num}` : `${target - num},${num}`;
9 seen.add(pair);
10 }
11 complement.add(num);
12 }
13 return seen.size;
14}
15
16function splitWords(s) {
17 return s === "" ? [] : s.split(" ");
18}
19
20function* main() {
21 const nums = splitWords(yield).map((v) => parseInt(v));
22 const target = parseInt(yield);
23 const res = twoSumUniquePairs(nums, target);
24 console.log(res);
25}
26
27class EOFError extends Error {}
28{
29 const gen = main();
30 const next = (line) => gen.next(line).done && process.exit();
31 let buf = "";
32 next();
33 process.stdin.setEncoding("utf8");
34 process.stdin.on("data", (data) => {
35 const lines = (buf + data).split("\n");
36 buf = lines.pop();
37 lines.forEach(next);
38 });
39 process.stdin.on("end", () => {
40 buf && next(buf);
41 gen.throw(new EOFError());
42 });
43}
441function twoSumUniquePairs(nums: number[], target: number): number {
2 const seen = new Set<string>();
3 const complement = new Set<number>();
4 for (const num of nums) {
5 if (complement.has(target - num)) {
6 const pair = num < target - num ? `${num},${target - num}` : `${target - num},${num}`;
7 seen.add(pair);
8 }
9 complement.add(num);
10 }
11 return seen.size;
12}
13
14function splitWords(s: string): string[] {
15 return s === "" ? [] : s.split(" ");
16}
17
18function* main() {
19 const nums = splitWords(yield).map((v) => parseInt(v));
20 const target = parseInt(yield);
21 const res = twoSumUniquePairs(nums, target);
22 console.log(res);
23}
24
25class EOFError extends Error {}
26{
27 const gen = main();
28 const next = (line?: string) => gen.next(line ?? "").done && process.exit();
29 let buf = "";
30 next();
31 process.stdin.setEncoding("utf8");
32 process.stdin.on("data", (data) => {
33 const lines = (buf + data).split("\n");
34 buf = lines.pop() ?? "";
35 lines.forEach(next);
36 });
37 process.stdin.on("end", () => {
38 buf && next(buf);
39 gen.throw(new EOFError());
40 });
41}
421#include <algorithm>
2#include <iostream>
3#include <iterator>
4#include <limits>
5#include <set>
6#include <sstream>
7#include <string>
8#include <unordered_set>
9#include <utility>
10#include <vector>
11
12int two_sum_unique_pairs(std::vector<int> nums, int target) {
13 std::set<std::pair<int, int>> seen;
14 std::unordered_set<int> complement;
15 for (int num : nums) {
16 if (complement.count(target - num)) {
17 auto pair = num < target - num
18 ? std::make_pair(num, target - num)
19 : std::make_pair(target - num, num);
20 seen.insert(pair);
21 }
22 complement.insert(num);
23 }
24 return seen.size();
25}
26
27template<typename T>
28std::vector<T> get_words() {
29 std::string line;
30 std::getline(std::cin, line);
31 std::istringstream ss{line};
32 ss >> std::boolalpha;
33 std::vector<T> v;
34 std::copy(std::istream_iterator<T>{ss}, std::istream_iterator<T>{}, std::back_inserter(v));
35 return v;
36}
37
38void ignore_line() {
39 std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
40}
41
42int main() {
43 std::vector<int> nums = get_words<int>();
44 int target;
45 std::cin >> target;
46 ignore_line();
47 int res = two_sum_unique_pairs(nums, target);
48 std::cout << res << '\n';
49}
501use std::collections::HashSet;
2use std::error;
3use std::io;
4use std::str::FromStr;
5
6fn two_sum_unique_pairs(nums: Vec<i32>, target: i32) -> i32 {
7 let mut seen = HashSet::new();
8 let mut complement = HashSet::new();
9 for num in nums {
10 if complement.contains(&(target - num)) {
11 let pair = if num < target - num {
12 (num, target - num)
13 } else {
14 (target - num, num)
15 };
16 seen.insert(pair);
17 }
18 complement.insert(num);
19 }
20 seen.len() as i32
21}
22
23fn main() -> Result<(), Box<dyn error::Error>> {
24 let mut line = String::new();
25 io::stdin().read_line(&mut line)?;
26 let nums = line
27 .split_whitespace()
28 .map(i32::from_str)
29 .collect::<Result<_, _>>()?;
30 let mut line = String::new();
31 io::stdin().read_line(&mut line)?;
32 let target = line.trim_end().parse()?;
33 let res = two_sum_unique_pairs(nums, target);
34 println!("{}", res);
35 Ok(())
36}
371package main
2
3import (
4 "bufio"
5 "fmt"
6 "os"
7 "strconv"
8 "strings"
9)
10
11func twoSumUniquePairs(nums []int, target int) int {
12 type pair struct{ a, b int }
13 seen := make(map[pair]bool)
14 complement := make(map[int]bool)
15 for _, num := range nums {
16 if complement[target-num] {
17 p := pair{num, target - num}
18 if num > target-num {
19 p = pair{target - num, num}
20 }
21 seen[p] = true
22 }
23 complement[num] = true
24 }
25 return len(seen)
26}
27
28func arrayAtoi(arr []string) []int {
29 res := []int{}
30 for _, x := range arr {
31 v, _ := strconv.Atoi(x)
32 res = append(res, v)
33 }
34 return res
35}
36
37func splitWords(s string) []string {
38 if s == "" {
39 return []string{}
40 }
41 return strings.Split(s, " ")
42}
43
44func main() {
45 scanner := bufio.NewScanner(os.Stdin)
46 scanner.Scan()
47 nums := arrayAtoi(splitWords(scanner.Text()))
48 scanner.Scan()
49 target, _ := strconv.Atoi(scanner.Text())
50 res := twoSumUniquePairs(nums, target)
51 fmt.Println(res)
52}
531#lang racket
2
3(define (two-sum-unique-pairs nums target)
4 (define-values (seen _)
5 (for/fold ([seen (set)] [complement (set)])
6 ([num (in-list nums)])
7 (if (set-member? complement (- target num))
8 (let ([pair (if (< num (- target num))
9 (cons num (- target num))
10 (cons (- target num) num))])
11 (values (set-add seen pair) (set-add complement num)))
12 (values seen (set-add complement num)))))
13 (set-count seen))
14
15(define nums (map string->number (string-split (read-line))))
16(define target (string->number (read-line)))
17(define res (two-sum-unique-pairs nums target))
18(displayln res)
191import qualified Data.Set as Set
2
3twoSumUniquePairs :: [Int] -> Int -> Int
4twoSumUniquePairs nums target = Set.size seen
5 where
6 (seen, _) = foldl process (Set.empty, Set.empty) nums
7 process (seenPairs, complement) num
8 | Set.member (target - num) complement =
9 let pair = if num < target - num then (num, target - num) else (target - num, num)
10 in (Set.insert pair seenPairs, Set.insert num complement)
11 | otherwise = (seenPairs, Set.insert num complement)
12
13main :: IO ()
14main = do
15 nums <- map read . words <$> getLine
16 target <- readLn
17 let res = twoSumUniquePairs nums target
18 print res
19