news 2026/9/3 0:14:00

(新卷,100分)- 符合要求的元组的个数(Java JS Python C)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
(新卷,100分)- 符合要求的元组的个数(Java JS Python C)

(新卷,100分)- 符合要求的元组的个数(Java & JS & Python & C)

题目描述

给定一个整数数组 nums、一个数字k,一个整数目标值 target,请问nums中是否存在k个元素使得其相加结果为target,请输出所有符合条件且不重复的k元组的个数

数据范围

  • 2 ≤ nums.length ≤ 200
  • -10^9 ≤ nums[i] ≤ 10^9
  • -10^9 ≤ target ≤ 10^9
  • 2 ≤ k ≤ 100
输入描述

第一行是nums取值:2 7 11 15

第二行是k的取值:2

第三行是target取值:9

输出描述

输出第一行是符合要求的元组个数:1

补充说明:[2,7]满足,输出个数是1

用例
输入-1 0 1 2 -1 -4
3
0
输出2
说明[-1,0,1],[-1,-1,2]满足条件
输入2 7 11 15
2
9
输出1
说明[2,7]符合条件

题目解析(分治递归+双指针)

本题其实就是要求K数之和。

本题的K数之和

本题的要求的K元组是从整数数组中选取的,这里的整数数组,既可能包含正数,也可能包含负数,也可能包含0,另外最终求得的符合要求的K元组,还要进行去重。

其中三数之和,是需要固定三元组中的最小的一个值,然后通过双指针找到剩余两个数。

其中四数之和,是需要固定四元组中的最小的两个值,然后通过双指针找到剩余两个数。

而K数之和,其实需要固定K元组中最小的K-2个值,然后通过双指针找到剩余两个数。

因此,下面代码实现中分为了两部分:

  1. K-2重for循环完成 K元组中最小的K-2个值的确定
  2. 通过双指针完成剩余两个值的确定

而实际上K的值是不确定的,因此第1部分的K-2重for循环需要通过递归完成。

具体请看下面代码实现。

