Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 找到递增的三元组,使总和小于或等于k_Java_Algorithm_Triplet - Fatal编程技术网

Java 找到递增的三元组,使总和小于或等于k

Java 找到递增的三元组,使总和小于或等于k,java,algorithm,triplet,Java,Algorithm,Triplet,这个问题更容易或更流行的版本是找到具有给定总和的三元组。但是这一个附加了一个条件。查找未排序数组中的所有三元组,以便 d[i]+d[j]+d[k] <= t; & d[i]<d[j]<d[k] where i<j<k d[i]+d[j]+d[k]哈哈,很高兴看到这里引用了我的博客。然而,你链接的帖子解决了d[i]+d[j]+d[k]

这个问题更容易或更流行的版本是找到具有给定总和的三元组。但是这一个附加了一个条件。查找未排序数组中的所有三元组,以便

d[i]+d[j]+d[k] <= t;   & d[i]<d[j]<d[k] where i<j<k

d[i]+d[j]+d[k]哈哈,很高兴看到这里引用了我的博客。然而,你链接的帖子解决了
d[i]+d[j]+d[k]

我认为您应该清楚地询问数组是否已排序,那么您的问题是对

所以对于您的情况(假设数组是排序的),您只需要确保i,j,k总是按递增顺序排列

因此,考虑到N个元素和一个目标T,一个经典的昼夜方法(即j,k相互移动),您可以尝试:

for (int i = 0; i < N, i++) {
    int j = i;
    int k = N-1;
    while (j < k) {
        int currSum = i+j+k;
        if (currSum < T) { // increase sum
            j++;
        }
        else if (currSum > T) { // decrease sum
            k--;
        }
        else {
            System.out.println("Found triple: " + i + ", " + j + ", " + k);
            j++;
        }
    }
}
for(int i=0;iT){//减少sum
k--;
}
否则{
System.out.println(“发现三元组:“+i+”,“+j+”,“+k”);
j++;
}
}
}
//i、 j,k保证为递增顺序


如果数组未排序,则可以执行优化的蛮力操作。求出所有的i,j,使得d[i] 如果修复i和j,则必须在数组中找到一个小于或等于
t-d[i]-d[j]
的数字。存储数组的第二个版本,其中每个元素也存储其索引。按递增顺序排序此数组

现在,对于具有
i
的所有对
i,j
(这只是两个嵌套的循环),您可以对
t-d[i]-d[j]
进行二进制搜索;如果存在这样一个数字,则检查从左到右的所有数字,并检查其索引是否大于j,如果是,则添加到输出中。复杂性是
O(n*n*lgn+k)
其中k是满足条件的输出数


编辑:OP的第一篇帖子是
=
现在他改成了
首先,值得指出的是,最坏情况下的复杂性不可能比
O(n^3)
更好,因为在最坏情况下有
O(n^3)
三元组,显然每个三元组至少需要恒定的时间来存储/打印它。还有一个非常简单和明显的
O(n^3)
算法

这就是说,这里有一个复杂度
O(n^2 log n+k)
的方法,其中
k
是答案的大小。(尽管@saadtaame声称具有相同的复杂性,但他的估计中存在一个问题,请参见其答案下面的评论)

首先,让我们修复一个元素,比如
a[i]
。现在,让我们创建一个新数组
b
,由
a
中的所有元素组成,它们的索引都大于
i
,值也大于
a[i]
。现在问题归结为在
b
中找到两个索引
j
k
,例如
j
b[j]

为此,我们可以使用某种排序集,比如Java中的
TreeSet
。我们将迭代
k
的所有可能值,在
TreeSet
中维护索引小于
k
的所有元素。由于
TreeSet
只包含索引小于
k
(因为我们构建它的方式)且大于
i
(因为
b
只包含这样的元素)的元素,并且被排序,因此
TreeSet
中的每个元素
q
的值都小于
b[k]
形成一个答案三元组
(a[i],q,b[k])
。下面是一个伪代码:

for i from 0 to size(a):
    b = empty array
    for j from i + 1 to size(a):
        if a[j] > a[i]:
            add a[j] to b
    treeSet = new TreeSet
    for k from 0 to size(b):
        for each element 'e' in the treeSet in sorted order: // (1)
            if e >= b[k] or a[i] + e + b[k] > t:
                break
            add (a[i], e, b[k]) to the answer // (2)
        add b[k] to the treeSet // (3)
这里,如果我们返回的元素数小于
O(n^2 logn)
,那么算法的复杂性将是
O(n^2 logn)
。原因是,行
(2)
被精确地执行
k次,因此可以忽略(并且在树集上迭代已经在元素数量上摊销了线性时间),而内部循环的其余部分:在
(1)
处初始化迭代器,并在
(3)处向
树集添加一个元素
最多都是
O(log n)
操作

