演算法中的雙指標使用,有時候會覺得很巧妙,解決了很多的問題,有必要歸納總結一下,首先雙指標也是個很寬泛的概念,它類似于遍歷中的 i 和 j 但是其區別是,兩個指標是同時移動的,即沒有貢獻復雜度從O(N) 到 O(N*N) ,所以被很多演算法大佬所推崇,所以基于此歸納總結出雙指標的常見解法和套路,
1.題型歸納
這里將題型歸納為三種,分別如下:
-
快慢指標(前后按不同步調的兩個指標)
-
前后雙端指標(一個在首,一個在尾部,向中間靠攏)
-
固定間隔的指標(以i, i + k的間距的兩個指標)
前面講到,這三種指標都是遍歷一次陣列即可完成,其時間復雜度低于或者等于O(N) ,空間復雜度是O(1) 因為就兩個指標存盤,
2.常見題型
2.1快慢指標
相當經典的一道題:
- 判斷鏈表是否有環-
通過步調不一致的兩個指標,一前一后一起移動,直到指標重合了
https://leetcode.com/problems/linked-list-cycle/description,代碼片段如下:
public boolean hasCycle(ListNode head) {
ListNode slow = head;
ListNode fast = head;
while (slow != null && fast != null) {
ListNode n = fast.next;
fast = n == null ? null : n.next;
if (slow == fast) {
return true;
}
slow = slow.next;
}
return false;
}
- 尋找重復復數,從陣列中找出一個重復的整數:https://leetcode-cn.com/problems/find-the-duplicate-number/
代碼解決如下:
public int findDuplicate(int[] nums) {
// 將其看成是一個回圈的鏈表,快慢指標回圈
int index1 = 0;
int index2 = 0;
do
{
index1 = nums[index1];
index2 = nums[index2];
index2 = nums[index2];
}while (nums[index1] != nums[index2]);
index1 = 0;
// 找出在哪個位置為起始點,可證必定在圓圈起點相遇
while(index1 != index2){
index1 = nums[index1];
index2 = nums[index2];
}
return index1;
}
2.2 前后首尾端點指標
- 二分查找
二分查找是典型的前后指標的題型,代碼如下:
public static int binarySearch(int[] array, int targetElement) {
int leftIndex = 0, rightIndex = array.length - 1, middleIndex = (leftIndex + rightIndex) / 2;
while(leftIndex <= rightIndex) {
int middleElement = array[middleIndex];
if(targetElement < middleElement) {
rightIndex = middleIndex - 1;
}else if(targetElement > middleElement) {
leftIndex = middleIndex + 1;
}else {
return middleIndex;
}
middleIndex = (leftIndex + rightIndex) / 2;
}
return -1;
}
2.3 固定間隔的指標
- 求鏈表中點https://leetcode-cn.com/problems/middle-of-the-linked-list/
// 快指標q每次走2步,慢指標p每次走1步,當q走到末尾時p正好走到中間,
class Solution {
public ListNode middleNode(ListNode head) {
ListNode p = head, q = head;
while (q != null && q.next != null) {
q = q.next.next;
p = p.next;
}
return p;
}
}
- 求鏈表倒數第k個元素 https://leetcode-cn.com/problems/lian-biao-zhong-dao-shu-di-kge-jie-dian-lcof/
// 快慢指標,先讓快指標走k步,然后兩個指標同步走,當快指標走到頭時,慢指標就是鏈表倒數第k個節點,
public ListNode getKthFromEnd(ListNode head, int k) {
ListNode frontNode = head, behindNode = head;
while (frontNode != null && k > 0) {
frontNode = frontNode.next;
k--;
}
while (frontNode != null) {
frontNode = frontNode.next;
behindNode = behindNode.next;
}
return behindNode;
}
3. 模板總結
看完三個代碼,是不是覺得很簡單,下面總結一下三種雙指標的代碼模板
// 1.快慢指標
l = 0
r = 0
while 沒有遍歷完
if 一定條件
l += 1
r += 1
return 合適的值
//2. 左右端點指標
l = 0
r = n - 1
while l < r
if 找到了
return 找到的值
if 一定條件1
l += 1
else if 一定條件2
r -= 1
return 沒找到
//3. 固定間距指標
l = 0
r = k
while 沒有遍歷完
自定義邏輯
l += 1
r += 1
return 合適的值
吳邪,小三爺,混跡于后臺,大資料,人工智能領域的小菜鳥,
更多請關注

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/230935.html
標籤:其他
上一篇:基于done檔案的資料監控-理論
