快慢指针
前言
对于数组来说, 在尾部插⼊、 删除元素是⽐较⾼效的, 时间复杂度是 O(1 ) , 但是如果在中间或者开 头插⼊、 删除元素, 就会涉及数据的搬移, 时间复杂度为 O(N) , 效率较低。
来讲⼀讲如何在原地修改数组, 避免数据的搬移。
一、应用场景
常用于原地修改数组
二、模板
int removeDuplicates(int[] nums) {
if (nums.length == 0) {
return 0;
}
int slow = 0, fast = 0;
while (fast < nums.length) {
if (nums[fast] != nums[slow]) {
slow++;
nums[slow] = nums[fast]; // 维护 nums[0..slow] ⽆重复
}
fast++;
}
return slow + 1; // 数组⻓度为索引 + 1
}
三、实践
26. 删除有序数组中的重复项(简单)
慢指针 slow ⾛在后⾯, 快指针 fast ⾛在前⾯探路, 找到⼀个不重复的元素就告诉 slow 并让 slow 前进⼀步。 这样当 fast 指针遍历完整个数组 nums 后, nums[0…slow] 就是不重复元素。
class Solution {
public int removeDuplicates(int[] nums) {
int slow = 0, fast = 0;
while (fast < nums.length) {
if (nums[slow] != nums[fast]) {
slow++;
nums[slow] = nums[fast]; // 维护 nums[0..slow] ⽆重复
}
fast++;
}
return slow + 1; // 数组⻓度为索引 + 1
}
}
83. 删除排序链表中的重复元素(简单)
class Solution {
public ListNode deleteDuplicates(ListNode head) {
if(head==null){
return head;
}
ListNode slow = head, fast = head;
while (fast != null) {
if (fast.val != slow.val) {
slow = slow.next;
slow.val = fast.val;
}
fast = fast.next;
}
slow.next = null;
return head;
}
}
27. 移除元素(简单)
class Solution {
// O(n) O(1)
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++;
}
fast++;
}
return slow;
}
}
283. 移动零(简单)
class Solution {
public void moveZeroes(int[] nums) {
int slow = 0, fast = 0;
while (fast < nums.length) {
if (nums[fast] != 0) {
nums[slow++] = nums[fast];
}
fast++;
}
for (int i = slow; i < nums.length; i++) {
nums[i] = 0;
}
}
}
141. 环形链表(简单)
public class Solution {
//n 1
public boolean hasCycle(ListNode head) {
ListNode slow = head, fast = head;
while (fast!= null && fast.next!= null) {
slow = slow.next;
fast = fast.next.next;
if (slow == fast) {
return true;
}
}
return false;
}
}