【leetcode】两数之和

时间:2024-01-18 14:01:44

https://leetcode.com/problems/two-sum/

Example:

Given nums = [2, 7, 11, 15], target = 9,

Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

Java:

版本1,暴力搜索(减少了部分搜索),预计打败全世界30%的答案。

public int[] twoSum(int[] nums, int target) {
int size = nums.length;
int size2 = size - 1;
for (int i=0; i<size2; i++) {
for (int j=i+1; j<size; j++) {
if ((nums[i] + nums[j]) == target) {
int[] pair = new int[2];
pair[0] = i;
pair[1] = j;
return pair;
}
}
}
int[] pair = new int[2];
return pair;
}

版本2,,通过HashMap解决循环匹配问题,预计打败全世界50%

HashMap<Integer, Integer> mm = new HashMap<Integer, Integer>();
int size = nums.length;
for (int i=0; i<size; i++) {
mm.put(nums[i], i);
}
Integer tmp = 0;
Integer v= 0;
for (int i=0; i<size; i++) {
tmp= target - nums[i];
v = mm.get(tmp);
if (v != null && v.intValue()!=i) {
int[] pair = new int[2];
pair[0] = i;
pair[1] = v;
return pair;
}
}
int[] pair = new int[2];
return pair;

版本3, 写到版本2的时候,肯定会想到把循环合并到一起执行,预计打败全世界58%。

HashMap<Integer, Integer> mm = new HashMap<Integer, Integer>();
int size = nums.length;
Integer tmp = 0;
Integer v= 0;
mm.put(nums[0], 0); for (int i=1; i<size; i++) {
tmp= target - nums[i];
v = mm.get(tmp);
if (v != null) {
int[] pair = new int[2];
pair[0] = i;
pair[1] = v;
return pair;
}
mm.put(nums[i], i);
} int[] pair = new int[2];
return pair;

版本4. 上面的代码已经不知道怎么优化,那么就减少int和Integer的转换吧,自己定制了一个IntHashMap,开始打败了68%,后面优化了hash的处理,提升到79%。

