0%

双指针

Two Pointers选编

接雨水问题

42. Trapping Rain Water

对每根柱子,求它的左侧和右侧的greatest element,探讨是否能在这根柱子上蓄水

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Solution {
public int trap(int[] height) {
int area=0;
int n=height.length;
int[] findLeft=new int[n];
for(int i=1; i<n-1; i++){
findLeft[i]=Math.max(findLeft[i-1],height[i-1]);
}
int[] findRight=new int[n];
for(int i=n-2; i>=1; i--){
findRight[i]=Math.max(findRight[i+1],height[i+1]);
}

for(int i=1; i<n-1; i++){
int left=findLeft[i];
int right=findRight[i];
int h=Math.min(left,right);
if(h<=height[i]){
continue;
}
area+=h-height[i];
}
return area;
}
}

11. Container With Most Water

由大缩小

双指针技巧:移动较低的一边,因为只有这样才可能使矩形面积增大:

  • 矩形面积由较短边和两边间距决定
  • 移动指针,两边间距必定缩小
  • 若移动较长边,则矩形面积必定缩小!无意义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Solution {
public int maxArea(int[] height) {
int max=Integer.MIN_VALUE;
int left=0;
int right= height.length-1;
while(left<right){
int area=(right-left)*Math.min(height[left],height[right]);
max=Math.max(area,max);
if(height[left]<=height[right]){//移动较短边,使面积可能扩大
left++;
}else{
right--;
}
}
return max;
}
}

数组移除元素

双指针,i 遍历数组,j 保留有效值

26. Remove Duplicates from Sorted Array

注意数组已排序,只需比较当前数组元素与最后一个有效项

1
2
3
4
5
6
7
8
9
10
11
class Solution {
public int removeDuplicates(int[] nums) {
int j=0;
for(int i=1; i<nums.length; i++){
if(nums[i]!=nums[j]){
nums[++j]=nums[i];
}
}
return j+1;
}
}

27. Remove Element

1
2
3
4
5
6
7
8
9
10
11
class Solution {
public int removeElement(int[] nums, int val) {
int j=0;
for(int i=0; i<nums.length; i++){
if(nums[i]!=val){
nums[j++]=nums[i];
}
}
return j;
}
}

283. Move Zeroes

注意要求:maintaining the relative order

直接左右双指针不满足

转换思路:

  1. j 初始化为第一个0, 用于和非零元素交换
    • [0, j] is valid, all 0s are at the end
  2. i 从 j+1 开始遍历,每找到一个非零元素,就与 j 交换
    • [0, i] is valid, where j is the first 0; swap i to j, and set i to 0
    • j is where the next non-zero element should stay (the frist zero), so that the result is in original order
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Solution {
public void moveZeroes(int[] nums) {
int j=0;
while(j<nums.length && nums[j]!=0){
j++;
}
//[0 1 0 3 12]
for(int i=j+1; i<nums.length; i++){
if(nums[i]!=0){
nums[j]=nums[i];
nums[i]=0;
j++;
}
}
}
}

75. Sort Colors

双指针,直到 i>right

  • 遇到0,换,i++
  • 遇到2,换,循环,直到nums[i]!=2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
public class LeetCode75 {
public void sortColors(int[] nums) {
int left=0;
int right=nums.length-1;
for (int i = 0; i <= right; i++) { //必须<=,不能换成< //[left,right] is undecided
while(i<=right && nums[i]==2){
swap(nums,i,right--);
}
if(nums[i]==0){
swap(nums,i,left++);
}
}
}

void swap(int[] nums, int i, int j){
if(i==j){
return;
}
int temp=nums[i];
nums[i]=nums[j];
nums[j]=temp;
}
}

字符串

844. Backspace String Compare

solve it in O(n) time and O(1) space ?

考虑 backspacing, 从后向前比较

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Solution {
public boolean backspaceCompare(String s, String t) {
int i=s.length()-1;
int j=t.length()-1;
int b1=0;
int b2=0;
while(i>=0 || j>=0){
while(i>=0 && (s.charAt(i)=='#' || b1!=0)){
if(s.charAt(i)=='#'){
b1++;
i--;
}else if(b1!=0){
b1--;
i--;
}
}
while(j>=0 && (t.charAt(j)=='#' || b2!=0)){
if(t.charAt(j)=='#'){
b2++;
j--;
}else if(b2!=0){
b2--;
j--;
}
}
if(i<0 || j<0 || s.charAt(i)!=t.charAt(j)){
break;
}
i--;
j--;
}
if(i>=0 || j>=0){
return false;
}else{
return true;
}
}
}