先快速排序,再左右双指针遍历。
1.快速排序推荐李春葆的快速排序算法,简洁明了。
2.1左右双指针遍历需要记录排序前数组中各个元素的初始位置,可用使用hashmap记录,如果使用二维数组记录,无法快速搜索到某个元素的原始位置,需要遍历二维数组。
2.2由于数组中存在相同元素,所以使用Map<Integer,Integer>会覆盖前一个相同元素的原始位置,所以使用链表追加相同元素原始位置,当需要取出某一元素的原始位置时从链表中移除,这样就不会重复使用同一位置的元素。
这一题虽然是简单题,之前也按照其他的题解写过一遍,但真正自己思考后按照自己的思路写出来是第一次,期间用时一个多小时,主要是在快速排序算法上。网上搜索了一些快速排序算法在交换i,j位置元素上都不是很清晰明了,想起来本科学数据结构快速排序算法也不是很难,翻了李春葆版的数据结构,果然简洁明了。
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer, LinkedList<Integer>> map = new HashMap<>();
for (int i = 0; i < nums.length; i++) {
if (map.containsKey(nums[i])) {
map.get(nums[i]).addLast(i);
map.put(nums[i], map.get(nums[i]));
} else {
LinkedList<Integer> list = new LinkedList<>();
list.addLast(i);
map.put(nums[i], list);
}
}
int left = 0, right = nums.length - 1;
sort(nums, left, right);
// for (int i : nums) {
// System.out.println(i);
// }
int res = 0;
while (left < right) {
res = nums[left] + nums[right];
if (res > target) {
right--;
} else if (res < target) {
left++;
} else {
return new int[]{map.get(nums[left]).removeLast(), map.get(nums[right]).removeLast()};
}
}
return new int[]{-1, -1};
}
private void sort(int[] nums,int left,int right) {
if (left > right) {
return;
}
int p = privot(nums, left, right);
sort(nums, left, p-1);
sort(nums, p+1, right);
}
private int privot(int[] nums,int left,int right) {
int temp = nums[left];
int i = left, j = right;
while (i < j) {
while (i < j && nums[j] >= temp) {
j--;
}
nums[i]=nums[j];
while (i < j && nums[i] <= temp) {
i++;
}
nums[j]=nums[i];
}
nums[i]=temp;
return i;
}
}