文章目录
有序删重复
删除有序数组中的重复项:每个元素只出现一次
题目链接
思路:快慢指针
让慢指针slow走在后面,快指针fast走在前面探路,找到一个不重复的元素
就告诉slow,slow前进一步并接收fast指向的元素。
这样当fast指针遍历完整个数组nums后,nums[0..slow]
就是所有数组中的所有元素且仅出现一次。
关键点:
1、是先slow++
,还是先 nums[slow]=nums[fast];
这个需要判断
2、fast在什么时候停下来做判断
class Solution {
public int removeDuplicates(int[] nums) {
int n=nums.length;
if(n<2){
return n;
}
int slow=0,fast=0;
while (fast<n){
if(nums[slow]!=nums[fast]){
slow++;
nums[slow]=nums[fast];
}
fast++;
}
return slow+1;
}
}
删除有序数组中的重复项 II:每个元素最多出现k次
添加链接描述
题目要求保留两个,其实任意多个都是可以的,所以下面写通用解法,对于本题就是k=2;
//解法自己想到的nice
class Solution {
public int removeDuplicates(int[] nums) {
int k=2;
int n=nums.length;
if(n<3){
return n;
}
int i=0,slow=0,fast=0;
while (fast<n){
while (fast<n && nums[fast]==nums[slow]) fast++;
int len=fast-slow;
len=Math.min(len,k);
while (len>0){
nums[i++]=nums[slow];
len--;
}
slow=fast;
}
return i; //返回i不是slow
}
}
删除有序链表中的重复项:每个元素只出现一次
题目链接
其实和数组是一模一样的,唯一的区别是把数组赋值操作变成操作指针而已
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head==null || head.next==null){
return head;
}
//养成好习惯,无论head会不会改变
ListNode preNode=new ListNode(0);
preNode.next=head;
ListNode slow=head;
ListNode fast=head.next;
while (fast!=null){
if(slow.val!=fast.val){
slow.next=fast;
slow=fast;
}
fast=fast.next;
}
//特殊情况:末尾节点有重复
slow.next=null;
return preNode.next;
}
}
删除有序链表中的重复项:一个也不留
添加链接描述
写法有很多,下面这种相对更符合自己的思维
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if (head == null || head.next == null) {
return head;
}
ListNode pre = new ListNode(0);
pre.next = head;
ListNode p = pre;
ListNode slow = head;
ListNode fast = head.next;
while (fast != null) {
if (slow.val == fast.val) {
while (fast != null && slow.val == fast.val) fast = fast.next;
p.next = fast;
if (fast == null) {
return pre.next;
}
} else {
p = slow;
}
slow = fast;
fast = fast.next;
}
return pre.next;
}
}
删除无序数组中的目标值
class Solution {
public int removeElement(int[] nums, int val) {
int slow=0,fast=0;
while (fast<nums.length){
if(nums[fast]!=val){
nums[slow]=nums[fast]; //先覆盖再slow++
slow++;
}
fast++;
}
return slow;
}
}
移动0
题目链接
思路:题目要求移动0,可以转换思路,不一定非要移动,可以删除0,然后再后面补0即可。于是就变成了上题“移除元素”中val看做0即可。
代码:
class Solution {
public void moveZeroes(int[] nums) {
int slow=0,fast=0;
while (fast<nums.length){
if(nums[fast]!=0){
nums[slow]=nums[fast];
slow++;
}
fast++;
}
// 注意不要用while循环,因为会超时。
for (int i=slow;i<nums.length;i++){
nums[i]=0;
}
}
}