1.两数之和 简单

    1. class Solution {
    2. public:
    3. vector<int> twoSum(vector<int>& nums, int target) {
    4. unordered_map<int,int> memo;
    5. for(int i=0;i<nums.size();i++){
    6. if(memo.count(nums[i])==0){
    7. memo.insert(make_pair(target-nums[i],i));
    8. }else{
    9. return {memo[nums[i]],i};
    10. }
    11. }
    12. return {};
    13. }
    14. };

    用哈希表做备忘
    11.盛最多水的容器 中等

    1. class Solution {
    2. public:
    3. int maxArea(vector<int>& height) {
    4. int L=0;
    5. int R=height.size()-1;
    6. int sum=0;
    7. while(L<R){
    8. sum=max(min(height[L],height[R])*(R-L),sum);
    9. if(height[L]<height[R]){
    10. L++;
    11. }else{
    12. R--;
    13. }
    14. }
    15. return sum;
    16. }
    17. };
    • 双指针
    • 用 left 和 right 两个指针从两端向中心收缩,一边收缩一边计算 [left, right] 之间的矩形面积,取最大的面积值即是答案。
    • key:指针收缩向更矮的方向,因为短的才是决定容量的

    15.三数之和

    1. class Solution {
    2. public:
    3. vector<vector<int>> threeSum(vector<int>& nums) {
    4. vector<vector<int>> res;
    5. if(nums.size()<3){
    6. return res;
    7. //真是坏!
    8. }
    9. sort(nums.begin(),nums.end());
    10. for(int i=0;i<nums.size()-2;i++){
    11. if(nums[i]>0){
    12. return res;
    13. }
    14. if(i>0&&nums[i]==nums[i-1]){
    15. continue;
    16. //注意点一,去重
    17. }
    18. int L=i+1;
    19. int R=nums.size()-1;
    20. while(L<R){
    21. if(nums[i]+nums[L]+nums[R]==0){
    22. res.push_back({nums[i],nums[L],nums[R]});
    23. while(R>L&&nums[L]==nums[L+1]) L++;
    24. while(R>L&&nums[R]==nums[R-1]) R--;
    25. L++;
    26. R--;
    27. }else if(nums[i]+nums[L]+nums[R]<0){
    28. while(L<R&&nums[L+1]==nums[L]) L++;
    29. L++;
    30. }else{
    31. while(L<R&&nums[R-1]==nums[R]) R--;
    32. R--;
    33. }
    34. }
    35. }
    36. return res;
    37. }
    38. };

    16.最接近的三数之和

    1. class Solution {
    2. public:
    3. int threeSumClosest(vector<int>& nums, int target) {
    4. int closest=nums[0]+nums[1]+nums[2];
    5. sort(nums.begin(),nums.end());
    6. for(int i=0;i<nums.size()-2;i++){
    7. if(i>0&&nums[i]==nums[i-1]){
    8. continue;
    9. }
    10. int L=i+1;
    11. int R=nums.size()-1;
    12. while(L<R){
    13. int curDif=abs(nums[i]+nums[R]+nums[L]-target);
    14. int prevDif=abs(closest-target);
    15. closest=prevDif>curDif?(nums[i]+nums[R]+nums[L]):closest;
    16. if(nums[i]+nums[R]+nums[L]>target){
    17. while(L<R&&nums[R-1]==nums[R]) R--;
    18. R--;
    19. }else{
    20. while(L<R&&nums[L+1]==nums[L]) L++;
    21. L++;
    22. }
    23. }
    24. }
    25. return closest;
    26. }
    27. };

    这种是考虑到不会出现正好等于target的情况的,不然的话和之前三数之和一样
    考虑了=target的情况?因为else的情况包含了,而且可能会重复,但是因为只要求返回和,而不是组合所以没差。
    18.四数之和

    1. class Solution {
    2. public:
    3. vector<vector<int>> fourSum(vector<int>& nums, int target) {
    4. vector<vector<int>> res;
    5. if(nums.size()<4) return res;
    6. sort(nums.begin(),nums.end());
    7. for(int i=0;i<nums.size();i++){
    8. if(i>0&&nums[i]==nums[i-1]) continue;//去重
    9. for(int j=i+1;j<nums.size();j++){
    10. if(j>i+1&&nums[j-1]==nums[j]) continue;//去重
    11. int L=j+1;
    12. int R=nums.size()-1;
    13. while(L<R){
    14. if(nums[i] + nums[j] > target - (nums[L] + nums[R])){
    15. //overflow!
    16. while(L<R&&nums[R]==nums[R-1]) R--;
    17. R--;
    18. }else if(nums[i] + nums[j] < target - (nums[L] + nums[R])){
    19. //overflow!
    20. while(L<R&&nums[L]==nums[L+1]) L++;
    21. L++;
    22. }else{
    23. res.push_back({nums[i],nums[j],nums[L],nums[R]});
    24. while(L<R&&nums[L]==nums[L+1]) L++;
    25. while(L<R&&nums[R]==nums[R-1]) R--;
    26. L++;
    27. R--;
    28. }
    29. }
    30. }
    31. }
    32. return res;
    33. }
    34. };

    :::tips 关于n数之和问题;

    • 首先要对数组做有序化
    • 有序化之后才能使用双指针
    • 对于n数之和不过是多次嵌套
    • 问题的难点在于如何去重以及在哪里去重 ::: :::info 双指针的问题:
    1. 什么时候收缩?
    2. 往哪里收缩?
    3. 要不要去重,如何去重
    4. 如果不让重拍如何去重 :::

    26.删除有序数组中的重复项

    1. class Solution {
    2. public:
    3. int removeDuplicates(vector<int>& nums) {
    4. if(nums.empty()){
    5. return 0;
    6. }
    7. int fast=0;
    8. int slow=0;
    9. while(fast<nums.size()){
    10. if(nums[fast]!=nums[slow]){
    11. slow++;
    12. nums[slow]=nums[fast];//赋值而不是交换
    13. }
    14. fast++;
    15. }
    16. return slow+1;
    17. }
    18. };

    本质是让快指针去探路,找到不同的值,然后慢指针维护当前数组都是不重复的。

    27.移除元素

    1. class Solution {
    2. public:
    3. int removeElement(vector<int>& nums, int val) {
    4. int fast=0;
    5. int slow=0;
    6. while(fast<nums.size()){
    7. if(nums[fast]!=val){
    8. nums[slow]=nums[fast];
    9. slow++;
    10. }
    11. fast++;
    12. }
    13. return slow;
    14. }
    15. };

    快指针去探路,找到不是val的值,和上一个一样的想法。
    75.颜色分类
    经典快排序

    1. class Solution {
    2. public:
    3. void sortColors(vector<int>& nums) {
    4. int red=-1;
    5. int blue=nums.size();
    6. int l=0;
    7. while(l<blue){
    8. if(nums[l]==0){
    9. swap(nums[++red],nums[l]);
    10. l++;//why?
    11. }else if(nums[l]==2){
    12. swap(nums[--blue],nums[l]);
    13. }else{
    14. l++;
    15. }
    16. }
    17. }
    18. };

    31. 下一个排列
    Medium

    1. class Solution {
    2. public:
    3. void nextPermutation(vector<int>& nums) {
    4. int index=-1;
    5. for(int i=nums.size()-1;i>0;i--){
    6. if(nums[i]>nums[i-1]){
    7. index=i;
    8. break;
    9. }
    10. }
    11. if(index==-1){
    12. sort(nums.begin(),nums.end());
    13. return;
    14. }
    15. int nxtmin=index;
    16. for(int i=index;i<nums.size();i++){
    17. if(nums[i]>nums[index-1]){
    18. nxtmin=i;
    19. }else{
    20. break;
    21. }
    22. }
    23. swap(nums[index-1],nums[nxtmin]);
    24. reverse(nums.begin()+index,nums.end());
    25. }
    26. };

    33. 搜索旋转排序数组
    Medium

    1. class Solution {
    2. public:
    3. int search(vector<int>& nums, int target) {
    4. int lo = 0, hi = nums.size() - 1;
    5. while (lo < hi) {
    6. int mid = (lo + hi) / 2;
    7. if ((nums[0] > target) ^ (nums[0] > nums[mid]) ^ (target > nums[mid]))
    8. lo = mid + 1;
    9. else
    10. hi = mid;
    11. }
    12. return lo == hi && nums[lo] == target ? lo : -1;
    13. }
    14. };