数配对
题目描述:设计一个算法,找出数组中两数之和为指定值的所有整数对。一个数只能属于一个数对。
示例 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;
}
}