🍺 二分法
🍻 旋转数组
🥂 33. 搜索旋转排序数组 [旋转数组] [目标值] (二分法)
class Solution {
public :
int search ( vector< int > & nums, int target) {
int n = nums. size ( ) ;
int left = 0 , right = n - 1 ;
while ( left <= right) {
int mid = left + ( right - left) / 2 ;
if ( nums[ mid] == target) return mid;
if ( nums[ mid] <= nums[ 0 ] ) {
if ( nums[ mid] < target && target <= nums[ n - 1 ] ) {
left = mid + 1 ;
} else {
right = mid - 1 ;
}
} else {
if ( nums[ 0 ] <= target && target < nums[ mid] ) {
right = mid - 1 ;
} else {
left = mid + 1 ;
}
}
}
return - 1 ;
}
} ;
🍻 元素边界
🥂 34. 在排序数组中查找元素的第一个和最后一个位置 [有序数组] > [元素边界] > (二分法)
class Solution {
public :
vector< int > searchRange ( vector< int > & nums, int target) {
int left = find_l ( nums, target) ;
int right = find_r ( nums, target) ;
return { left, right} ;
}
int find_l ( vector< int > & nums, int target) {
int n = nums. size ( ) ;
int left = 0 , right = n - 1 ;
while ( left <= right) {
int mid = left + ( right - left) / 2 ;
if ( nums[ mid] >= target) {
right = mid - 1 ;
} else {
left = mid + 1 ;
}
}
if ( 0 <= left && left < n && nums[ left] == target) {
return left;
}
return - 1 ;
}
int find_r ( vector< int > & nums, int target) {
int n = nums. size ( ) ;
int left = 0 , right = n - 1 ;
while ( left <= right) {
int mid = left + ( right - left) / 2 ;
if ( nums[ mid] > target) {
right = mid - 1 ;
} else {
left = mid + 1 ;
}
}
if ( 0 <= right && right < n && nums[ right] == target) {
return right;
}
return - 1 ;
}
} ;
🥂 81. 搜索旋转排序数组Ⅱ [旋转数组] [有重] [目标值] (二分法)
class Solution {
public :
bool search ( vector< int > & nums, int target) {
int n = nums. size ( ) ;
int left = 0 , right = n - 1 ;
while ( left <= right) {
int mid = left + ( right - left) / 2 ;
if ( nums[ mid] == target) return true ;
if ( nums[ mid] == nums[ left] ) {
left++ ;
continue ;
}
if ( nums[ mid] == nums[ right] ) {
right-- ;
continue ;
}
if ( nums[ mid] < nums[ 0 ] ) {
if ( nums[ mid] < target && target <= nums[ n - 1 ] ) {
left = mid + 1 ;
} else {
right = mid - 1 ;
}
} else {
if ( nums[ 0 ] <= target && target < nums[ mid] ) {
right = mid - 1 ;
} else {
left = mid + 1 ;
}
}
}
return false ;
}
} ;
🥂 153. 寻找旋转排序数组中的最小值 [旋转数组] [最小值] (二分法)
class Solution {
public :
int findMin ( vector< int > & nums) {
int left = 0 , right = nums. size ( ) - 1 ;
while ( left <= right) {
int mid = left + ( right - left) / 2 ;
if ( nums[ mid] < nums[ right] ) {
right = mid;
} else if ( nums[ mid] > nums[ right] ) {
left = mid + 1 ;
} else {
right-- ;
}
}
return nums[ left] ;
}
} ;
🍺 双指针
🍻 元素合并
🥂 21. 合并两个有序链表 [有序链表] [合并] (双指针) (归并)
class Solution {
public :
ListNode* mergeTwoLists ( ListNode* list1, ListNode* list2) {
ListNode* dummy = new ListNode ( - 1 ) , * cur = dummy;
ListNode* p1 = list1, * p2 = list2;
while ( p1 != nullptr && p2 != nullptr ) {
if ( p1-> val < p2-> val) {
cur-> next = p1;
p1 = p1-> next;
} else {
cur-> next = p2;
p2 = p2-> next;
}
cur = cur-> next;
}
if ( p1 != nullptr ) cur-> next = p1;
if ( p2 != nullptr ) cur-> next = p2;
return dummy-> next;
}
} ;
🍻 元素交换
🥂 LCR 139. 训练计划 I [数组] [元素交换] (双指针)
class Solution {
public :
vector< int > trainingPlan ( vector< int > & actions) {
int n = actions. size ( ) ;
if ( n <= 1 ) return actions;
int left = 0 , right = n - 1 ;
while ( left < right) {
while ( left < right && actions[ left] % 2 == 1 ) {
left++ ;
}
while ( left < right && actions[ right] % 2 == 0 ) {
right-- ;
}
std:: swap ( actions[ left] , actions[ right] ) ;
}
return actions;
}
} ;
🍻 元素相交
🥂 142. 环形链表II [链表] > [环] > (双指针)
class Solution {
public :
ListNode * detectCycle ( ListNode * head) {
ListNode* dummy = new ListNode ( - 1 ) ;
dummy-> next = head;
ListNode* fast = dummy, * slow = dummy;
while ( fast-> next && fast-> next-> next) {
slow = slow-> next;
fast = fast-> next-> next;
if ( fast == slow) {
fast = dummy;
while ( fast != slow) {
slow = slow-> next;
fast = fast-> next;
}
return fast;
}
}
return nullptr ;
}
} ;
🥂 160. 相交链表 [链表] > [相交] > (双指针)
class Solution {
public :
ListNode * getIntersectionNode ( ListNode * headA, ListNode * headB) {
ListNode * p1 = headA, * p2 = headB;
while ( p1 != p2) {
if ( p1 == nullptr ) p1 = headB;
else p1 = p1-> next;
if ( p2 == nullptr ) p2 = headA;
else p2 = p2-> next;
}
return p1;
}
} ;
🍻 面积
🥂 11. 盛最多水的容器 [数组] [面积] (双指针)
class Solution {
public :
int maxArea ( vector< int > & height) {
int left = 0 , right = height. size ( ) - 1 ;
int res = 0 , cur = 0 ;
while ( left < right) {
cur = min ( height[ left] , height[ right] ) * ( right - left) ;
res = max ( res, cur) ;
if ( height[ left] < height[ right] ) {
left++ ;
} else {
right-- ;
}
}
return res;
}
} ;
🥂 42. 接雨水 [数组] [面积] (双指针)
class Solution {
public :
int trap ( vector< int > & height) {
int left = 0 , right = height. size ( ) - 1 ;
int left_max = height[ left] , right_max = height[ right] ;
int cur = 0 , res = 0 ;
while ( left <= right) {
left_max = max ( left_max, height[ left] ) ;
right_max = max ( right_max, height[ right] ) ;
if ( left_max < right_max) {
res += left_max - height[ left] ;
left++ ;
} else {
res += right_max - height[ right] ;
right-- ;
}
}
return res;
}
} ;
🥂 其他
🥂 31. 下一个排列 [数组] [排列] (双指针) (推导)
class Solution {
private :
int flag = 0 ;
public :
void nextPermutation ( vector< int > & nums) {
int n = nums. size ( ) ;
int i = n - 2 , j = n - 1 ;
while ( i >= 0 && nums[ i] >= nums[ i + 1 ] ) {
i-- ;
}
if ( i >= 0 ) {
while ( j > i && nums[ j] <= nums[ i] ) {
j-- ;
}
swap ( nums[ i] , nums[ j] ) ;
reverse ( nums. begin ( ) + i + 1 , nums. end ( ) ) ;
} else {
reverse ( nums. begin ( ) , nums. end ( ) ) ;
}
return ;
}
} ;
🍺 三指针
🍻 链表反转
🥂 25. K 个一组翻转链表 [链表] [分组反转] (三指针)
class Solution {
public :
ListNode* reverseKGroup ( ListNode* head, int k) {
ListNode* dummy = new ListNode ( - 1 ) ;
dummy-> next = head;
ListNode* pre = dummy, * end = dummy;
while ( end-> next != nullptr ) {
for ( int i = 0 ; i < k && end != nullptr ; ++ i) {
end = end-> next;
}
if ( end == nullptr ) break ;
ListNode* start = pre-> next, * next = end-> next;
end-> next = nullptr ;
pre-> next = reverse ( start) ;
start-> next = next;
pre = start;
end = start;
}
return dummy-> next;
}
ListNode* reverse ( ListNode* head) {
ListNode* pre = nullptr ;
ListNode* cur = head;
while ( cur != nullptr ) {
ListNode* next = cur-> next;
cur-> next = pre;
pre = cur;
cur = next;
}
return pre;
}
} ;
🥂 92. 反转链表II [链表] [反转] (三指针)
class Solution {
public :
ListNode* reverseBetween ( ListNode* head, int left, int right) {
ListNode* dummy = new ListNode ( - 1 ) ;
dummy-> next = head;
ListNode* pre = dummy, * end = dummy;
for ( int i = 0 ; i < left - 1 ; ++ i) pre = pre-> next;
cout << pre-> val;
for ( int j = 0 ; j < right; ++ j) end = end-> next;
ListNode* start = pre-> next, * next = end-> next;
end-> next = nullptr ;
pre-> next = reverse ( start) ;
start-> next = next;
return dummy-> next;
}
ListNode* reverse ( ListNode* head) {
ListNode* pre = nullptr ;
ListNode* cur = head;
while ( cur != nullptr ) {
ListNode* next = cur-> next;
cur-> next = pre;
pre = cur;
cur = next;
}
return pre;
}
} ;
🥂 206. 反转链表 [链表] [反转] (三指针)
class Solution {
public :
ListNode* reverseList ( ListNode* head) {
return reverse ( head) ;
}
ListNode* reverse ( ListNode* head) {
ListNode* pre = nullptr ;
ListNode* cur = head;
while ( cur != nullptr ) {
ListNode* next = cur-> next;
cur-> next = pre;
pre = cur;
cur = next;
}
return pre;
}
} ;
🍻 快速排序
🥂 215. 数组中的第K个最大元素 [数组] [第K大元素] (三指针) (快速排序)
class Solution {
private :
int target;
int res;
public :
int findKthLargest ( vector< int > & nums, int k) {
int n = nums. size ( ) ;
target = n - k;
quickSort ( nums, 0 , n - 1 ) ;
return res;
}
void quickSort ( vector< int > & nums, int left, int right) {
if ( left > right) return ;
if ( left == right && left == target) {
res = nums[ target] ;
return ;
}
vector< int > edge = part ( nums, left, right) ;
if ( edge[ 0 ] <= target && target <= edge[ 1 ] ) {
res = nums[ target] ;
return ;
}
quickSort ( nums, left, edge[ 0 ] - 1 ) ;
quickSort ( nums, edge[ 1 ] + 1 , right) ;
}
vector< int > part ( vector< int > & nums, int left, int right) {
int pivot_idx = rand ( ) % ( right - left + 1 ) + left;
int pivot = nums[ pivot_idx] ;
swap ( nums[ pivot_idx] , nums[ left] ) ;
int curp = left + 1 , leftp = left, rightp = right + 1 ;
while ( curp < rightp) {
if ( nums[ curp] < pivot) {
leftp++ ;
swap ( nums[ curp] , nums[ leftp] ) ;
curp++ ;
} else if ( nums[ curp] > pivot) {
rightp-- ;
swap ( nums[ curp] , nums[ rightp] ) ;
} else {
curp++ ;
}
}
swap ( nums[ left] , nums[ leftp] ) ;
return { leftp, rightp - 1 } ;
}
} ;
🥂 912. 排序数组 [数组] [排序] (三指针) (快速排序)
class Solution {
public :
vector< int > sortArray ( vector< int > & nums) {
int n = nums. size ( ) ;
quickSort ( nums, 0 , n - 1 ) ;
return nums;
}
void quickSort ( vector< int > & nums, int left, int right) {
if ( left > right) return ;
vector< int > edge = part ( nums, left, right) ;
quickSort ( nums, left, edge[ 0 ] - 1 ) ;
quickSort ( nums, edge[ 1 ] + 1 , right) ;
}
vector< int > part ( vector< int > & nums, int left, int right) {
int pivot_idx = rand ( ) % ( right - left + 1 ) + left;
int pivot = nums[ pivot_idx] ;
swap ( nums[ pivot_idx] , nums[ left] ) ;
int curp = left + 1 , leftp = left, rightp = right + 1 ;
while ( curp < rightp) {
if ( nums[ curp] < pivot) {
leftp++ ;
swap ( nums[ curp] , nums[ leftp] ) ;
curp++ ;
} else if ( nums[ curp] > pivot) {
rightp-- ;
swap ( nums[ curp] , nums[ rightp] ) ;
} else {
curp++ ;
}
}
swap ( nums[ left] , nums[ leftp] ) ;
return { leftp, rightp - 1 } ;
}
} ;
🍺 滑动窗口
🍻 子串
🥂 3. 无重复字符的最长子串 [字符串] [子串] (滑动窗口)
class Solution {
private :
unordered_map< char , int > umap;
int res = 0 ;
public :
int lengthOfLongestSubstring ( string s) {
int n = s. size ( ) ;
int left = 0 , right = 0 ;
while ( right < n) {
char cur_r = s[ right++ ] ;
umap[ cur_r] ++ ;
while ( umap[ cur_r] > 1 ) {
char cur_l = s[ left++ ] ;
umap[ cur_l] -- ;
}
res = max ( res, right - left) ;
}
return res;
}
} ;
🍻 区间和
🥂 1423. 可获得的最大点数 [数组] > [区间外最大值] > [区间内最小值] > (定长滑动窗口)
class Solution {
public :
int maxScore ( vector< int > & cardPoints, int k) {
int n = cardPoints. size ( ) ;
int windowSize = n - k;
int sum = accumulate ( cardPoints. begin ( ) , cardPoints. begin ( ) + windowSize, 0 ) ;
int min_val = sum;
for ( int i = 0 ; i < n - windowSize; ++ i) {
int left = i, right = i + windowSize;
sum += cardPoints[ right] - cardPoints[ left] ;
min_val = min ( min_val, sum) ;
}
return accumulate ( cardPoints. begin ( ) , cardPoints. end ( ) , 0 ) - min_val;
}
} ;