将数组中的数字(a,b)配对为a * 2> = b

时间:2019-01-24 11:26:18

标签: java algorithm data-structures java-8

我正在尝试以a*2 >=b这样的方式解决数组中的配对数字(a,b)。其中a和b是输入数组中的数字。

示例:

输入:a[] = {1,2,3,4,5}

输出:2

说明:

  • 我们可以将1与3配对
  • 2与4或5

输入:a[] = {4,3,2,1,5}

输出:2

说明:

  • 我们可以将1与3配对
  • 2与4或5

输入:a[] = {4,3,2,1,5,6}

输出:3

说明:

  • 我们可以将5与1配对
  • 2与4
  • 3与6

我尝试使用如下所示的递归解决问题,但这没有给出正确的结果。任何帮助将不胜感激。

  • 排序输入数组
  • 如果发现a [开始] * 2> = [结束],则add 1导致start +1end - 1的结果再次出现
  • 其他重复(start + 1, end)(start, end - 1)(start + 1, end - 1)

想法将a[start]与数组中的剩余个元素匹配,并获得最大结果。

    public static int countPairs(int[] a){
       Arrays.sort(a);
       return countPairs(a,a.length,0,a.length-1);
    }

    public static int countPairs(int[] a, int n, int start, int end){


        if(end == start){
            return 0;
        }
        if(start >= n || end < 0){
            return 0;
        }

         System.out.print("matching start: "+start + " and end "+end+"   ");System.out.println("matching "+a[start] + " and "+a[end]);

        if(a[start] < a[end] && a[start] * 2 >= a[end]  ){

            int res = countPairs(a,n,start+1,end-1) +1;
             //System.out.print("inside if matching start: "+start + " and end "+end+"   ");System.out.println("matching "+a[start] + " and "+a[end] + " count is "+res);
            return res;
        }
        else{

            return max(countPairs(a,n,start+1,end) ,
                    countPairs(a,n,start,end - 1),countPairs(a,n,start+1,end - 1));
        }

    }

测试:

import org.junit.Test;

import java.util.Arrays;
import java.util.Random;


public class CountingPairsTest {

    static int countPairs(int[] a){
        return PairingNumbers.countPairs(a);
    }

    @Test
     public void test1(){
        int[] a = {1,2,3,4,5};
        System.out.println("****************************************\n" + Arrays.toString(a));
        int count = countPairs(a);
        System.out.println("count "+count);
    }

    @Test public void test2(){
        int[] a = {1,2,3,4,5,6};
        System.out.println("****************************************\n" + Arrays.toString(a));
        int count = countPairs(a);
        System.out.println("count "+count);
    }

    @Test public void test5(){
        int[] a = {1,2,3,7,4,5,6};
        System.out.println("****************************************\n" + Arrays.toString(a));
        int count = countPairs(a);
        System.out.println("count "+count);
    }

    @Test public void test6(){
        int[] a = {9,8,20,15,21};

        System.out.println("****************************************\n" + Arrays.toString(a));
        int count = countPairs(a);
        System.out.println("count "+count);
    }

    @Test public  void test3(){
        int[] a = {5,4,3,2,1};
        System.out.println("****************************************\n" + Arrays.toString(a));
        int count = countPairs(a);
        System.out.println("count "+count);
    }

    @Test public void test4(){
        int[] a = {2,4,5,3,1};

        System.out.println("****************************************\n" + Arrays.toString(a));
        int count = countPairs(a);
        System.out.println("count "+count);
    }

    @Test public void test7(){
        int[] a = new Random().ints(10,1,100).toArray();// IntStream.range(1,100).toArray();


        System.out.println("****************************************\n" + Arrays.toString(a));
        int count = countPairs(a);
        System.out.println("count "+count);
    }
    @Test public void test8(){
        int[] a = new Random().ints(10,1,10).toArray();// IntStream.range(1,100).toArray();


        System.out.println("****************************************\n" + Arrays.toString(a));
        int count = countPairs(a);
        System.out.println("count "+count);
    }
}

2 个答案:

答案 0 :(得分:8)

我建议答案是a.length / 2。数组长度的一半(如果长度为奇数,则四舍五入)。您可以按照自己喜欢的任何方式配对数字。对于非负数 a b 如果 a * 2 < b ,只需交换 a b ,您将拥有 a * 2> = b 。因此,由于需要两个数字才能成对,因此您始终可以精确地形成多达数组长度一半的对。

示例(来自注释):[1、2、2、2]。长度为4,长度的一半为2,因此应该有2对。让我们检查一下:(1,2)是一个不错的对,因为1 * 2> =2。(2,2)是另一个不错的对,因为2 * 2> =2。在这种情况下,我们甚至不需要任何交换(在另一方面,相同的配对也可以通过 交换来工作:2 * 2> = 1和2 * 2> = 2)。

如果数组可能包含负数,则它并不总是有效。因此,您可能想要添加一个验证数组的校验,以检查数组是否有效。

您的解决方案出了什么问题?

您的递归算法错误。假设数组为[2,3,7,9]。显然(2,3)和(7,9)是好对,因此这里有两对。由于(2,9)不是有效的配对,因此您描述算法的方式将丢弃2和9中的至少一个,从而没有机会从其余数字中形成两个配对。

答案 1 :(得分:1)

您可以通过以下方式解决它:

i。排序数组。

ii。对于每个数字 a ,找到包含> = 2 * b的数组的最左侧位置 p 。那么您可以计算出满足多少个数字。

复杂度: O(nlogn)+ nlogn