Java算法OJ(13)双指针
双指针(Two Pointers)是一种常用的算法技巧,特别适用于数组和链表相关的问题。双指针通常有几种常见的用法:
- 快慢指针:用于检测循环或找到中点
- 左右指针:用于有序数组的搜索或处理
- 滑动窗口:用于子数组/子串问题
下面我将介绍几种常见的双指针问题及其Java解法。
1. 快慢指针示例 - 判断链表是否有环
class ListNode {
int val;
ListNode next;
ListNode(int x) {
val = x;
next = null;
}
}
public class Solution {
public boolean hasCycle(ListNode head) {
if (head == null || head.next == null) {
return false;
}
ListNode slow = head;
ListNode fast = head.next;
while (slow != fast) {
if (fast == null || fast.next == null) {
return false;
}
slow = slow.next;
fast = fast.next.next;
}
return true;
}
}
2. 左右指针示例 - 两数之和 II
给定一个已按照升序排列的有序数组,找到两个数使得它们相加之和等于目标数。
public int[] twoSum(int[] numbers, int target) {
int left = 0;
int right = numbers.length - 1;
while (left < right) {
int sum = numbers[left] + numbers[right];
if (sum == target) {
return new int[]{left + 1, right + 1};
} else if (sum < target) {
left++;
} else {
right--;
}
}
return new int[]{-1, -1};
}
3. 滑动窗口示例 - 无重复字符的最长子串
public int lengthOfLongestSubstring(String s) {
int n = s.length();
Set<Character> set = new HashSet<>();
int ans = 0, i = 0, j = 0;
while (i < n && j < n) {
if (!set.contains(s.charAt(j))) {
set.add(s.charAt(j++));
ans = Math.max(ans, j - i);
} else {
set.remove(s.charAt(i++));
}
}
return ans;
}
4. 合并两个有序数组
public void merge(int[] nums1, int m, int[] nums2, int n) {
int p1 = m - 1;
int p2 = n - 1;
int p = m + n - 1;
while (p1 >= 0 && p2 >= 0) {
nums1[p--] = (nums1[p1] > nums2[p2]) ? nums1[p1--] : nums2[p2--];
}
System.arraycopy(nums2, 0, nums1, 0, p2 + 1);
}
5. 盛最多水的容器
public int maxArea(int[] height) {
int max = 0;
int left = 0;
int right = height.length - 1;
while (left < right) {
int currentArea = Math.min(height[left], height[right]) * (right - left);
max = Math.max(max, currentArea);
if (height[left] < height[right]) {
left++;
} else {
right--;
}
}
return max;
}
双指针技巧总结
- 快慢指针常用于链表问题,如检测环、找中点等
- 左右指针常用于有序数组,如两数之和、反转数组等
- 滑动窗口常用于子串/子数组问题,如最小覆盖子串、最长无重复子串等
双指针技巧通常能将O(n²)的时间复杂度优化到O(n),是算法面试中非常重要的技巧。
33万+

被折叠的 条评论
为什么被折叠?



