LeetCode题解——双指针(一)

我不是女神ヾ 2023-06-08 15:00 188阅读 0赞

文章目录

      1. 两数之和 II - 输入有序数组
      • 二分查找
      • 双指针
      1. 平方数之和
      • 双指针
      1. 反转字符串中的元音字母
      • 双指针
      • 双指针优化
      1. 验证回文字符串 Ⅱ
      • 双指针

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

给定一个已按照升序排列 的有序数组,找到两个数使得它们相加之和等于目标数。

函数应该返回这两个下标值 index1 和 index2,其中 index1 必须小于 index2。

说明:

返回的下标值(index1 和 index2)不是从零开始的。
你可以假设每个输入只对应唯一的答案,而且你不可以重复使用相同的元素。
示例:

  1. 输入: numbers = [2, 7, 11, 15], target = 9
  2. 输出: [1,2]
  3. 解释: 2 7 之和等于目标数 9 。因此 index1 = 1, index2 = 2

二分查找

x + y = target, 先设numbers[i] = x,二分查找target - y ,找到即成功

  1. class Solution {
  2. public:
  3. int binsearch(vector<int>& numbers, int target)
  4. {
  5. int left = 0, right = numbers.size() - 1;
  6. int ans = -1;
  7. while(left <= right)
  8. {
  9. int mid = left + ((right - left) >> 1);
  10. if(numbers[mid] < target)
  11. left = mid + 1;
  12. else if(numbers[mid] > target)
  13. right = mid - 1;
  14. else
  15. {
  16. ans = mid;
  17. break;
  18. }
  19. }
  20. return ans;
  21. }
  22. vector<int> twoSum(vector<int>& numbers, int target) {
  23. vector<int> ans;
  24. for(int i = 0; i < numbers.size(); ++i)
  25. {
  26. int y = target - numbers[i];
  27. int j = binsearch(numbers, y);
  28. if(j != -1 && i != j)
  29. {
  30. ans.push_back(min(i+1, j+1));
  31. ans.push_back(max(i+1, j+1));
  32. break;
  33. }
  34. }
  35. return ans;
  36. }
  37. };

双指针

由于数组是有序的,只需要双指针即可。一个left首指针,一个right尾指针,如果left + right 值大于 target 则 right左移动, 否则 left 右移。

  1. class Solution {
  2. public:
  3. vector<int> twoSum(vector<int>& numbers, int target) {
  4. vector<int> ans;
  5. int left = 0, right = numbers.size() - 1;
  6. while(left < right)
  7. {
  8. int sum = numbers[left] + numbers[right];
  9. if(sum == target)
  10. {
  11. ans.push_back(left + 1);
  12. ans.push_back(right + 1);
  13. break;
  14. }
  15. else if(sum < target)
  16. left++;
  17. else
  18. right--;
  19. }
  20. return ans;
  21. }
  22. };

633. 平方数之和

给定一个非负整数 c ,你要判断是否存在两个整数 a 和 b,使得 a2 + b2 = c。

  1. 示例1:
  2. 输入: 5
  3. 输出: True
  4. 解释: 1 * 1 + 2 * 2 = 5
  5. 示例2:
  6. 输入: 3
  7. 输出: False

双指针

首指针left = 0, 尾指针 right = sqrt©的整数,然后从两头遍历,left * left + right * right < c 则left++;否则,right–。防止越界特殊处理一下。

  1. class Solution {
  2. public:
  3. bool judgeSquareSum(int c) {
  4. if(c == 0)
  5. return true;
  6. double left = 0;
  7. double right = (int)sqrt(c);
  8. bool flag = 0;
  9. double eps = 1e-8;
  10. while(left <= right)
  11. {
  12. double tmp = c - left * left;
  13. if(fabs(tmp / right - right) < eps)
  14. {
  15. flag = 1;
  16. break;
  17. }
  18. else if((right - tmp / right) > eps)
  19. right--;
  20. else
  21. left++;
  22. }
  23. return flag;
  24. }
  25. };

format_png

345. 反转字符串中的元音字母

编写一个函数,以字符串作为输入,反转该字符串中的元音字母。

示例 1:

输入: “hello”
输出: “holle”
示例 2:

