双指针
相向双指针
leetcode 167. 两数之和 II - 输入有序数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 vector<int > twoSum (vector<int >& numbers, int target) { int n = numbers.size (); int left = 0 , right = n - 1 ; while (left < right){ if (numbers[left] + numbers[right] == target){ return {left + 1 , right + 1 }; } else if (numbers[left] + numbers[right] > target){ right--; } else if (numbers[left] + numbers[right] < target){ left++; } } return {}; }
同向双指针
leetcode 209. 长度最小的子数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int minSubArrayLen (int target, vector<int >& nums) { int n = nums.size (); int left = 0 ; int ans = n + 1 ; int s = 0 ; for (int right = 0 ; right < n; right++){ s += nums[right]; while (s - nums[left] >= target){ s -= nums[left]; left++; } if (s >= target){ ans = min (ans, right - left + 1 ); } } return ans <= n? ans : 0 ; }
二分查找
leetcode 34. 在排序数组中查找元素的第一个和最后一个位置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 vector<int > searchRange (vector<int >& nums, int target) { int n = nums.size (); int l1 = -1 ,l2 = -1 ; int left = 0 ; int right = n - 1 ; while (left <= right){ int mid = left + (right - left)/2 ; if (nums[mid] < target){ left = mid + 1 ; } else { right = mid - 1 ; } } if (left < n && nums[left] == target) l1 = left; else return {-1 , -1 }; left = 0 ; right = n - 1 ; while (left <= right){ int mid = left + (right - left)/2 ; if (nums[mid] <= target){ left = mid + 1 ; } else { right = mid - 1 ; } } if (right >= 0 && nums[right] == target) l2 = right; return {l1, l2}; }
反转链表
leetcode 206. 反转链表
1 2 3 4 5 6 7 8 9 10 11 ListNode* reverseList (ListNode* head) { ListNode* pre = nullptr ; ListNode* cur = head; while (cur){ ListNode* next = cur->next; cur->next = pre; pre = cur; cur = next; } return pre; }
快慢指针
leetcode 141. 环形链表
1 2 3 4 5 6 7 8 9 10 11 bool hasCycle (ListNode *head) { ListNode* slow = head; ListNode* fast = head; while (fast && fast->next){ slow = slow->next; fast = fast->next->next; if (slow == fast) return true ; } return false ; }
前后指针
leetcode 19. 删除链表的倒数第 N 个结点
1 2 3 4 5 6 7 8 9 10 11 12 ListNode *removeNthFromEnd (ListNode *head, int n) { ListNode *dummy = new ListNode (0 , head); ListNode *left = dummy, *right = dummy; while (n--) right = right->next; while (right->next) { left = left->next; right = right->next; } left->next = left->next->next; return dummy->next; }
单调栈
leetcode 739. 每日温度
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 vector<int > dailyTemperatures (vector<int >& temperatures) { int n = temperatures.size (); vector<int > ans (n,0 ) ; stack<int > st; for (int i = n - 1 ; i >= 0 ; i--){ int t = temperatures[i]; while (!st.empty () && t >= temperatures[st.top ()]){ st.pop (); } if (!st.empty ()) ans[i] = st.top () - i; st.push (i); } return ans; }
单调队列/双端队列
leetcode 239. 滑动窗口最大值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 vector<int > maxSlidingWindow (vector<int >& nums, int k) { vector<int > ans; deque<int > q; for (int i = 0 ; i < nums.size (); i++){ while (!q.empty () && nums[q.back ()] <= nums[i]){ q.pop_back (); } q.push_back (i); if (i - q.front () + 1 > k){ q.pop_front (); } if (i >= k - 1 ){ ans.push_back (nums[q.front ()]); } } return ans; }
0-1背包
有n个物品,第i个物品的重量为w[i],价值为v[i]。每个物品至多选一个,求体积和不超过capacity时的最大价值和。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 int knapsack (int n, int capacity, vector <int >& w, vector <int >& v) { vector <vector <int >> dp(n + 1 , vector <int >(capacity + 1 , 0 )); for (int i = 1 ; i <= n; i++){ for (int j = 0 ; j <= capacity; j++){ if (j >= w[i - 1 ]){ dp[i][j] = max(dp[i - 1 ][j], dp[i - 1 ][j - w[i - 1 ]] + v[i - 1 ]); } else { dp[i][j] = dp[i - 1 ][j]; } } } return dp[n][capacity]; }
完全背包
有n种物品,第i种物品的重量为w[i],价值为v[i]。每个物品无限次重复选,求体积和不超过capacity时的最大价值和。
1 2 3 4 5 6 7 8 9 int knapsack (int n, int capacity, vector <int >& w, vector <int >& v) { vector <int > dp (capacity + 1 , 0 ) ; for (int i = 1 ; i <= n; i++){ for (int j = w[i - 1 ]; j <= capacity; j++){ dp[j] = max(dp[j], dp[j - w[i - 1 ]] + v[i - 1 ]); } } return dp[capacity]; }
最长公共子序列
leetcode 1143. 最长公共子序列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int longestCommonSubsequence (string text1, string text2) { int m = text1.size (); int n = text2.size (); vector<vector<int >> dp (m + 1 , vector <int >(n + 1 , 0 )); for (int i = 1 ; i <= m; i++){ for (int j = 1 ; j <= n; j++){ if (text1[i - 1 ] == text2[j - 1 ]){ dp[i][j] = dp[i - 1 ][j - 1 ] + 1 ; } else { dp[i][j] = max (dp[i - 1 ][j], dp[i][j - 1 ]); } } } return dp[m][n]; }
相交链表
leetcode 160. 相交链表
1 2 3 4 5 6 7 8 9 10 11 struct ListNode *getIntersectionNode (struct ListNode *headA, struct ListNode *headB) { if (headA == NULL || headB == NULL ) { return NULL ; } struct ListNode *pA = headA, *pB = headB; while (pA != pB) { pA = pA == NULL ? headB : pA->next; pB = pB == NULL ? headA : pB->next; } return pA; }
两个非重叠子数组的最大和
leetcode 1031. 两个非重叠子数组的最大和
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 int maxSumTwoNoOverlap (int * nums, int numsSize, int firstLen, int secondLen) { int pre[numsSize+1 ]; pre[0 ] = 0 ; for (int i=0 ;i<numsSize;i++){ pre[i+1 ] = pre[i] + nums[i]; } int ans = 0 ; int maxfirst1 = -1 ; int maxsecond1 = -1 ; int maxfirst2 = -1 ; int maxsecond2 = -1 ; for (int i=firstLen+secondLen;i<=numsSize;i++){ maxsecond1 = pre[i] - pre[i-secondLen]; if (pre[i-secondLen]-pre[i-secondLen-firstLen]>maxfirst1){ maxfirst1 = pre[i-secondLen]-pre[i-secondLen-firstLen]; } ans = fmax(ans,maxfirst1+maxsecond1); maxfirst2 = pre[i]-pre[i-firstLen]; if (pre[i-firstLen]-pre[i-firstLen-secondLen]>maxsecond2){ maxsecond2 = pre[i-firstLen]-pre[i-firstLen-secondLen]; } ans = fmax(ans,maxfirst2+maxsecond2); } return ans; }
笨阶乘
leetcode 1006. 笨阶乘
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 int clumsy (int n) { int stack [n], top=0 ; stack [top++] = n; n = n-1 ; int index = 0 ; while (n){ if (index==0 ){ stack [top-1 ] *= n; } else if (index==1 ){ stack [top-1 ] /= n; } else if (index==2 ){ stack [top++] = n; } else if (index==3 ){ stack [top++] = -n; } index = (index+1 )%4 ; n--; } int sum = 0 ; for (int i=0 ;i<top;i++){ sum += stack [i]; } return sum; }
阶乘后的零的个数
leetcode 172. 阶乘后的零
1 2 3 4 5 6 7 8 int trailingZeroes (int n) { int ans = 0 ; while (n){ n /= 5 ; ans+=n; } return ans; }
Pow(x, n)
leetcode 50. Pow(x, n)
1 2 3 4 5 6 7 8 9 10 11 12 double quickMul (double x, long long N) { if (N==0 ){ return 1.0 ; } double y = quickMul(x, N/2 ); return N%2 == 0 ?y*y:y*y*x; } double myPow (double x, int n) { long long N = n; return N>=0 ?quickMul(x,N):1.0 /quickMul(x,-N); }
只出现一次的数字 II
leetcode 137. 只出现一次的数字 II
1 2 3 4 5 6 7 8 9 10 11 12 13 int singleNumber (int * nums, int numsSize) { int ans = 0 ; for (int i=0 ;i<32 ;i++){ int cnt = 0 ; for (int j=0 ;j<numsSize;j++){ cnt += (nums[j]>>i) & 1 ; } if (cnt%3 !=0 ) ans |= (1u <<i); } return ans; }
腐烂的橘子
leetcode 994. 腐烂的橘子
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 int orangesRotting (int ** grid, int gridSize, int * gridColSize) { int count = 0 ; while (1 ){ int end = 1 ; for (int i=0 ;i<gridSize;i++){ for (int j=0 ;j<gridColSize[i];j++){ if (grid[i][j]==3 ){ grid[i][j] = 2 ; } else if (grid[i][j]==1 ){ if ((i<gridSize-1 &&grid[i+1 ][j]==2 )||(j<gridColSize[i]-1 &&grid[i][j+1 ]==2 )){ grid[i][j] = 2 ; end = 0 ; } } else if (grid[i][j]==2 ){ if (i<gridSize-1 &&grid[i+1 ][j]==1 ){ grid[i+1 ][j] = 3 ; end = 0 ; } if (j<gridColSize[i]-1 &&grid[i][j+1 ]==1 ){ grid[i][j+1 ] = 3 ; end = 0 ; } } } } if (end){ break ; } else { count++; } } for (int i = 0 ; i < gridSize; i++) for (int j = 0 ; j < gridColSize[i]; j++) if (grid[i][j] == 1 ) return -1 ; return count; }
航班预订统计(差分数组)
leetcode 1109. 航班预订统计
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int * corpFlightBookings (int ** bookings, int bookingsSize, int * bookingsColSize, int n, int * returnSize) { int * ans = (int *)malloc (sizeof (int )*n); memset (ans,0 ,sizeof (int )*n); *returnSize = n; for (int i=0 ;i<bookingsSize;i++){ int left = bookings[i][0 ]; int right = bookings[i][1 ]; ans[left-1 ] += bookings[i][2 ]; if (right<n) ans[right] -= bookings[i][2 ]; } for (int i=1 ;i<n;i++){ ans[i] += ans[i-1 ]; } return ans; }
单调递增的数字
leetcode 738. 单调递增的数字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 int monotoneIncreasingDigits (int n) { if (n<10 ){ return n; } int arr[15 ]; int k = 0 ; while (n){ arr[k++] = n%10 ; n = n/10 ; } int flag = -1 ; for (int i=0 ;i<k-1 ;i++){ if (arr[i]<arr[i+1 ]){ flag = i; arr[i+1 ]--; } } for (int i=flag;i>=0 ;i--){ arr[i] = 9 ; } int ans = 0 ; for (int i=k-1 ;i>=0 ;i--){ if (ans==0 &&arr[i]==0 ){ continue ; } else { ans *= 10 ; ans += arr[i]; } } return ans; }
快乐数
leetcode 202. 快乐数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 int bitSquareSum (int n) { int sum=0 ; while (n>0 ){ int bit = n%10 ; sum+=bit*bit; n=n/10 ; } return sum; } bool isHappy (int n) { int slow = n, fast = n; do { slow = bitSquareSum(slow); fast = bitSquareSum(fast); fast = bitSquareSum(fast); }while (slow!=fast); return slow==1 ; }
最大间距
leetcode 164. 最大间距
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 int maximumGap (int * nums, int numsSize) { if (numsSize==1 ){ return 0 ; } int maxval = INT_MIN; for (int i=0 ;i<numsSize;i++){ maxval = fmax(maxval,nums[i]); } int buffer[numsSize]; int exp = 1 ; while (maxval>=exp ){ int cnt[10 ] = {0 }; for (int i=0 ;i<numsSize;i++){ int digit = nums[i]/exp ; cnt[digit%10 ]++; } for (int i=1 ;i<10 ;i++){ cnt[i] += cnt[i-1 ]; } for (int i=numsSize-1 ;i>=0 ;i--){ int digit = nums[i]/exp ; digit = digit%10 ; buffer[cnt[digit]-1 ] = nums[i]; cnt[digit]--; } for (int i=0 ;i<numsSize;i++){ nums[i] = buffer[i]; } exp *=10 ; } maxval = 0 ; for (int i=1 ;i<numsSize;i++){ maxval = fmax(maxval,nums[i]-nums[i-1 ]); } return maxval; }
格雷编码
leetcode 89. 格雷编码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 int * grayCode (int n, int * returnSize) { int * ans = malloc (sizeof (int )*(int )pow (2 ,n)); ans[0 ] = 0 ; int k=0 ; int j=1 ; while (j<pow (2 ,n)){ for (int i=k;i>=0 ;i--){ ans[i] = ans[i] << 1 ; ans[j++] = ans[i]+1 ; } k = j-1 ; } *returnSize = j; return ans; }
对于qsort函数,cmp()会有三种返回值:
1、返回一个正数:a排列在b之后;
2、返回0:a、b相等;
3、返回一个负数:a排在b之前;
位运算 两整数之和
leetcode 371. 两整数之和
1 2 3 4 5 6 7 8 int getSum (int a, int b) { while (b!=0 ){ unsigned int carry = (unsigned int )(a&b) << 1 ; a = a^b; b = carry; } return a; }
消除游戏
leetcode 390. 消除游戏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 int lastRemaining (int n) { if (n==1 ){ return 1 ; } int cnt = n; int step = 1 ; int k = 0 ; int a1 = 1 ; int an = n; while (cnt>1 ){ if (k%2 ==0 ){ if (cnt%2 ==0 ){ a1 += step; } else { a1 += step; an -= step; } } else { if (cnt%2 ==0 ){ an -= step; } else { a1 += step; an -= step; } } step *= 2 ; k++; cnt = cnt/2 ; } return an; }