Leetcode算法题第一题Two Sum,题目如下
Two Sum Total Accepted: 86454 Total Submissions: 490141 My Submissions Question Solution
Given an array of integers, find two numbers such that they add up to a specific target number.
The function twoSum should return indices of the two numbers such that they add up to the target, where index1 must be less than index2. Please note that your returned answers (both index1 and index2) are not zero-based.
You may assume that each input would have exactly one solution.
Input: numbers={2, 7, 11, 15}, target=9
Output: index1=1, index2=2
这一题的大概意思,是说给你一个数组和一个数,从数组中找出两个数的和等于这一数,然后输出这两个数在数组中的位置,数组的下标从1开始。
看到这一题的第一个想法是,卧槽,这么简单,通过率才17%,我是不是进错网站了。然后啪啪啪的写出解法,写的过程中一看时间复杂度是O(n*n),我就知道肯定不对了。
// public int[] twoSum(int[] numbers, int target) {
// int [] result = new int [2];
// for (int i = 0; i < numbers.length; i++) {
// for (int j = i+1; j < numbers.length; j++) {
// int sum = numbers[i]+numbers[j];
// if (sum == target) {
// result[0] = i+1;
// result[1] = j+1;
// }
// }
// }
// return result;
// }
心中冒出一个声音,能不能再给力一点!我想,这个肯定是要求时间复杂度为O(n*logn)的,那应该是先将数组排序弄成有序数组,然后分别从两端相加,如果小于目标值,左端下标右移,大于目标值,右端下标左移。嘴角不由露出微笑,这把一定行。
但数组的下标发生了改变,输出不是原下标了!这不是问题,来一个hashmap,用数组的值做key,原下标为value不就ok了?我去,什么鬼,还有相同的值,key重复了怎么办?嗯,开放地址发咯,给这个key加个100000,到时候在两数相等的时候处理一下就好了嘛。
于是又啪啪啪的整出个快排,弄出解法,submit,然后继续得到time limted。傻眼了,麻辣,这是为什么!定睛一看,原来给出的超时case是一个超长的,有序的数组,妈蛋,这不正好是快排的最差情况吗!
好吧,我归并。于是,终于ac了!
public static int[] twoSum(int[] numbers, int target) {
int [] result = new int [2];
// hashmap以数组值为key,原下标为value
HashMap<Integer, Integer> map = new HashMap<Integer,Integer>(numbers.length,(float)0.75);
for (int i = 0; i < numbers.length; i++) {
Object k = map.put(numbers[i], i);
// 如果key值相等,则改变key值,存储原来的下标
if (k!=null) {
map.put(100000+numbers[i], (Integer)k);
}
}
// 数组排序
mergesort(numbers);
int sum = -1;
int i = 0;
int j = numbers.length-1;
while (i<j) {
sum = numbers[i]+numbers[j];
if(sum<target)
i++;
if (sum>target)
j--;
if (sum == target) {
if (numbers[i] == numbers[j]) {
result[0] = map.get(numbers[i]+100000)+1;
result[1] = map.get(numbers[j])+1;
}
else {
result[0] = map.get(numbers[i])+1;
result[1] = map.get(numbers[j])+1;
}
if (result[0]>result[1]) {
int t = result[0];
result[0] = result[1];
result[1] = t;
}
break;
}
}
return result;
}
// 归并排序算法
public static void merge(int[] r,int[] order,int t,int m,int k){
int i = t;
int s = t;
int j = m+1;
while (i<=m&&j<=k) {
if (r[i]<r[j]) {
order[s] = r[i];
s++;
i++;
}
else {
order[s] = r[j];
s++;
j++;
}
}
while (i<=m) {
order[s] = r[i];
s++;
i++;
}
while (j<=k) {
order[s] = r[j];
s++;
j++;
}
}
public static void merges(int[] r,int [] order,int s){
int p = 0;
while(p+2*s-1<=r.length-1){
merge(r, order, p, p+s-1,p+2*s-1);
p = p+2*s;
}
if (p+s-1<r.length-1) {
merge(r, order, p, p+s-1, r.length-1);
}
else {
for (int i = p; i < order.length; i++) {
order[i] = r[i];
}
}
}
public static void mergesort(int[] r){
int s = 1;
int [] order = new int [r.length];
while (s<r.length) {
merges(r, order, s);
s = 2*s;
merges(order, r, s);
s = 2*s;
}
}