今天进入双指针环节,由于题目都做过,所以选三题来复习
27. 移除元素
这里重点研究下边界值和特殊情况的处理
下面是我原来写的代码,没有考虑边界
class Solution {
public int removeElement(int[] nums, int val) {
int i = 0, j = nums.length-1;
while(i < j) {
while(nums[i] != val && i < j) i++;
while(nums[j] == val && i < j) j--;
nums[i++] = nums[j--];
}
return j+1;
}
}
结果提交发现小数组(根本凑不出两个指针)就过不了。
对于下面这个例子,可以模拟到i=0,j=0,根本没进入循环
发现while里面的while太过于冗长,采用在while里面判断。这样在循环里面进行三选一,在每次移动指针之前先检查是否越界。
class Solution {
public int removeElement(int[] nums, int val) {
int i = 0, j = nums.length-1;
while (i <= j) {
if (nums[i] != val) {
i++;
} else if (nums[j] == val) {
j--;
} else {
nums[i++] = nums[j--];
}
}
return j+1;
}
}
206.反转链表
二刷发现记住有三个指针,在保存了后一个元素的前提下转向就可以了
class Solution {
public ListNode reverseList(ListNode head) {
ListNode pre=null;
ListNode curr=head;
while(curr!=null){
ListNode temp=curr.next;
curr.next=pre;
pre=curr;
curr=temp;
}
return pre;
}
}
15. 三数之和
首先需要记住暴力做法已经超过排序的nlogn时,可以先给数组排序了
排序后数组不仅可以根据当前和控制左右指针,还可以用来去重
class Solution {
public List<List<Integer>> threeSum(int[] nums) {
List<List<Integer>> res = new ArrayList<>();
Arrays.sort(nums);
for (int i = 0; i < nums.length; i++) {
int l = i+1, r = nums.length-1;
// 对第一个数去重
if (i > 0 && nums[i] == nums[i-1]) continue;
while(l < r) {
if (nums[i] + nums[l] + nums[r] < 0) l++;
else if (nums[i] + nums[l] + nums[r] > 0) r--;
else {
res.add(Arrays.asList(nums[i], nums[l], nums[r]));
// 对第二三个数去重
while(l<r && nums[l]==nums[l+1]) l++;
while(l<r && nums[r]==nums[r-1]) r--;
l++;
r--;
}
}
}
return res;
}
}