终于把leetcode的151题刷完第一遍,第二遍打算在做的过程中,把之前没有记录的题目,分类整合进行解析,首先就是leetcode上的 X Sum问题。
Two Sum 题目:
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
方法二:先进行快速排序,时间复杂度O(NlogN),再定义两个指针p1和p2,分别从头尾向中间移动,如果 numbers[p1]+ numbers[p2] > target,p2向左移动,如果numbers[p1]+numbers[p2] < target,p1向右移动,如果numbers[p1]+numbers[p2] = target,输出p1和p2。
方法三:hash方法,如果是C++,因为map是用红黑树实现,查找时间O(logN),所以时间复杂度O(NlogN),如果是Java,hashMap底层是根据对象的hashCode进行存放的数组结构,查询时间复杂度是O(N)。具体做法是将值和下表存放在map数据结构中,如果当前值number[i]对应的target - nubmer[i]在map中,输出 number[i]和target - nubmer[i],如果当前值number[i]对应的target - nubmer[i]不在map中,将number[i]存入map,遍历一次数组即可,C++ AC代码如下:
vector<int > twoSum(vector< int> &numbers , int target) {
vector<int > result(2,0);
map<int ,int> mapping;
for (int i = 0; i < numbers.size(); i++){
int temp = numbers [i];
if (mapping[target - temp]>0){
result[0] = mapping[target - temp];
result[1] = i + 1;
}
else{
mapping[temp] = i + 1;
}
}
return result;
}
3 Sum 题目:
Given an array S of n integers, are there elements a, b, c in S such that a + b + c = 0? Find all unique triplets in the array which gives the sum of zero.
Note:
- Elements in a triplet (a,b,c) must be in non-descending order. (ie, a ≤ b ≤ c)
- The solution set must not contain duplicate triplets.
For example, given array S = {-1 0 1 2 -1 -4}, A solution set is: (-1, 0, 1) (-1, -1, 2)
public List<List<Integer>> threeSum(int[] num) {
Arrays.sort(num);
List<List<Integer>> result = new ArrayList<List<Integer>>();
for (int i = 0; i < num.length - 2; i++) {
//优化一:判断第一个数字是否和上次的第一个数字相同,重复计算
if (i != 0 && num[i] == num[i - 1]) {
continue;
}
//优化二:如果第一个数字为正数,后面的数字更大,三个数字之和不可能为0,这种情况可以不考虑
if (num[i] > 0)
break;
int tempSum = -num[i];
int p1 = i + 1;
int p2 = num.length - 1;
while (p1 < p2) {
int temp1 = num[p1];
int temp2 = num[p2];
if (temp1 + temp2 == tempSum) {
List<Integer> tempList = new ArrayList<Integer>();
tempList.add(-tempSum);
tempList.add(temp1);
tempList.add(temp2);
Collections.sort(tempList);
if (!result.contains(tempList)) {
result.add(tempList);
}
p1++;
} else if (temp1 + temp2 > tempSum) {
p2--;
//优化三:判断第三个数字是否和上一次的第三个数字重复,防止重复计算
while (num[p2] == num[p2 + 1] && p2 > p1)
p2--;
} else {
p1++;
//优化三:判断第二个数字是否和上一次的第二个数字重复,防止重复计算
while (num[p1] == num[p1 - 1] && p2 > p1)
p1++;
}
}
}
return result;
}
3 Sum Closet题目:
Given an array S of n integers, find three integers in S such that the sum is closest to a given number, target. Return the sum of the three integers. You may assume that each input would have exactly one solution.
For example, given array S = {-1 2 1 -4}, and target = 1. The sum that is closest to the target is 2. (-1 + 2 + 1 = 2).
解析:已知一组数组,找到三个整数的和与目标值target最为接近,并且每个输入只有一个输出。该题的解决方法和3Sum类似,也是先做个快速排序,时间复杂度为O(logN)。循环取出数字num[i]后,针对下标为i~n-1的数字,采取2Sum的方法二做两个指针的移动,总时间复杂度是O(N^2)。不同的是,为了找出最接近target的结果,该题可以定义一个变量mindis,这个变量用于更新当前三个值的和与target的差值,如果当前三个值的和与target的差值等于mindis,当前三个值即所求结果。如果当前三个值的和与target的差值小于mindis,说明当前三个值的和是最优解(最接近target),更新mindis。无论当前三个值的和与target的差值是大于mindis还是小于mindis,都要移动三个指针来更新这三个值的和。Java AC代码如下:
public int threeSumClosest(int[] num, int target) {
int result = num[0] + num[1] + num[2];
int mindis = Math.abs(result - target);
Arrays.sort(num);
for (int i = 0; i < num.length; i++) {
if (i > 0 && num[i] == num[i - 1])
continue;
if (i > 0 && num[i - 1] > target && num[i] > target)
break;
int p1 = i + 1;
int p2 = num.length - 1;
while (p1 < p2) {
int tempSum = num[p1] + num[p2] + num[i];
if (Math.abs(tempSum - target) < mindis) {
result = tempSum;
mindis = Math.abs(tempSum - target);
}
if (tempSum < target) {
p1++;
while (num[p1] == num[p1 - 1] && p1 < p2)
p1++;
} else if (tempSum > target) {
p2--;
while (num[p2] == num[p2 + 1] && p1 < p2)
p2--;
} else {
return result;
}
}
}
return result;
}
4 Sum题目:
Given an array S of n integers, are there elements a, b, c, and d in S such that a + b + c + d = target? Find all unique quadruplets in the array which gives the sum of target.
Note:
- Elements in a quadruplet (a,b,c,d) must be in non-descending order. (ie, a ≤ b ≤ c ≤ d)
- The solution set must not contain duplicate quadruplets.
For example, given array S = {1 0 -1 0 -2 2}, and target = 0. A solution set is: (-1, 0, 0, 1) (-2, -1, 1, 2) (-2, 0, 0, 2)
解析:leetcode中的X Sum系列最后一题4 Sum,我的解法比较暴力,将第一个数和第二个数通过迭代取出,第三个数和第四个数做两个指针,时间复杂度O(N^3)。按照这种做法可以实现5 Sum,6 Sum,但是时间复杂度也很高,如果找到更好的方法再进行更新记录吧。Java AC代码如下:
public List<List<Integer>> fourSum(int[] num, int target) {
Arrays.sort(num);
List<List<Integer>> result = new ArrayList<List<Integer>>();
for (int i = 0; i < num.length - 3; i++) {
if (i > 0 && num[i] == num[i - 1])
continue;
for (int j = i + 1; j < num.length - 2; j++) {
if (j > i + 1 && num[j] == num[j - 1])
continue;
int p1 = j + 1;
int p2 = num.length - 1;
while (p1 < p2) {
int tempSum = num[i] + num[j] + num[p1] + num[p2];
if (tempSum < target) {
p1++;
while (p1 < p2 && num[p1] == num[p1 - 1])
p1++;
} else if (tempSum > target) {
p2--;
while (p1 < p2 && num[p2] == num[p2 + 1])
p2--;
} else {
List<Integer> tempList = new ArrayList<Integer>();
tempList.add(num[i]);
tempList.add(num[j]);
tempList.add(num[p1]);
tempList.add(num[p2]);
result.add(tempList);
p1++;
while (p1 < p2 && num[p1] == num[p1 - 1])
p1++;
}
}
}
}
return result;
}