力扣 双指针专题
167. 两数之和 II
https://leetcode-cn.com/problems/two-sum-ii-input-array-is-sorted/
vector<int> twoSum(vector<int>& numbers, int target) {
for(int i=0,j=numbers.size()-1;i<j;i++){
while(i<j && numbers[i]+numbers[j]>target) j--;
if(i<j && numbers[i]+numbers[j]==target) return {i+1,j+1};
}
return {};
}
思路:定义双指针,i在数组的开头,j在数组的末尾。
如果两个指针指向元素的和 sum == target,那么得到要求的结果;
如果 sum > target,移动较大的元素,使 sum 变小一些;
如果 sum < target,移动较小的元素,使 sum 变大一些。
数组中的元素最多遍历一次,时间复杂度为 O(N)。只使用了两个额外变量,空间复杂度为 O(1)。
633. 平方数之和
https://leetcode-cn.com/problems/sum-of-square-numbers/submissions/
bool judgeSquareSum(int c) {
for(long long i=0;i*i<=c;i++){
int j=c-i*i;
int r=sqrt(j);
if(r*r==j){
return true;
}
}
return false;
}
直接暴力完事。 也可以用上题的思路,稍微转换一下就可
class Solution {
public:
bool judgeSquareSum(int c) {
for(long long i=0,j=sqrt(c);i<=j;i++){
while(i<=j && i*i+j*j >c) j--;
if(i<=j && i*i+j*j==c) return true;
}
return false;
}
};
345. 反转字符串中的元音字母
头尾开始循环,都找到就交换即可
class Solution {
public:
string s="aeiou";
bool isyuan(char c){
return s.find(tolower(c))!=-1;
}
string reverseVowels(string s) {
for(int i=0,j=s.size()-1;i<j;i++,j--){
while(i<j && !isyuan(s[i]))i++;
while(i<j && !isyuan(s[j]))j--;
swap(s[i],s[j]);
}
return s;
}
};
680. 验证回文字符串 Ⅱ
https://leetcode-cn.com/problems/valid-palindrome-ii/description/
class Solution {
public:
bool validPalindrome(string s) {
for (int i = 0, j = s.size() - 1;i < j;i++, j--) {
if (s[i] != s[j]) {
return(fun(i + 1, j, s) || fun(i, j - 1, s));
}
}
return true;
}
bool fun(int i, int j,string s) {
while (i < j) {
if (s[i] != s[j]) {
return false;
}
i++;j--;
}
return true;
}
};
本题的关键是处理删除一个字符。在使用双指针遍历字符串时,如果出现两个指针指向的字符不相等的情况,我们就试着删除一个字符,再判断删除完之后的字符串是否是回文字符串。
在判断是否为回文字符串时,我们不需要判断整个字符串,因为左指针左边和右指针右边的字符之前已经判断过具有对称性质,所以只需要判断中间的子字符串即可。
在试着删除字符时,我们既可以删除左指针指向的字符,也可以删除右指针指向的字符。
88. 合并两个有序数组
https://leetcode-cn.com/problems/merge-sorted-array/
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int k=m+n-1;//确定开始下标
int i=m-1,j=n-1;//确定两个数组指针下标
while(i>=0 && j>=0){
if(nums1[i]>=nums2[j]){
nums1[k--]=nums1[i--];
}
else nums1[k--]=nums2[j--];
}
while(j>=0){
nums1[k--]=nums2[j--];
}
}
};
两个有序数组合并,但是题目比较特殊需要结果合并到第一个数组,这里通过反向合并即可解决问题。
141. 环形链表
https://leetcode-cn.com/problems/linked-list-cycle/
/**
* Definition for singly-linked list.
* class ListNode {
* int val;
* ListNode next;
* ListNode(int x) {
* val = x;
* next = null;
* }
* }
*/
public class Solution {
public boolean hasCycle(ListNode head) {
if(head==null) return false;
ListNode l1=head;
ListNode l2=head.next;
while(l1 != null && l2 != null && l2.next!=null){
if(l1==l2) return true;
l1=l1.next;//每次走一步
l2=l2.next.next;//每次走两步
}
return false;
}
}
经典快慢指针判断环算法(java语言)
524. 通过删除字母匹配到字典里最长单词
class Solution {
public:
bool check(string& a, string& b) {
int i=0, j = 0;
while (i < a.size() && j < b.size()) {
if (a[i] == b[j]) {
i++;
}
j++;
if (i == a.size() ) {
return true;
}
}
return false;
}
string findLongestWord(string s, vector<string>& d) {
string res;
for (auto str : d) {
if (check(str, s)) {
if (res.empty() == true || res.size()<str.size() || res.size()==str.size() && res>str) {
res = str;
}
}
}
return res;
}
};
通过双指针实现一个判断是否是子序列函数
之后每次循环字符串集,如果是子序列就判断和之前保存的答案哪个是最优解

浙公网安备 33010602011771号