JS算法源码
/* JavaScript Node ACM模式 控制台输入获取 */ const readline = require("readline"); const rl = readline.createInterface({ input: process.stdin, output: process.stdout, }); const lines = []; rl.on("line", (line) => { lines.push(line); if (lines.length == 3) { const nums = lines[0].split(" ").map(Number); const k = parseInt(lines[1]); const target = parseInt(lines[2]); console.log(getResult(nums, k, target)); lines.length = 0; } }); function getResult(nums, k, target) { if (k > nums.length) return 0; nums.sort((a, b) => a - b); return kSum(nums, k, target, 0, 0, 0); } // k数之和 function kSum(nums, k, target, start, count, sum) { if (k < 2) return count; if (k == 2) { return twoSum(nums, target, start, count, sum); } for (let i = start; i <= nums.length - k; i++) { // 剪枝 if (nums[i] > 0 && sum + nums[i] > target) break; // 去重 if (i > start && nums[i] == nums[i - 1]) continue; count = kSum(nums, k - 1, target, i + 1, count, sum + nums[i]); } return count; } // 两数之和 function twoSum(nums, target, start, count, preSum) { let l = start; let r = nums.length - 1; while (l < r) { const sum = preSum + nums[l] + nums[r]; if (sum > target) { r--; } else if (sum < target) { l++; } else { count++; // 去重 while (l + 1 < r && nums[l] == nums[l + 1]) l++; // 去重 while (r - 1 > l && nums[r] == nums[r - 1]) r--; l++; r--; } } return count; }
Java算法源码
import java.util.Arrays; import java.util.Scanner; public class Main { public static void main(String[] args) { Scanner sc = new Scanner(System.in); int[] nums = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray(); int k = Integer.parseInt(sc.nextLine()); int target = Integer.parseInt(sc.nextLine()); System.out.println(getResult(nums, k, target)); } public static int getResult(int[] nums, int k, int target) { if (k > nums.length) return 0; Arrays.sort(nums); return kSum(nums, k, target, 0, 0, 0); } // k数之和 public static int kSum(int[] nums, int k, int target, int start, int count, long sum) { if (k < 2) return count; if (k == 2) { return twoSum(nums, target, start, count, sum); } for (int i = start; i <= nums.length - k; i++) { // 剪枝 if (nums[i] > 0 && sum + nums[i] > target) break; // 去重 if (i > start && nums[i] == nums[i - 1]) continue; count = kSum(nums, k - 1, target, i + 1, count, sum + nums[i]); } return count; } // 两数之和 public static int twoSum(int[] nums, int target, int start, int count, long preSum) { int l = start; int r = nums.length - 1; while (l < r) { long sum = preSum + nums[l] + nums[r]; if (target < sum) { r--; } else if (target > sum) { l++; } else { count++; // 去重 while (l + 1 < r && nums[l] == nums[l + 1]) l++; // 去重 while (r - 1 > l && nums[r] == nums[r - 1]) r--; l++; r--; } } return count; } }
Python算法源码
# 输入获取 nums = list(map(int, input().split())) k = int(input()) target = int(input()) # 两数之和 def twoSum(nums, target, start, count, preTotal): l = start r = len(nums) - 1 while l < r: total = preTotal + nums[l] + nums[r] if target < total: r -= 1 elif target > total: l += 1 else: count += 1 # 去重 while l + 1 < r and nums[l] == nums[l + 1]: l += 1 # 去重 while r - 1 > l and nums[r] == nums[r - 1]: r -= 1 l += 1 r -= 1 return count # k数之和 def kSum(nums, k, target, start, count, total): if k < 2: return count if k == 2: return twoSum(nums, target, start, count, total) for i in range(start, len(nums) - k + 1): # 剪枝 if nums[i] > 0 and total + nums[i] > target: break # 去重 if i > start and nums[i] == nums[i - 1]: continue count = kSum(nums, k - 1, target, i + 1, count, total + nums[i]) return count # 算法入口 def getResult(): if k > len(nums): return 0 nums.sort() return kSum(nums, k, target, 0, 0, 0) # 算法调用 print(getResult())
C算法源码
#include <stdio.h> #include <stdlib.h> #define MAX_SIZE 200 int cmp(const void *a, const void *b) { return (*(int *) a) - (*(int *) b); } int getResult(int nums[], int nums_size, int k, int target); int kSum(const int nums[], int nums_size, int k, int target, int start, int count, long sum); int twoSum(const int nums[], int nums_size, int target, int start, int count, long preSum); int main() { int nums[MAX_SIZE]; int nums_size = 0; while (scanf("%d", &nums[nums_size++])) { if (getchar() != ' ') break; } int k; scanf("%d", &k); int target; scanf("%d", &target); printf("%d\n", getResult(nums, nums_size, k, target)); return 0; } int getResult(int nums[], int nums_size, int k, int target) { if (k > nums_size) return 0; qsort(nums, nums_size, sizeof(int), cmp); return kSum(nums, nums_size, k, target, 0, 0, 0); } // k数之和 int kSum(const int nums[], int nums_size, int k, int target, int start, int count, long sum) { if (k < 2) return count; if (k == 2) { return twoSum(nums, nums_size, target, start, count, sum); } for (int i = start; i <= nums_size - k; i++) { // 剪枝 if (nums[i] > 0 && sum + nums[i] > target) break; // 去重 if (i > start && nums[i] == nums[i - 1]) continue; count = kSum(nums, nums_size, k - 1, target, i + 1, count, sum + nums[i]); } return count; } // 两数之和 int twoSum(const int nums[], int nums_size, int target, int start, int count, long preSum) { int l = start; int r = nums_size - 1; while (l < r) { long sum = preSum + nums[l] + nums[r]; if (target < sum) { r--; } else if (target > sum) { l++; } else { count++; // 去重 while (l + 1 < r && nums[l] == nums[l + 1]) l++; // 去重 while (r - 1 > l && nums[r] == nums[r - 1]) r--; l++; r--; } } return count; }

题目解析(回溯算法+组合求解)

JS算法源码
const rl = require("readline").createInterface({ input: process.stdin }); var iter = rl[Symbol.asyncIterator](); const readline = async () => (await iter.next()).value; void (async function () { const nums = (await readline()).split(" ").map(Number); const k = parseInt(await readline()); const target = parseInt(await readline()); let ans = 0; /** * 回溯算法 组合求解 * @param {*} index 当前树层选取元素的起始位置,每次递归就是一层 * @param {*} total 组合内元素之和 * @param {*} count 组合内元素个数 */ function dfs(index, total, count) { // 组合内元素个数达到k个时 if (count == k) { // 检查组合内元素之和是否为target if (total == target) { // 若是,则符合要求的元组个数+1 ans++; } return; } for (let i = index; i < nums.length; i++) { // 树层去重 if (i > index && nums[i] == nums[i - 1]) continue; // 回溯逻辑已隐含 dfs(i + 1, total + nums[i], count + 1); } } nums.sort((a, b) => a - b); dfs(0, 0, 0); console.log(ans); })();
Java算法源码
import java.util.Arrays; import java.util.Scanner; public class Main { static int[] nums; static int k; static int target; static int ans = 0; public static void main(String[] args) { Scanner sc = new Scanner(System.in); nums = Arrays.stream(sc.nextLine().split(" ")).mapToInt(Integer::parseInt).toArray(); k = Integer.parseInt(sc.nextLine()); target = Integer.parseInt(sc.nextLine()); System.out.println(getResult()); } public static int getResult() { Arrays.sort(nums); dfs(0, 0, 0); return ans; } /** * 回溯算法 组合求解 * * @param index 当前树层选取元素的起始位置,每次递归就是一层 * @param total 组合内元素之和 * @param count 组合内元素个数 */ public static void dfs(int index, long total, int count) { // 组合内元素个数达到k个时 if (count == k) { // 检查组合内元素之和是否为target if (total == target) { // 若是,则符合要求的元组个数+1 ans += 1; } return; } for (int i = index; i < nums.length; i++) { // 树层去重 if (i > index && nums[i] == nums[i - 1]) continue; // 回溯逻辑已隐含 dfs(i + 1, total + nums[i], count + 1); } } }
Python算法源码
nums = list(map(int, input().split())) k = int(input()) target = int(input()) ans = 0 def dfs(index, total, count): """ 回溯算法 组合求解 :param index: 当前树层选取元素的起始位置,每次递归就是一层 :param total: 组合内元素之和 :param count: 组合内元素个数 """ global ans # 组合内元素个数达到k个时 if count == k: # 检查组合内元素之和是否为target if total == target: # 若是,则符合要求的元组个数+1 ans += 1 return for i in range(index, len(nums)): # 树层去重 if i > index and nums[i] == nums[i - 1]: continue # 回溯逻辑已隐含 dfs(i + 1, total + nums[i], count + 1) def result(): nums.sort() dfs(0, 0, 0) return ans print(result())
C算法源码
#include <stdio.h> #include <stdlib.h> #define MAX_SIZE 200 int cmp(const void *a, const void *b) { return (*(int *) a) - (*(int *) b); } int getResult(int nums[], int nums_size, int k, int target); void dfs(const int nums[], int nums_size, int k, int target, int index, long total, int count, int* ans); int main() { int nums[MAX_SIZE]; int nums_size = 0; while (scanf("%d", &nums[nums_size++])) { if (getchar() != ' ') break; } int k; scanf("%d", &k); int target; scanf("%d", &target); printf("%d\n", getResult(nums, nums_size, k, target)); return 0; } int getResult(int nums[], int nums_size, int k, int target) { int ans = 0; qsort(nums, nums_size, sizeof(int), cmp); dfs(nums, nums_size, k, target, 0, 0, 0, &ans); return ans; } void dfs(const int nums[], int nums_size, int k, int target, int index, long total, int count, int* ans) { // 组合内元素个数达到k个时 if (count == k) { // 检查组合内元素之和是否为target if (total == target) { // 若是,则符合要求的元组个数+1 (*ans)++; } return; } for (int i = index; i < nums_size; i++) { // 树层去重 if (i > index && nums[i] == nums[i - 1]) { continue; } // 回溯 dfs(nums, nums_size, k, target, i + 1, total + nums[i], count + 1, ans); } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/2 23:23:27

(新卷,100分)- 喊7的次数重排(Java JS Python)

(新卷,100分)- 喊7的次数重排&#xff08;Java & JS & Python&#xff09;题目描述喊7是一个传统的聚会游戏&#xff0c;N个人围成一圈&#xff0c;按顺时针从1到N编号。编号为1的人从1开始喊数&#xff0c;下一个人喊的数字为上一个人的数字加1&#xff0c;但是当将要…

作者头像 李华
网站建设 2026/9/2 23:25:48

(新卷,100分)- 恢复数字序列(Java JS Python)

(新卷,100分)- 恢复数字序列&#xff08;Java & JS & Python&#xff09;题目描述对于一个连续正整数组成的序列&#xff0c;可以将其拼接成一个字符串&#xff0c;再将字符串里的部分字符打乱顺序。如序列8 9 10 11 12&#xff0c;拼接成的字符串为89101112&#xff0…

作者头像 李华
网站建设 2026/9/1 10:10:49

基于改进下垂控制的微电网控制研究Simulink实现

✅作者简介&#xff1a;热爱科研的Matlab仿真开发者&#xff0c;擅长数据处理、建模仿真、程序设计、完整代码获取、论文复现及科研仿真。 &#x1f34e; 往期回顾关注个人主页&#xff1a;Matlab科研工作室 &#x1f447; 关注我领取海量matlab电子书和数学建模资料 &#x1…

作者头像 李华
网站建设 2026/8/30 10:39:06

绿色AI:降低环境影响的计算策略

绿色AI:降低环境影响的计算策略 关键词:绿色AI、环境影响、计算策略、节能算法、可持续发展 摘要:本文聚焦于绿色AI领域,旨在探讨降低人工智能计算对环境影响的有效策略。随着AI技术的迅猛发展,其高能耗问题日益凸显,对环境造成了一定压力。文章首先介绍了绿色AI的背景,包…

作者头像 李华
网站建设 2026/8/28 21:37:33

论文查重神器:8款AI工具助你一臂之力

在学术写作过程中&#xff0c;查重率往往成为研究者必须面对的关键指标&#xff0c;既反映了学术规范性要求&#xff0c;又可能带来修改压力。为有效应对这一挑战&#xff0c;当前已有多种智能辅助工具可供选择&#xff0c;能够帮助用户在保持学术严谨性的前提下优化文本原创性…

作者头像 李华