输入: “leetcode”
输出: “leotcede”
说明:
元音字母不包含字母”y”。

双指针

双指针,一个在头,一个在尾,两个都是元音就交换,遍历一遍即可

  1. class Solution {
  2. public:
  3. bool is_flag(char c)
  4. {
  5. if(c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u' || c == 'A' || c == 'E' || c == 'I' || c == 'O' || c =='U')
  6. return true;
  7. return false;
  8. }
  9. string reverseVowels(string s) {
  10. int left = 0, right = s.size() - 1;
  11. while(left < right)
  12. {
  13. bool f1 = is_flag(s[left]), f2 = is_flag(s[right]);
  14. if(f1 && f2)
  15. {
  16. char c = s[left];
  17. s[left] = s[right];
  18. s[right] = c;
  19. left++, right--;
  20. }
  21. else if(f1 && !f2)
  22. right--;
  23. else if(!f1 && f2)
  24. left++;
  25. else
  26. right--, left++;
  27. }
  28. return s;
  29. }
  30. };

双指针优化

判断的次数少一点

  1. class Solution {
  2. public:
  3. string reverseVowels(string s) {
  4. unordered_map<char,int> map{
  5. {
  6. 'a', 1}, {
  7. 'e', 1}, {
  8. 'i', 1},{
  9. 'o', 1},{
  10. 'u', 1},
  11. {
  12. 'A', 1},{
  13. 'E', 1},{
  14. 'I', 1},{
  15. 'O', 1},{
  16. 'U', 1}};
  17. int i =0;
  18. int j = s.length()-1;
  19. char temp;
  20. while(i<j)
  21. {
  22. while(i<j&&map[s[i]]!=1) i++;
  23. while(i<j&&map[s[j]]!=1) j--;
  24. if(i<j)
  25. {
  26. temp = s[i];
  27. s[i] = s[j];
  28. s[j] = temp;
  29. }
  30. i++;j--;
  31. }
  32. return s;
  33. }
  34. };

680. 验证回文字符串 Ⅱ

给定一个非空字符串 s,最多删除一个字符。判断是否能成为回文字符串。

示例 1:

输入: “aba”
输出: True
示例 2:

输入: “abca”
输出: True
解释: 你可以删除c字符。
注意:

字符串只包含从 a-z 的小写字母。字符串的最大长度是50000。

双指针

如果字符串的起始字符和结束字符相同(即 s[0]==s[s.length-1]),则内部字符是否为回文(s[1], s[2], …, s[s.length - 2])将唯一地确定整个字符串是否为回文。

算法:
假设我们想知道 s[i],s[i+1],…,s[j] 是否形成回文。如果 i >= j,就结束判断。如果 s[i]=s[j],那么我们可以取 i++;j–。否则,回文必须是 s[i+1], s[i+2], …, s[j] 或 s[i], s[i+1], …, s[j-1] 这两种情况。
见代码中注释

  1. class Solution {
  2. public:
  3. bool validPalindrome(string s) {
  4. int l = 0, r = s.length() - 1;
  5. int del_index = -1;
  6. while(l <= r)
  7. {
  8. if(s[l] == s[r])
  9. l++, r--;
  10. else
  11. {
  12. if(del_index == -1) // 第一次不等,先删除左边的,l++
  13. del_index = l, l++;
  14. else if(del_index == s.length()) // 第三次不等,直接返回false
  15. return false;
  16. else // 第二次不等,l返回到第一次不等的位置,r也回到对应的位置,删除右边的
  17. l = del_index, r = s.length() - l - 2, del_index = s.length();
  18. }
  19. }
  20. return true;
  21. }
  22. };

在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,188人围观)

还没有评论,来说两句吧...

相关阅读

    相关 【算法】指针题解

    双指针 算法解释:(直接照搬齐姐的了) 双指针主要用于遍历数组,两个指针指向不同的元素,从而协同完成任务。也可以延伸到多 个数组的多个指针。 若两个指针指向同一数组

    相关 leetcode指针(进阶)

    1. 删除排序链表中的重复元素 II 存在一个按升序排列的链表,给你这个链表的头节点 head ,请你删除链表中所有存在数字重复情况的节点,只保留原始链表中 没有重复出现