算法学习之双指针(java版)

算法学习之双指针(java版)

文章目录

  • 算法学习之双指针(java版)
    • 概念
      • 快慢指针
      • 左右指针
    • 例题
      • 判断链表是否有环(快慢指针)
      • 判断链表是否有环并返回其实位置(快慢指针)
      • 两数之和(左右指针)
    • 总结

数组或字符串相关的问题经常需要运用双指针来求解。而双指针又分为快慢指针和左右指针。其中快慢指针主要用于解决链表问题,而左右指针用于解决数组问题。

概念

快慢指针

顾名思义,快慢指针是指一个指针走的快,一个指针走得慢。

左右指针

左右指针是指双指针中一个指针在数组的最左侧,而另一个在最右侧。通过判断,可以分别让两侧的指针向中间移动,以求解问题。

例题

判断链表是否有环(快慢指针)

思路:快指针每次走两步,慢指针每次走一步。如果链表中存在环,总有那么一个时刻快指针比慢指针多走了一圈,此时他们相遇。

boolean hasCycle(ListNode head){
     
  ListNode fast, slow;
  fast = slow = head;
  while(fast != null && fast.next != null){
     
    fast = fast.next.next;
    slow = slow.next;
    if(slow == fast){
     
      return true;
    }
  }
  return false;
}

判断链表是否有环并返回其实位置(快慢指针)

思路:快指针是慢指针的两倍速度,当相遇时,慢指针走了k步,快指针走了2k步,其中k就是一圈的长度。假设相遇点距离环起点距离为m,那么k-m是起点到head的距离。当slow从起点走k-m步,fast继续走k-m步时,fast指针走了3k-m步,正好处于起点位置,slow也在起点位置,两者相遇。
算法学习之双指针(java版)_第1张图片
[图片来自labuladong的算法小抄]

ListNode detectCycle(ListNode head){
     
	ListNode slow, fast;
	slow = fast = head;
	while(fast != null && fast.next != null){
     
		fast = fast.next.next;
		slow = slow.next;
		if(slow == fast) break;
	}
	slow = head;
	while(slow!=fast){
     
		slow = slow.next;
		fast = fast.next;
	}
	return slow;
}

两数之和(左右指针)

给定一个按升序排列的有序数组,找到两个数使得它们相加之和等于目标数
输入:nums=[2, 7, 11, 15], target = 9
输出: [1, 2]

思路:这题用到左右指针。初始化left=0, right=nums.length,当nums[left]+nums[right]>target时,right指针向左移动,减小两数之和。相反的情况时,left指针向右移动,增加两数之和。

int[] twoSum(int[] nums, int target){
     
  int len = nums.length;
  int left = 0, right = len-1;
  while(left<right){
     
    if(nums[left]+nums[right]==target){
     
      return new int[]{
     left+1,right+1};
    }else if(nums[left]+nums[right]<target){
     
      left++;
    }else{
     
      right--;
    }
  }
  return new int[]{
     -1, -1};
}

总结

双指针的精髓就是左右指针的不同节奏移动,根据不同的条件对不同的指针进行操作。

申明:本博文是看了labuladong的算法小抄之后个人的理解以及总结。

你可能感兴趣的:(算法学习,算法,指针,java)