2、双指针问题(结合 LeetCode 167、88、142、76、633、680、524、340学习)(76未做)

作者学习算法的教材是LeetCode 101

有需要的同学直接GitHub搜索LeetCode 101即可

**

双指针问题

167. 两数之和 II - 输入有序数组(难度:简单)

  • 本题过于简单,直接贴代码:
class Solution {
public:
    vector<int> twoSum(vector<int>& numbers, int target) {
        vector<int> back;
        int start = 0;
        int end = numbers.size()-1;     
        int sum; 
        while (start != end) {
            sum = numbers[start]+numbers[end];
            if (sum == target) {
                back.push_back(start+1);
                back.push_back(end+1);
                break;
            }
            else if (sum < target) {
                start++;
            }
            else if (sum > target) {
                end--;
            }
        }
        return back;
    }
};

88.合并两个有序数组(难度:简单)

  • 本题由于两个数组有序,于是可以设定两个指针分别在两个数组的末尾,再设置一个pos指针指向要复制的位置,每次将较大的数字复制到nums1的后边,然后pos指针向前移动一位;
  • 若nums1数组全部复制完,则将nums2中的数字继续复制,若nums2数组全部复制完,则直接结束,因为此时nums1数组必然是有序的;
  • 代码如下:
class Solution {
public:
    void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
        int pos = m-- + n-- -1;
        while (m >= 0 && n >= 0) {
            nums1[pos--] = nums1[m] > nums2[n] ? nums1[m--] : nums2[n--];
        }
        while (n >= 0) {
            nums1[pos--] = nums2[n--];
        }
    }
};

142.环形链表Ⅱ(难度:中等)

  • 本题用到快慢指针(Floyd判圈法);
  • 定义两个指针low和fast,首先low向前一次,fast向前两次,如果fast可以和low相遇,代表有回路,如果fast可以走完整个链表,说明没有回路;
  • 当fast和low第一次相遇时,将fast重新移动到链表开头,并且每次只前进一次,当low和fast第二次相遇时,相遇点即为环路的开始点;
  • 代码如下:
class Solution {
public:
    ListNode *detectCycle(ListNode *head) {
        ListNode *low = head , *fast = head;
        do {
            if (fast == NULL || fast->next == NULL) {
                return NULL;
            }
            fast = fast->next->next;
            low = low->next;
        } while (fast != low);
        fast = head;
        while (fast != low) {
            fast = fast->next;
            low = low->next;
        }
        return fast;
    }
};

76.最小覆盖子串(难度:困难)

  • 本题用到快慢指针(Floyd判圈法);
  • 代码如下:

633.平方数之和(难度:中等)

  • 思路与167相同,注意定义变量为长整型即可;
  • 代码如下:
class Solution {
public:
    bool judgeSquareSum(int c) {
        long long min = 0,max = sqrt(c);
        while (min*min + max*max != c && max >= min) {
            if (min*min + max*max > c) {
                max -= 1;
            }
            else {
                min += 1;
            }
        }
        if (min*min + max*max == c) {
            return true;
        }
        else {
            return false;
        }
    }
};

680.验证回文字符串Ⅱ(难度:简单)

  • 思路与167、633相似;
  • 重点是递归函数中的++min以及第二个递归函数中的–min和–max,使用–min的原因是需要先计算,再代入;第二个–min的原因是前一个递归函数已经++,所以要先–;
  • 代码如下:
class Solution {
public:
	int flag = 0;
	bool isPalindrome(string s, int min, int max) {
		while (max >= min) {
			if (s[min] == s[max]) {
				min++;
				max--;
			}
			else {
				if (flag == 0) {
					flag = 1;
					if (isPalindrome(s, ++min, max) == false && isPalindrome(s, --min, --max) == false) {
						return false;
					}
					else
						return true;
				}
				else {
					return false;
				}
			}
		}
		return true;
	}
	bool validPalindrome(string s) {
		int min = 0, max = s.length() - 1;
		if (isPalindrome(s, min, max)) {
			return true;
		}
		return false;
	}
};

524.通过删除字母匹配到字典里最长单词(难度:中等)

  • 本题代码比较复杂,但是思路清晰;
  • 首先用和字典一样大小的num数组,存储给定数组中每个字符串是否可通过给定字符串删除字母得到,若可以,用num数组记录给定数组中每个字符串的长度,若匹配不到,该长度为0;
  • 之后通过*max_element()函数找到num数组中的最大值,然后遍历给定数组,若某字符串长度是最大值,则用max_return、dictionary_return记录该点,并用first记录第一个遍历到的最长单词,之后跳出循环;
  • 接着从该点的下一点开始,继续便利给定数组,如果再次找到相同长度的单词,就用strcmp()函数进行比较,如果已记录的单词字典序大于这次找到的单词字典序,则将dictionary_return更新为这次找到的单词的下标,然后first更新为这次找到的单词,继续遍历;
  • 最后判断如果num记录的最大值大于0,说明匹配到了单词,可以返回dictionary_return记录的下标,否则返回空;
  • 代码如下:
class Solution {
public:
    string findLongestWord(string s, vector<string>& dictionary) {
        vector<int> num(dictionary.size(),0);
        for (int i = 0;i < dictionary.size();i++) {
            int j = 0,first = 0;
            while (j < dictionary[i].length() && first < s.length()) {
                if (s[first] != dictionary[i][j]) {
                    first++;
                }
                else {
                    first++;
                    j++;
                    num[i]++;
                }
            }
            if (j < dictionary[i].length()) {
                num[i] = 0;
            }
        }
        int max = *max_element (num.begin() , num.end());
        string first,sencend;
        int i = 0,dictionary_return;
        int max_return;
        for (i = 0;i < dictionary.size(); i++) {
            if (num[i] == max) {
                max_return = i;
                dictionary_return = i;
                first = dictionary[i];
                break;
            }
        }
        while (i < dictionary.size()) {
            if (num[i] == max) {
                sencend = dictionary[i];
                if (strcmp(first.c_str() , sencend.c_str()) > 0) {
                    dictionary_return = i;
                    first = dictionary[i];
                }
            }
            i++;
        }
        if (num[max_return] > 0) {
            return dictionary[dictionary_return];
        }
        return "";
    }
};

340.最多包含K个不同字符的最长字串(难度:中等)

  • 这题需LeetCode会员才可做,等我改天办个会员再更;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值