一、题目要求:删除排序数组中的重复项
解题:
代码:
class Solution {
public int removeDuplicates(int[] nums) {
int n = nums.length; // 获取数组长度
if(n == 0){
return 0;
}
int fast = 1; // 快指针
int slow = 1; // 慢指针记录不重复个数
for(fast = 1; fast < n;){
if(nums[fast] != nums[fast - 1]){
nums[slow] = nums[fast]; // 将后一个覆盖前一个元素值
slow++; // 不重复值+1
}
fast++; // 当重复时跳过此元素
}
return slow; // 返回记录的不重复元素个数
}
}
题目要求: 需要返回的只是不重复元素的总个数k 并且此数组是非严格递增排列的数组。这样就可以每次比较相邻两个元素即可。
思路: 使用双指针,fast
指针用于跳过重复的元素值,slow
指针用于记录不重复的元素总个数。
关键点: 每次都比较相邻的两个元素,只要相等时,fast
指针就要往后走;当前后两个元素不相等时,符合题目要求,记录slow
个数即可。
二、题目要求:根据值删除单向链表值
解题:
代码:
/**
* 方法1:双指针+哨兵
* @param head 待处理链表
* @param val 待删除值
* @return 处理好链表
*/
public ListNode removeElements1(ListNode head, int val){
ListNode s = new ListNode(-1,head);
ListNode p1 = s;
ListNode p2 = s.next;
while (p2 != null){
if(p2.val == val) {
// 删除操作
p1.next = p2.next;
}else {
// 向后平移
p1 = p1.next;
}
p2 = p2.next;
}
return s.next;
}
// 节点类
public class ListNode(int val, ListNode next){
public int val;
public ListNode next;
public ListNode(int val, listNode next){
this.val = val;
this.next = next;
}
}
思路: 定义两个指针p1/p2分别指向哨兵节点和哨兵节点的下一个节点(头结点),哨兵节点指向head
节点,为了能够删除头结点。p2
快于p1
,当p2的值==待删除的值
时,让p1.next指向p2.next,从而断开此时p2节点。这样就能实现删除功能。当一直未找到时p1和p2
要同时后移一位,直到找到或到null为止。
关键点:
- 如何才能找到待删除的节点呢?
- 找到后该如何实现删除操作?(双指针的好处体现出来了)
总结:
对于链表的操作有很多可以依赖于双指针 || 双指针+哨兵节点的结合使用。包括数组也可以使用双指针进行标记。
比如:对有序链表进行插入操作时,同样可以使用双指针,一个用来记录比待初入值小的节点
,一个用来记录比待插入值大的节点
。