个人技术分享

  • 对撞指针是双指针算法之一。
  • 对撞指针从两端向中间迭代数组。一个指针从始端开始,另一个从末端开始。
  • 对撞指针的终止条件是两个指针相遇。
  • 对撞指针常用于排序数组

167. 两数之和 II - 输入有序数组

class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        int left = 0, right = numbers.size() - 1;
        while (left < right) {
            int sum = numbers[left] + numbers[right];
            if (sum == target) {
                return {left + 1, right + 1};
            } else if (sum < target) {
                left++;
            } else {
                right--;
            }
        }
        return {-1, -1};
    }
};

27. 移除元素

class Solution {
public:
    int removeElement(vector<int>& nums, int val) {
        int left = 0, right = nums.size();
        while (left < right) {
            if (nums[left] == val) {
                nums[left] = nums[right-1];
                right--;
            } else {
                left++;
            }
        }
        return left;
    }
};

125. 验证回文串

class Solution {
public:
    bool isPalindrome(string s) {
        string sgood;
        for (char ch: s) {
            if (isalnum(ch)) {
                sgood += tolower(ch);
            }
        }
        int n = sgood.size();
        int left = 0, right = n - 1;
        while (left < right) {
           if (sgood[left] != sgood[right]) {
                return false;
            }
            ++left;
            --right;
        }
        return true;
    }
};

11. 盛最多水的容器

在每个状态下,无论长板或短板向中间收窄一格,都会导致水槽 底边宽度−1变短:

  • 若向内 移动短板 ,水槽的短板 min(h[i],h[j]) 可能变大,因此下个水槽的面积 可能增大 。
  • 若向内 移动长板 ,水槽的短板 min(h[i],h[j])不变或变小,因此下个水槽的面积 一定变小 。

因此,初始化双指针分列水槽左右两端,循环每轮将短板向内移动一格,并更新面积最大值,直到两指针相遇时跳出;即可获得最大面积。

算法流程:

  • 初始化: 双指针 iii , jjj 分列水槽左右两端;
  • 循环收窄: 直至双指针相遇时跳出;
    • 更新面积最大值 res ;
    • 选定两板高度中的短板,向中间收窄一格;
  • 返回值: 返回面积最大值 res即可;
class Solution {
public:
    int maxArea(vector<int>& height) {
        int len = height.size();
        int left = 0, right = len - 1;
        int area = 0;
        while (left < right) {
            int curArea = min(height[left], height[right]) * (right - left);
            area = max(area, curArea);
            if (height[left] < height[right]) {
                left++;
            } else {
                right--;
            }
        }
        return area;
    }
};

215. 数组中的第K个最大元素

class Solution {
public:
    int partition(vector<int>& nums, int left, int right) {
        int randIndex = left + rand() % (right - left + 1);
        swap(nums[left], nums[randIndex]);

        int pivot = nums[left];
        while (left < right) {
            while (left < right && nums[right] >= pivot) {
                right--;
            }
            nums[left] = nums[right];
            while (left < right && nums[left] <= pivot) {
                left++;
            }
            nums[right] = nums[left];
        }
        nums[left] = pivot;
        return left;
    }

    int findKthLargest(vector<int>& nums, int k) {
        int left = 0, right = nums.size() - 1;
        int targetIndex = nums.size() - k;
        while (left <= right) {
            int mid = partition(nums, left, right);
            if (mid == targetIndex) {
                return nums[mid];
            } else if (mid < targetIndex) {
                left = mid + 1;
            } else {
                right = mid - 1;
            }
        }
        return INT_MIN;
    }
};

  • leetcode 对撞指针 解法题目
  • 7. 整数反转(easy)
  • 9.回文数(easy)
  • 27.移除元素(easy)
  • 125.验证回文串(easy)
  • 167.两数之II-输入有序数组(easy)
  • 190.颠倒二进制位(easy)
  • 344.反转字符串(easy)
  • 345.反转字符串中的元音字母(easy)
  • 11.盛水最多的容器(medium)