Java 给定一个排序整数数组,如何找到是否存在一组3个元素和为K?
假设我有一个排序数组:Java 给定一个排序整数数组,如何找到是否存在一组3个元素和为K?,java,arrays,algorithm,Java,Arrays,Algorithm,假设我有一个排序数组: { 1, 2, 3, 4, 5, 6 } 我想看看是否有三个元素加起来等于14 3 + 5 + 6 = 14 我很确定在O(N)时间内没有办法做到这一点,但我认为它可以在O(N^2)时间内完成。这类似于子集和问题,它是NP完全。 但将子集长度限制为3,可以找到快速解决方案。 您的问题相当于 r=K就像你的问题一样 伪代码:O(N^2) for (i in 1..n-2) { j = i+1 // Start right after i. k = n
{ 1, 2, 3, 4, 5, 6 }
我想看看是否有三个元素加起来等于14
3 + 5 + 6 = 14
我很确定在O(N)时间内没有办法做到这一点,但我认为它可以在O(N^2)时间内完成。这类似于子集和问题,它是NP完全。
但将子集长度限制为3,可以找到快速解决方案。
您的问题相当于
r
=K
就像你的问题一样
伪代码:O(N^2)
for (i in 1..n-2)
{
j = i+1 // Start right after i.
k = n // Start at the end of the array.
while (k >= j) {
// done.
if (A[i] + A[j] + A[k] == r) return (A[i], A[j], A[k])
// We didn't match. Let's try to get a little closer:
// If the sum was too big, decrement k.
// If the sum was too small, increment j.
(A[i] + A[j] + A[k] > r) ? k-- : j++
}
// When the while-loop finishes, j and k have passed each other and there's
// no more useful combinations that we can try with this i.
}
此问题类似于,可以在
O(N^2)
中完成java工作代码实现了这一点
// The function prints the values if there exists 3 distinct indices
// in the array arr that sum to req.
void run(){
int[] arr = { 1, 2, 3, 4, 5, 6 };
int req = 14;
// For the algorithm to work correctly, the array must be sorted
Arrays.sort(arr);
for(int i=0; i<arr.length; i++){// Iterate over the elements of the array.
// Check in linear time whether there exists distinct indices
// lo and hi that sum to req-arr[i]
int lo=0, hi = arr.length-1;
boolean found = false;
while(lo<hi){
if(lo==i){
lo++;
continue;
}
if(hi==i){
hi--;
continue;
}
int val = arr[lo] + arr[hi] + arr[i];
if(val == req){
System.out.println(arr[lo] + " + " + arr[hi] + " + " + arr[i] + " = " + req);
found = true;
break;
}else if(val < req){
lo++;
}else{
hi--;
}
}
if(found)break;
}
}
//如果存在3个不同的索引,该函数将打印值
//在数组arr中,求和为req。
无效运行(){
int[]arr={1,2,3,4,5,6};
int req=14;
//为了使算法正确工作,必须对数组进行排序
数组。排序(arr);
对于(int i=0;i,在计算理论中,这被称为问题。迄今为止发现的这个问题的最佳解决方案成本为O(N^2)。能否以更好的成本解决这个问题仍然是一个悬而未决的问题。您可以找到这个算法的一个实现。如果k
与数组大小大致相同(或更小)所有的数字都是正数(处理零很简单),可以有效地使用DP。对于从0到k
的所有数字,您可以记住是否可以使用数组中的零、一、二或三个整数来获得DP。解决方案在时间上是O(Nk)
,在空间上是O(k)
,非常容易实现
int[] myarray = {1, 2, 3, 4, 5, 6};
int k = 14;
int[] dp = new int[k+1];
dp[0] = 1;
for (int i = 0; i < myarray.length; ++i) {
for (int j = k; j >= myarray[i]; --j) {
dp[j] |= dp[j-myarray[i]] << 1;
}
}
if ((dp[k] & 8) > 0) {
System.out.println("YES");
} else {
System.out.println("NO");
}
int[]myarray={1,2,3,4,5,6};
int k=14;
int[]dp=新的int[k+1];
dp[0]=1;
对于(int i=0;i=myarray[i];--j){
dp[j]|=dp[j-myarray[i]]0){
System.out.println(“是”);
}否则{
系统输出打印项次(“否”);
}
@Maroun不,这没有多大帮助here@downvoter我的算法是绝对正确的!为什么你投了否决票?至少要评论一下。我没有投否决票,但条件A[I]+A[j]+A[k]==0
似乎不正确:)这似乎是从这里得到的。评论完全一样。@downvoter请解释为什么投否决票?(没有向下投票)看起来像一个for循环包含一个二进制搜索,你能解释一下为什么时间复杂度是O(N^2)吗?内循环是O(N)。我们只查看数组的每个元素一次。外数组是O(N)。所以算法是O(N^2)。是的,明白了,谢谢:)为什么这个回答被挂起?O。O他的活动日志在我看来还行。