static final int MISSIDX = -1;
public int[] twoSum(int[] nums, int target) {
IntHashMap mm = new IntHashMap();
int size = nums.length;
int tmp = 0;
int v = 0;
mm.put(nums[0], 0);
for (int i = 1; i < size; i++) {
tmp = target - nums[i];
v = mm.get(tmp);
if (v != MISSIDX) {
int[] pair = new int[2];
if (tmp == nums[i]) {
pair[0] = v;
pair[1] = i;
} else {
pair[0] = i;
pair[1] = v;
}
return pair;
}
mm.put(nums[i], i);
} int[] pair = new int[2];
return pair;
} static class IntHashMap {
public static final int DEFAULT_INITIAL_CAPACITY = 16;
public static final int MAXIMUM_CAPACITY = 1073741824;
public static final float DEFAULT_LOAD_FACTOR = 0.75F;
private transient IntEntry[] table;
private transient int size;
private int threshold;
private final float loadFactor; public IntHashMap(int initialCapacity) {
this.loadFactor = 0.75F;
int capacity = 1;
while (capacity < initialCapacity) {
capacity <<= 1;
}
this.threshold = ((int)(capacity * loadFactor));
this.table = new IntEntry[capacity];
} public IntHashMap() {
this.loadFactor = 0.75F;
this.threshold = 12;
this.table = new IntEntry[16];
} protected int indexFor(int key, int length) {
return key & length - 1;
} public int get(int key) {
int i = indexFor(key, this.table.length);
IntEntry e = this.table[i];
while (true) {
if (e == null)
return MISSIDX;
if (e.key == key)
return e.value;
e = e.next;
}
} public void put(int key, int value) {
int i = indexFor(key, this.table.length);
addEntry(key, value, i);
} private void addEntry(int key, int value, int bucketIndex) {
IntEntry e = this.table[bucketIndex];
this.table[bucketIndex] = new IntEntry(key, value, e);
if (this.size++ >= this.threshold)
resize(2 * this.table.length);
} protected void resize(int newCapacity) {
IntEntry[] oldTable = this.table;
int oldCapacity = oldTable.length;
if (oldCapacity == 1073741824) {
this.threshold = 2147483647;
return;
} IntEntry[] newTable = new IntEntry[newCapacity];
transfer(newTable);
this.table = newTable;
this.threshold = ((int) (newCapacity * this.loadFactor));
} private void transfer(IntEntry[] newTable) {
IntEntry[] src = this.table;
int newCapacity = newTable.length;
for (int j = 0; j < src.length; j++) {
IntEntry e = src[j];
if (e != null) {
src[j] = null;
do {
IntEntry next = e.next;
int i = indexFor(e.key, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
} while (e != null);
}
}
} public String toString() {
return Arrays.deepToString(this.table);
}
} static class IntEntry {
protected final int key;
protected int value;
protected IntEntry next; protected IntEntry(int k, int v, IntEntry n) {
this.value = v;
this.next = n;
this.key = k;
} public int getKey() {
return this.key;
} public int getValue() {
return this.value;
} public void setValue(int newValue) {
this.value = newValue;
} public boolean equals(Object o) {
if (!(o instanceof IntEntry))
return false;
IntEntry e = (IntEntry) o;
int eKey = e.getKey();
int eVal = e.getValue();
if (eKey == getKey()) {
return eVal == MISSIDX ? false : getValue() == MISSIDX ? true
: eVal == getValue();
}
return false;
} public int hashCode() {
return this.key ^ (this.value == MISSIDX ? 0 : value);
} public String toString() {
return "[" + key + "," + value + "]";
}
}

版本5. hashMap这个方向看来是尽头了,那用稀疏数组吧,貌似打败了87.62%

static final int MISSIDX = -1;
public int[] twoSum_0_4(int[] nums, int target) {
SparseIntArray mm = new SparseIntArray();
int size = nums.length;
int tmp = 0;
int v = 0;
mm.put(nums[0], 0);
for (int i = 1; i < size; i++) {
tmp = target - nums[i];
v = mm.get(tmp);
if (v != MISSIDX) {
int[] pair = new int[2];
if (tmp == nums[i]) {
pair[0] = v;
pair[1] = i;
} else {
pair[0] = i;
pair[1] = v;
}
return pair;
}
mm.put(nums[i], i);
} int[] pair = new int[2];
return pair;
} static final int[] EMPTY_INTS = new int[0];
static int idealByteArraySize(int need) {
for (int i = 4; i < 32; i++)
if (need <= (1 << i) - 12)
return (1 << i) - 12; return need;
}
static int idealIntArraySize(int need) {
return idealByteArraySize(need * 4) / 4;
}
static int binarySearch(int[] array, int size, int value) {
int lo = 0;
int hi = size - 1; while (lo <= hi) {
final int mid = (lo + hi) >>> 1;
final int midVal = array[mid]; if (midVal < value) {
lo = mid + 1;
} else if (midVal > value) {
hi = mid - 1;
} else {
return mid; // value found
}
}
return ~lo; // value not present
}
static class SparseIntArray {
private int[] mKeys;
private int[] mValues;
private int mSize;
public SparseIntArray() {
this(10);
}
public SparseIntArray(int initialCapacity) {
initialCapacity = idealIntArraySize(initialCapacity);
mKeys = new int[initialCapacity];
mValues = new int[initialCapacity];
mSize = 0;
}
public int get(int key) {
return get(key, MISSIDX);
}
public int get(int key, int valueIfKeyNotFound) {
int i = binarySearch(mKeys, mSize, key); if (i < 0) {
return valueIfKeyNotFound;
} else {
return mValues[i];
}
}
public void put(int key, int value) {
int i = binarySearch(mKeys, mSize, key); if (i >= 0) {
mValues[i] = value;
} else {
i = ~i; if (mSize >= mKeys.length) {
int n = idealIntArraySize(mSize + 1); int[] nkeys = new int[n];
int[] nvalues = new int[n]; System.arraycopy(mKeys, 0, nkeys, 0, mKeys.length);
System.arraycopy(mValues, 0, nvalues, 0, mValues.length); mKeys = nkeys;
mValues = nvalues;
} if (mSize - i != 0) {
System.arraycopy(mKeys, i, mKeys, i + 1, mSize - i);
System.arraycopy(mValues, i, mValues, i + 1, mSize - i);
} mKeys[i] = key;
mValues[i] = value;
mSize++;
}
} public String toString() {
if (mSize <= 0) {
return "{}";
} StringBuilder buffer = new StringBuilder(mSize * 28);
buffer.append('{');
for (int i=0; i<mSize; i++) {
if (i > 0) {
buffer.append(", ");
}
int key = mKeys[i];
buffer.append(key);
buffer.append('=');
int value = mValues[i];
buffer.append(value);
}
buffer.append('}');
return buffer.toString();
}
}

【leetcode】两数之和