标签:cto null shu als 遇到 ref lock == 索引
双指针技巧可以分为两类:一类是【快慢指针】、一类是【左右指针】
快慢指针一般初始化指向链表头结点head,前进时快指针fast在前,慢指针slow在后,巧妙解决链表中的一些问题。
1 /** 2 * Definition for singly-linked list. 3 * struct ListNode { 4 * int val; 5 * ListNode *next; 6 * ListNode(int x) : val(x), next(NULL) {} 7 * }; 8 */ 9 class Solution { 10 public: 11 bool hasCycle(ListNode *head) { 12 ListNode *slow, *fast; 13 slow = head; fast = head; 14 while (fast != NULL && fast->next != NULL) { 15 fast = fast->next->next; 16 slow = slow->next; 17 ? 18 if (fast == slow) return true; 19 } 20 return false; 21 } 22 };
第一次相遇时,假设慢指针 slow 走了 k 步,那么快指针 fast 一定走了 2k 步,也就是说比 slow 多走了 k 步(也就是环的长度)。设相遇点距环的起点的距离为 m,那么环的起点距头结点 head 的距离为 k - m,也就是说如果从 head 前进 k - m 步就能到达环起点。
巧的是,如果从相遇点继续前进 k - m 步,也恰好到达环起点。
1 class Solution { 2 public: 3 ListNode *detectCycle(ListNode *head) { 4 ListNode *slow, *fast; 5 bool hascycle = false; //标记链表中是否有环 6 slow = head; fast = head; 7 while (fast != NULL && fast->next != NULL) { 8 fast = fast->next->next; 9 slow = slow->next; 10 if (fast == slow) { 11 hascycle = true; 12 break; 13 } 14 } 15 if (hascycle) { 16 slow = head; 17 while (slow != fast) { 18 slow = slow->next; 19 fast = fast->next; 20 } 21 return slow; 22 } else 23 return NULL; 24 } 25 };
快指针一次前进两步,慢指针一次前进一步,当快指针到达链表尽头时,慢指针就处于链表的中间位置。
class Solution { public: ListNode* middleNode(ListNode* head) { ListNode *slow, *fast; slow = head; fast = head; while (fast != NULL && fast->next != NULL) { fast = fast->next->next; slow = slow->next; } return slow; } };
我们的思路还是使用快慢指针,让快指针先走 k 步,然后快慢指针开始同速前进。这样当快指针走到链表末尾 null 时,慢指针所在的位置就是倒数第 k 个链表节点.
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* getKthFromEnd(ListNode* head, int k) { ListNode *slow, *fast; slow = head; fast = head; while (k--) { fast = fast->next; } while(fast != NULL) { fast = fast->next; slow = slow->next; } return slow; } };
左右指针在数组中实际是指两个索引值,一般初始化为 left = 0, right = nums.length - 1 。
1 int binarySerarch(vector<int> &nums, int target) { 2 int left = 0; 3 int right = nums.size() - 1; 4 while (left <= right) { 5 int mid = (left + right) >> 1; 6 if (nums[mid] == target) { 7 return mid; 8 } else if (nums[mid] < target) { 9 left = mid + 1; 10 } else { 11 right = mid - 1; 12 } 13 } 14 return -1; 15 }
如果数组有序,就应该想到双指针技巧。这道题的解法有点类似二分查找,通过调节 left 和 right 可以调整 sum 的大小:
1 int twoSum(vector<int> &nums, int target) { 2 int left = 0; 3 int right = nums.size() - 1; 4 while (left < right) { 5 int num = nums[left] + nums[right]; 6 if (num == target) { 7 return {left, right}; 8 } else if (num < target) { 9 left++; 10 } else { 11 right--; 12 } 13 } 14 return {}; 15 }
1 void reverse(int[] nums) { 2 int left = 0; 3 int right = nums.length - 1; 4 while (left < right) { 5 // swap(nums[left], nums[right]) 6 int temp = nums[left]; 7 nums[left] = nums[right]; 8 nums[right] = temp; 9 left++; right--; 10 } 11 }
标签:cto null shu als 遇到 ref lock == 索引
原文地址:https://www.cnblogs.com/captand/p/14450110.html