这两天做力扣题发现很多题会围绕链表出,但是对与我这种萌新一下子上难度高的链表既看不懂代码也没有思路,于是从一些简单的题型和链表的运用开始,快慢指针就是其中一个,说是指针可能很抽象,做了一些题以数组为例,更像是对数组下标的移动并且查询下标对应的数据来进行条件判断,下面有几道例题代码方便理解快慢指针的作用,力扣的labuladong插件里讲解的也很详细,配有GIF动态图来方便理解。
一般的场景应用,在删除数组或链表中的相同元素,如果一个一个遍历时间复杂度为O(n),使用快慢指针两个指针同时移动时间复杂度降为了O(1)提高了程序运行速度。主要思路就是fast指针负责探路,slow指针在后面,如果fast指针对应的数据条件判断合格,则赋值给slow指针指向的存储空间,一遍下来就可以删除重复元素或者想删除的元素。而且在链表中,中间跳过的数据,java的垃圾回收站还会自动将其处理,不在需要手动删除,对java很友好。
public class 快慢指针 {
/*
力扣第26题——删除有序数组中的重复项
此题助于理解双指针技巧——快慢指针
*/
public static void main(String[] args) {
System.out.println(removeDuplicates(new int[]{0, 0, 1, 1, 2, 2, 3, 4}));
System.out.println(removeElement(new int[]{0,1,1,2,3,3},3));
}
static int removeDuplicates(int[] nums) {
if (nums.length == 0) {
return 0;
}
//定义快慢指针
int slow = 0, fast = 0;
while (fast < nums.length) {
// 如果fast指向的数和slow不同,slow+1,并且赋值,
if (nums[fast] != nums[slow]) {
slow++;
nums[slow] = nums[fast];
}
fast++;
}
return slow + 1;
}
ListNode deleteDuplicates(ListNode head) {
if (head == null) return null;
ListNode slow = head, fast = head;
while (fast != null) {
if (fast.val != slow.val) {
slow.next = fast;
slow = slow.next;
}
fast = fast.next;
}
slow.next = null;
return head;
}
/*
力扣83题——删除排序列表中的重复元素
与数组去重一样,只不过由数组赋值变为操作指针
*/
public class ListNode {
int val;
ListNode next;
ListNode() {
}
ListNode(int val) {
this.val = val;
}
ListNode(int val, ListNode next) {
this.val = val;
this.next = next;
}
}
/*
利用快慢指针原地删除数组中的某些元素
力扣第27题——移除元素
*/
public static int removeElement(int[] nums, int val) {
int slow = 0, fast = 0;
while (fast < nums.length){
//快指针负责探路,如果有和val一样的值,则跳过,不给nums[slow]赋值,不等于则把值给nums[slow]
if (nums[fast] != val ){
nums[slow] = nums[fast];
slow ++;
}
fast++;
}
return slow;
}
}