数配对问题

数配对
题目描述:设计一个算法,找出数组中两数之和为指定值的所有整数对。一个数只能属于一个数对。
示例 1:
输入: nums = [5,6,5], target = 11
输出: [[5,6]]
示例 2:
输入: nums = [5,6,5,6], target = 11
输出: [[5,6],[5,6]]

1.方案一:堆排+双指针(但是该方法会超时)

import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
public class Math {
    public List<List<Integer>> pairSums(int[] nums, int target) {
        heap_sort(nums);
        List<List<Integer>>  lists = new ArrayList<List<Integer>>();
            int a=0,b=nums.length-1;//两个指针初始化
            while(a<b)
            {
                if(nums[a]+nums[b]==target)
                {
                    ArrayList<Integer> list = new ArrayList<>();
                    list.add(nums[a]);
                    list.add(nums[b]);
                    lists.add(list);
                    //添加后两个数都不可以用
                    a++;
                    b--;
                }
                else if(nums[a]+nums[b]<target)
                {
                    a++;
                }
                else
                {
                    b--;
                }
            }
            return lists;
    }
	//堆排
    void heap_sort(int nums[])
    {
        for(int i=nums.length-1;i>=1;i--)
            heapify(nums,i);
    }
    //先使用堆排序将数组排排列写好,时间复杂度为nlogn
    //构建大跟根堆
    void heapify(int[] nums,int i)
    {
        int current;
        for(int k=1;k<=i;k++)
        {
            current = k;
            while(nums[(current-1)/2]<nums[current]) {
                swap(nums, (current - 1) / 2, current);
                current  = (current-1)/2;
            }
        }
        swap(nums,0,i);
    }

    void swap(int[] nums,int i,int j)
    {
        int temp = nums[i];
        nums[i]=nums[j];
        nums[j]=temp;
    }
    @Test
    public void Test()
    {
        int nums[]={7, 0, 8, 2, 4, 4, 9, 3, 9, -5};
        heapify(nums,nums.length-1);
        for (int num : nums) {
            System.out.print(num+ " ");
        }
        System.out.println();
        List<List<Integer>> lists = pairSums(nums, 3);
        for (List<Integer> list : lists) {
          //  list;
            for (Integer integer : list) {
                System.out.print(integer+" ");
            }
            System.out.println();
        }

    }
}

2.方案二:快排+双指针

class Solution {
      public List<List<Integer>> pairSums(int[] nums, int target) {
          quicksort(nums,0,nums.length-1);
        List<List<Integer>>  lists = new ArrayList<List<Integer>>();
            int a=0,b=nums.length-1;//两个指针初始化
            while(a<b)
            {
                if(nums[a]+nums[b]==target)
                {
                    ArrayList<Integer> list = new ArrayList<>();
                    list.add(nums[a]);
                    list.add(nums[b]);
                    lists.add(list);
                    a++;
                    b--;
                }
                else if(nums[a]+nums[b]<target)
                {
                    a++;
                }
                else
                {
                    b--;
                }
            }
            return lists;
    }
    //快排
    void quicksort(int[] nums,int i,int j)
    {
        int index;
        if(i<j)
        {
            index = getMiddle(nums,i,j);
            quicksort(nums,i,index-1);
            quicksort(nums,index+1,j);
        }
    }
    //该方法的作用是返回分组后的中间数索引
    int getMiddle(int[] nums,int i,int j)
    {
        int temp = nums[i];
        while(i<j)
        {
            while(nums[j]>=temp&&i<j)
                j--;
            nums[i]=nums[j];
            while(nums[i]<=temp&&i<j)
                i++;
            nums[j]= nums[i];
        }
        nums[i]=temp;
        return i;
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值