您的位置:首页 > 其它

LeetCode刷题系列(十五)Sums && Sort Colors

2016-07-06 12:05 453 查看
  本篇包含关于2-sum、3-sum等关于给定和,求其中的数的题型,还有包含使用了3sum中前后指针的sort题型。

2 Sum

  给定目标值,求数组中和为目标值的两个数。使用一个hash可以巧妙地将时间复杂度降到O(n),之后的题可以参考此思路。

public int[] twoSum(int[] nums, int target) {
Map<Integer, Integer> hash = new HashMap<Integer, Integer> ();
int[] result = new int[2];
for (int i = 0; i < nums.length; ++i) {
if (hash.containsKey(target - nums[i])) {
result[0] = hash.get(target - nums[i]) + 1;
result[1] = i + 1;
break;
}
hash.put(nums[i], i);
}
return result;
}


3 Sum

  求数组中和为0的三个数。这道题在2Sum的基础上,在寻找第三个数时,使用left和right两个指针,类似于二分查找,可以有效减少算法时间。这种方法可以移植到接下来介绍的几道题上。

public ArrayList<ArrayList<Integer>> threeSum(int[] num) {

ArrayList<ArrayList<Integer>> rst = new ArrayList<ArrayList<Integer>>();
if(num == null || num.length < 3) {
return rst;
}
Arrays.sort(num);
for (int i = 0; i < num.length - 2; i++) {
if (i != 0 && num[i] == num[i - 1]) {
continue; // to skip duplicate numbers; e.g [0,0,0,0]
}

int left = i + 1;
int right = num.length - 1;
while (left < right) {
int sum = num[left] + num[right] + num[i];
if (sum == 0) {
ArrayList<Integer> tmp = new ArrayList<Integer>();
tmp.add(num[i]);
tmp.add(num[left]);
tmp.add(num[right]);
rst.add(tmp);
left++;
right--;
while (left < right && num[left] == num[left - 1]) { // to skip duplicates
left++;
}
while (left < right && num[right] == num[right + 1]) { // to skip duplicates
right--;
}
} else if (sum < 0) {
left++;
} else {
right--;
}
}
}
return rst;
}


4 Sum

  求数组中和为目标值的四个数。基本可以使用3sum的方法,在其基础上多加一个for循环(这个无可避免)。

public ArrayList<ArrayList<Integer>> fourSum(int[] num, int target) {
ArrayList<ArrayList<Integer>> rst = new ArrayList<ArrayList<Integer>>();
Arrays.sort(num);

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 left = j + 1;
int right = num.length - 1;
while (left < right) {
int sum = num[i] + num[j] + num[left] + num[right];
if (sum < target) {
left++;
} else if (sum > target) {
right--;
} else {
ArrayList<Integer> tmp = new ArrayList<Integer>();
tmp.add(num[i]);
tmp.add(num[j]);
tmp.add(num[left]);
tmp.add(num[right]);
rst.add(tmp);
left++;
right--;
while (left < right && num[left] == num[left - 1]) {
left++;
}
while (left < right && num[right] == num[right + 1]) {
right--;
}
}
}
}
}

return rst;
}


3 Sum Closest

  求数组中和最接近目标值的3个数。这道题与3sum类似,使用其思路,将判别标准改变即可。

public int threeSumClosest(int[] numbers, int target) {
if (numbers == null || numbers.length < 3) {
return -1;
}

Arrays.sort(numbers);
int bestSum = numbers[0] + numbers[1] + numbers[2];
for (int i = 0; i < numbers.length; i++) {
int start = i + 1, end = numbers.length - 1;
while (start < end) {
int sum = numbers[i] + numbers[start] + numbers[end];
if (Math.abs(target - sum) < Math.abs(target - bestSum)) {
bestSum = sum;
}
if (sum < target) {
start++;
} else {
end--;
}
}
}

return bestSum;
}


Sort Colors

  将color号为0、1、2的数依次排序为0***1***2***。与3sum类似,使用两个指针,为1时不动,为0或3时进行交换即可。

public void sortColors(int[] a) {
if (a == null || a.length <= 1) {
return;
}

int pl = 0;
int pr = a.length - 1;
int i = 0;
while (i <= pr) {
if (a[i] == 0) {
swap(a, pl, i);
pl++;
i++;
} else if(a[i] == 1) {
i++;
} else {
swap(a, pr, i);
pr--;
}
}
}

private void swap(int[] a, int i, int j) {
int tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}


Sort Colors II

  这道题color号为从1到k。基于上题的思路,我们可以一次排序2个数,最前面(上题的0)和最后面(上题的2)的,其余看成上题的1,然后依次向中心收缩。

public void sortColors2(int[] colors, int k) {
int count = 0;
int start = 0;
int end = colors.length-1;
while (count < k) {
int min = Integer.MAX_VALUE;
int max = Integer.MIN_VALUE;

for (int i = start; i <= end; i++) {
min = Math.min(min, colors[i]);
max = Math.max(max, colors[i]);
}
int left = start;
int right = end;
int cur = left;
while(cur <= right) {
if (colors[cur] == min) {
swap(left, cur, colors);
cur++;
left++;
} else if (colors[cur] > min && colors[cur] < max) {
cur++;
} else {
int tmp = colors[cur];
swap(cur, right, colors);
right--;
}
}
count += 2;
start = left;
end = right;
}
}

void swap(int left, int right, int[] colors) {
int tmp = colors[left];
colors[left] = colors[right];
colors[right] = tmp;
}


Sort Letters by Case

  这道题也是使用前后指针然后交换的思路。

public void sortLetters(char[] chars) {
int i = 0, j = chars.length - 1;
char tmp ;
while ( i <= j) {
while (i <= j && Character.isLowerCase(chars[i]) ) i++;
while (i <= j && Character.isUpperCase(chars[j]) ) j--;
if (i <= j) {
tmp = chars[i];
chars[i] = chars[j];
chars[j] = tmp;
i++; j--;
}
}
//write your code here
return ;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode