第一行给出 n 和 S,第二行给出按从小到大(可以有相同值)排好序的 n 个整数 a₁ … aₙ。 找出满足 aᵢ + aⱼ = S 且 i < j 的两个位置 i, j,输出 "i j"(位置从 1 开始)。 同一个位置不能用两次。 若有多个答案,输出 i 最小的,其中再取 j 最大的。 若不存在这样的两个位置,输出 -1。
输入
2 ≤ n ≤ 10,000,-2,000,000,000 ≤ aᵢ ≤ 2,000,000,000,-4,000,000,000 ≤ S ≤ 4,000,000,000,a₁ ≤ a₂ ≤ … ≤ aₙ
输出
一行 "i j",或 -1
样例 1 · stdin
6 4
1 1 2 3 3 3
stdout
1 6
样例 2 · stdin
3 10
1 5 8
stdout
-1
main.py
错误列表00F8 ↓ · ⇧F8 ↑
输入(stdin)
运行时这些行会依次作为 input()/标准输入传入(运行中不会等待输入)。
$ 就绪
请在电脑上打开以编写和运行代码。在手机上可以查看题目和题解。
其他语言怎么写?查看各语言题解 · 8 种语言题解
枚举所有数对在 n = 10,000 时约 5 千万次,太慢。 数列有序,所以用双指针从两端开始:和太小就把左指针右移,太大就把右指针左移,n 步以内结束。 这个方法自然会先找到 i 最小、其次 j 最大的答案。 答案有两个值 (i, j),各语言从函数返回两个值的方式不同:Python 元组 return i, j,JavaScript 数组 return [i, j] 配合 const [i, j] = …,TypeScript 元组类型 [number, number],C# 元组 (int, int) 配合 var (i, j) = …,C++ std::pair 配合 auto [i, j] = …,Java 没有元组所以用 int[](或 record),C 用指针参数 int *pi,Craykon 返回列表 返回 [i, j];。 两个陷阱:用 lo <= hi 循环会把同一个元素用两次,在 1 5 9 里找到 5 + 5 = 10。 另外数值可达 20 亿,两数之和可能超过 int(约 21 亿)——C、C++、Java、C# 必须用 long long/long 读入(Java、C# 溢出后会绕成负数;在 C、C++ 中有符号溢出是未定义行为,结果可能对也可能错);Python、JavaScript、TypeScript、Craykon 直接就对。
Pythonmain.py · 18 行
def find_pair(a, s): """a[i] + a[j] == s 인 (i, j)를 1부터 센 자리로 돌려준다. 없으면 (-1, -1).""" lo, hi = 0, len(a) - 1 while lo < hi: total = a[lo] + a[hi] if total == s: return lo + 1, hi + 1 if total < s: lo += 1 else: hi -= 1 return -1, -1n, s = map(int, input().split())a = list(map(int, input().split()))i, j = find_pair(a, s)print(-1 if i == -1 else f"{i} {j}")
JavaScriptmain.js · 16 行
// a[i] + a[j] === s 인 [i, j]를 1부터 센 자리로 돌려준다. 없으면 [-1, -1].function findPair(a, s) { let lo = 0; let hi = a.length - 1; while (lo < hi) { const total = a[lo] + a[hi]; if (total === s) return [lo + 1, hi + 1]; if (total < s) lo++; else hi--; } return [-1, -1];}const [n, s, ...a] = require("fs").readFileSync(0, "utf8").trim().split(/\s+/).map(Number);const [i, j] = findPair(a, s);console.log(i === -1 ? "-1" : `${i} ${j}`);
TypeScriptmain.ts · 18 行
import { readFileSync } from "node:fs";// a[i] + a[j] === s 인 [i, j]를 1부터 센 자리로 돌려준다. 없으면 [-1, -1].function findPair(a: number[], s: number): [number, number] { let lo = 0; let hi = a.length - 1; while (lo < hi) { const total = a[lo] + a[hi]; if (total === s) return [lo + 1, hi + 1]; if (total < s) lo++; else hi--; } return [-1, -1];}const [n, s, ...a]: number[] = readFileSync(0, "utf8").trim().split(/\s+/).map(Number);const [i, j] = findPair(a, s);console.log(i === -1 ? "-1" : `${i} ${j}`);
JavaMain.java · 30 行
import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.util.StringTokenizer;public class Main { // a[i] + a[j] == s 인 {i, j}를 1부터 센 자리로 돌려준다. 없으면 {-1, -1}. static int[] findPair(long[] a, long s) { int lo = 0, hi = a.length - 1; while (lo < hi) { long total = a[lo] + a[hi]; if (total == s) return new int[] {lo + 1, hi + 1}; if (total < s) lo++; else hi--; } return new int[] {-1, -1}; } public static void main(String[] args) throws IOException { BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); StringTokenizer st = new StringTokenizer(in.readLine()); int n = Integer.parseInt(st.nextToken()); long s = Long.parseLong(st.nextToken()); st = new StringTokenizer(in.readLine()); long[] a = new long[n]; for (int k = 0; k < n; k++) a[k] = Long.parseLong(st.nextToken()); int[] p = findPair(a, s); System.out.println(p[0] == -1 ? "-1" : p[0] + " " + p[1]); }}
C#Main.cs · 27 行
using System;using System.Linq;class Program{ // a[i] + a[j] == s 인 (i, j)를 1부터 센 자리로 돌려준다. 없으면 (-1, -1). static (int, int) FindPair(long[] a, long s) { int lo = 0, hi = a.Length - 1; while (lo < hi) { long total = a[lo] + a[hi]; if (total == s) return (lo + 1, hi + 1); if (total < s) lo++; else hi--; } return (-1, -1); } static void Main() { long s = long.Parse(Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries)[1]); long[] a = Console.ReadLine().Split(' ', StringSplitOptions.RemoveEmptyEntries).Select(long.Parse).ToArray(); var (i, j) = FindPair(a, s); Console.WriteLine(i == -1 ? "-1" : $"{i} {j}"); }}
C++main.cpp · 26 行
#include <iostream>#include <utility>#include <vector>// a[i] + a[j] == s 인 {i, j}를 1부터 센 자리로 돌려준다. 없으면 {-1, -1}.std::pair<int, int> findPair(const std::vector<long long>& a, long long s) { int lo = 0, hi = static_cast<int>(a.size()) - 1; while (lo < hi) { long long total = a[lo] + a[hi]; if (total == s) return {lo + 1, hi + 1}; if (total < s) lo++; else hi--; } return {-1, -1};}int main() { int n; long long s; std::cin >> n >> s; std::vector<long long> a(n); for (auto& x : a) std::cin >> x; auto [i, j] = findPair(a, s); if (i == -1) std::cout << "-1\n"; else std::cout << i << " " << j << "\n";}
Cmain.c · 28 行
#include <stdio.h>/* 값 두 개는 포인터로 돌려준다. 찾으면 1, 없으면 0. */static int find_pair(const long long *a, int n, long long s, int *pi, int *pj) { int lo = 0, hi = n - 1; while (lo < hi) { long long total = a[lo] + a[hi]; if (total == s) { *pi = lo + 1; *pj = hi + 1; return 1; } if (total < s) lo++; else hi--; } return 0;}int main(void) { static long long a[10000]; int n, i, j; long long s; scanf("%d %lld", &n, &s); for (int k = 0; k < n; k++) scanf("%lld", &a[k]); if (find_pair(a, n, s, &i, &j)) printf("%d %d\n", i, j); else puts("-1"); return 0;}
Craykonmain.cray · 36 行
// a[i] + a[j] == s 인 [i, j]를 1부터 센 자리로 돌려준다. 없으면 [-1, -1].짝찾기(a, s){ lo = 0; hi = a.数量 - 1; 当 (lo < hi) { total = a[lo] + a[hi]; 如果 (total == s) { 返回 [lo + 1, hi + 1]; } 如果 (total < s) { lo += 1; } 否则 { hi -= 1; } } 返回 [-1, -1];}첫줄 = 控制台.读数字();s = 첫줄[1];a = 控制台.读数字();답 = 짝찾기(a, s);如果 (답[0] == -1){ 控制台.输出(-1);}否则{ 控制台.输出(답[0] + " " + 답[1]);}