编辑:这里有一个小例子。假设数组是
a=[5,3,7,9,8,1]
t=20
。然后
i
首先指向
5
,我们将
5
和更大的元素放到
b
,因此
b=[7,9,8]
。然后
k
将进行三次迭代:

  • b[k]=7
    。此时树集是空的,因此不会发生任何事情,
    7
    被添加到树集中

  • b[k]=9
    。此时树集有元素7。它小于9,但和
    5+7+9>20
    ,因此我们中断了树集上的迭代。我们把
    9
    放在树集合中,集合现在包含
    (7,9)


  • b[k]=8
    。我们在树集上迭代。对于元素7,两个条件都满足(
    7<8和5+7+8条件,其中
    i我认为你可以做得比O(n^2 log n+k)稍微好一些

    假设您位于位置i。i(1…i)之前的所有元素都存储在一个BST中,i(1+1…n)之后的所有元素都存储在第二个BST中

    在第一棵树中,找到最小的元素A[j],使A[j]
    现在,在第二棵树中找到最大的元素A[k],这样A[k] 我们要做的是首先使用快速排序对数字进行排序,这样可以避免额外的循环,默认情况下i
    我的逻辑是d[i]+d[j]+d[k]查找递增的三元组,使总和小于或等于k:

    # include <stdio.h>
    void find3Numbers(int A[], int arr_size, int sum)
    {
        int l, r;
        for (int i = 0; i < arr_size-2; i++){
           for (int j = i+1; j < arr_size-1; j++){         
               for (int k = j+1; k < arr_size; k++){
                   if (A[i] + A[j] + A[k] <= sum)
                     printf("Triplet is %d, %d, %d\n", A[i], A[j], A[k]);
                }
            }
         }
    }
    int main()
    {
        int A[] = {1, 2, 3, 4, 6};
        int sum = 8;
        int arr_size = sizeof(A)/sizeof(A[0]);
        find3Numbers(A, arr_size, sum);
        return 0;
    }
    
    #包括
    vo
    
    Initialization: firstTree={A[1]}, secondTree = {A[3]..A[n]}
    
    For i = 2:(n-1) do:
        j = getFirst(firstTree)
        firstIter = true;
        while(true)
            if A[j]>=A[i] or A[j]+A[i]>t break
            if firstIter:
                k = binSearch(secondTree, t - A[i] -A[j])
                firstIter=false
            else
                if bestk<0:
                    break;
                k = bestk
            bestk = -1
            jnext = nextElement(firstTree, A[j]);
            while (A[k]>A[i]):
                print (A[j], A[i], A[k])
                if bestk<0 and A[i]+A[jnext]+A[k] < t:
                    bestk = k;
                k = prevElement(secondTree, A[k])
        Add(firstTree, A[i])
        Remove(secondTree, A[i+1])
    
        Arrays.sort(d);
        for (int i = 0; i < d.length; i++) {
            for (int j = i + 1; j < d.length; j++) {
                int firstNumber = d[i];
                int secondNumber = d[j];
                int temp = t - firstNumber - secondNumber;
                if ((firstNumber < secondNumber) && (secondNumber < temp))  {
                    int index = Arrays.binarySearch(d, temp);
                        if (index >= 0) {
                        ......
                        }
                    }
                }
            }
        }
    
    # include <stdio.h>
    void find3Numbers(int A[], int arr_size, int sum)
    {
        int l, r;
        for (int i = 0; i < arr_size-2; i++){
           for (int j = i+1; j < arr_size-1; j++){         
               for (int k = j+1; k < arr_size; k++){
                   if (A[i] + A[j] + A[k] <= sum)
                     printf("Triplet is %d, %d, %d\n", A[i], A[j], A[k]);
                }
            }
         }
    }
    int main()
    {
        int A[] = {1, 2, 3, 4, 6};
        int sum = 8;
        int arr_size = sizeof(A)/sizeof(A[0]);
        find3Numbers(A, arr_size, sum);
        return 0;
    }
    
    Execution :
    arr_size = 5
    Step:1   i=0 and i<3 (arr_size-2)
                                    j=1 and j<4 (arr_size-1)
                                                    k=2 and k<5 (arr_size)
                                                                    A[0]+A[1]+A[2]<=sum --> 1+2+3 <=8 --> 6<=8 ( true )
                                                    k=3 and k<5
                                                                    A[0]+A[1]+A[3]<=sum --> 1+2+4 <=8 --> 7<=8 ( true )
                                                    k=4 and k<5
                                                                    A[0]+A[1]+A[4]<=sum --> 1+2+6 <=8 --> 9<=8 ( false )
                                    j=2 and j<4
                                                    k=3 and k<5
                                                                    A[0]+A[2]+A[3]<=sum --> 1+3+4 <=8 --> 8<=8 ( true )
                                                    k=4 and k<5
                                                                    A[0]+A[2]+A[4]<=sum --> 1+3+6 <=8 --> 10<=8 ( false )
                                    j=3 and j<4
                                                    k=4 and k<5
                                                                    A[0]+A[3]+A[4]<=sum --> 1+4+6 <=8 --> 11<=8 ( false )
                                    j=4 and j<4 (false)
    Step:2  i=1 and i<3
                                    j=2 and j<4
                                                    k=3 and k<5
                                                                    A[1]+A[2]+A[3]<=sum --> 2+3+4 <=8 --> 9<=8 ( false )
                                                    k=4 and k<5
                                                                    A[1]+A[2]+A[4]<=sum --> 2+3+6 <=8 --> 11<=8 ( false )
                                    j=3 and j<4
                                                    k=4 and k<5
                                                                    A[1]+A[3]+A[4]<=sum --> 2+4+6 <=8 --> 12<=8 ( false )
                                    j=4 and j<4 (false)
    Step:3 i=2 and i<3
                                    j=3 and j<4
                                                    k=4 and k<5
                                                                    A[2]+A[3]+A[4]<=sum --> 3+4+6 <=8 --> 13<=8 ( false )
                                    j=4 and j<4 (false)
    Step:4 i=3 and i<3 (false)
    
    import java.util.*;
    public class Main
    {
        public static void main(String[] args) {
            int arr[]={1,2,3,3,4,4,9,10,11,342,43};
            int n=arr.length,t=98,cnt=0;
            Arrays.sort(arr);
            for(int k=2;k<n;k++)
            {
                TreeMap<Integer,Integer> ts1=new TreeMap<>();
                for(int j=0;j<k;j++)
                {
                    if(arr[j]==arr[k])
                    break;
                    int i=Math.min(t-arr[k]-arr[j],arr[j]); //try to get the number of elements less than arr[j] and target-arr[k]-arr[j]
                    cnt+=(ts1.lowerKey(i)==null?0:ts1.get(ts1.lowerKey(i)));
                    
                    if(ts1.containsKey(arr[j]))
                    ts1.put(arr[j],ts1.get(arr[j])+1);
                    else
                    {
                        Integer val=ts1.lowerKey(arr[j]);
                        ts1.put(arr[j],1+(val==null?0:ts1.get(val)));
                    }
                }
            }
            System.out.println(cnt);
        }
    }
    
    #include <bits/stdc++.h>
    using namespace std;
    
    vector<int> helper(vector<int> &A, int T)
    {
        vector<int> ans;
        int N = A.size();
        for (int i = 0; i < N; i++)
        {
            vector<int> B;
            for (int j = i + 1; j < N; j++)
            {
                if (A[j] > A[i])
                    B.push_back(A[j]);
            }
            set<int> S;
            set<int>::iterator it;
            for (int k = 0; k < B.size(); k++)
            {
                for (auto it = S.begin(); it != S.end(); it++)
                {
                    int sum = A[i] + *it + B[k];
                    if (*it >= B[k] || sum > T)
                        break;
                    cout << A[i] << " - " << *it << " - " << B[k] << endl;
                    ans.push_back(sum);
                }
                S.insert(B[k]);
            }
        }
        return ans;
    }
    
    vector<int> helper1(vector<int> &A, int T)
    {
        vector<int> ans;
        int N = A.size();
        for (int i = 0; i < N - 2; i++)
        {
            for (int j = i + 1; j < N - 1; j++)
            {
                for (int k = j + 1; k < N; k++)
                {
                    int sum = A[i] + A[j] + A[k];
                    if (sum <= T && A[i] < A[j] && A[j] < A[k])
                    {
                        cout << A[i] << " - " << A[j] << " - " << A[k] << endl;
                        ans.push_back(sum);
                    }
                }
            }
        }
        return ans;
    }
    
    void print(vector<int> &A)
    {
        for (int a : A)
            cout << a << " ";
        cout << endl;
    }
    
    int main()
    {
        vector<int> A({1, 4, 12, 3, 6, 10, 14, 3});
        int T = 11;
        vector<int> ans = helper(A, T); // O(n^2log n)
        print(ans);
        vector<int> ans1 = helper1(A, T); // )(n^3)
        print(ans1);
        return 0;
    }