学习大纲
背向双指针:longest palindromic substring 中心线枚举算法, find k cloest elements
相向双指针:1、reverse 2、two sum 3、partition:quick select, 分两部分,分三部分
同向双指针:滑动窗口、快慢指针
相向双指针
1、reverse
三部翻转法
valid palindrome:给定一个字符串,判断其是否为一个回文串。只考虑字母和数字,忽略大小写。
class Solution {
public:
/**
* @param s: A string
* @return: Whether the string is a valid palindrome
*/
bool isPalindrome(string &s) {
for (int i = 0, j = s.size() - 1; i < j; i++, j--) {
while (!isdigit(s[i]) && !isalpha(s[i]) && i < j)
i++;
while (!isdigit(s[j]) && !isalpha(s[j]) && i < j)
j--;
if (i < j && tolower(s[i]) != tolower(s[j]))
return false;
}
return true;
}
};
给一个非空字符串 s,你最多可以删除一个字符。判断是否可以把它变成回文串。
可以在遇到不相同时左或右指针移动一格
class Solution
{
public:
bool validPalindrome(string s)
{
int left = 0, right = s.size() - 1;
while (left < right)
{
if (s[left] != s[right])
return isValid(s, left, right - 1) || isValid(s, left + 1, right);
++left;
--right;
}
return true;
}
bool isValid(string s, int left, int right)
{
while (left < right)
{
if (s[left] != s[right])
return false;
++left;
--right;
}
return true;
}
};
2、two sum 类
只能用hashmap
设计b并实现一个 TwoSum 类。他需要支持以下操作:add 和 find。
add -把这个数添加到内部的数据结构。
find -是否存在任意一对数字之和等于这个值
class TwoSum {
public:
/**
* @param number: An integer
* @return: nothing
*/
void add(int number) {
++m[number];
}
bool find(int value) {
for (auto a : m) {
int t = value - a.first;
// 如果找的value-当前值的差能在map中找到,返回true。
if ((t != a.first && m.count(t)) || (t == a.first && a.second > 1)) {
return true;
}
}
return false;
}
private:
unordered_map<int, int> m;
};
给定一个已经 按升序排列 的数组,找到两个数使他们加起来的和等于特定数。
函数应该返回这两个数的下标,index1必须小于index2。注意返回的值不是 0-based。
使用双指针
class Solution {
public:
/**
* @param nums: an array of Integer
* @param target: target = nums[index1] + nums[index2]
* @return: [index1 + 1, index2 + 1] (index1 < index2)
*/
vector<int> twoSum(vector<int> &nums, int target) {
int i=0; int j=nums.size()-1;
vector<int> output;
if(!j) return output;
while(i<j){
if(nums[i]+nums[j]<target) {
i++;
}
else if(nums[i]+nums[j]>target){
j--;
}
else{
output.push_back(i+1);
output.push_back(j+1);
return output;
}
}
return output;
}
};
给一整数数组, 找到数组中有多少组 不同的元素对 有相同的和, 且和为给出的 target 值, 返回对数.
class Solution {
public:
/**
* @param nums an array of integer
* @param target an integer
* @return an integer
*/
int twoSum6(vector<int> &nums, int target) {
// Write your code here
int n = nums.size(), cnt = 0;
sort(nums.begin(), nums.end());
int l = 0, r = nums.size() -1;
while (l < r) {
if (nums[l] + nums[r] == target) {
cnt ++;
l ++, r --;
while (l < r && nums[r] == nums[r + 1])
r --;
while (l < r && nums[l] == nums[l - 1])
l ++;
} else if (nums[l] + nums[r] > target) {
r --;
} else {
l ++;
}
}
return cnt;
}
};
给出一个有n个整数的数组S,在S中找到三个整数a, b, c,找到所有使得a + b + c = 0的三元组。
其实也是two sum 问题,循环讨论a就行
class Solution {
public:
/**
* @param numbers : Give an array numbers of n integer
* @return : Find all unique triplets in the array which gives the sum of zero.
*/
vector<vector<int> > threeSum(vector<int> &nums) {
vector<vector<int> > result;
sort(nums.begin(), nums.end());
for (int i = 0; i < nums.size(); i++) {
// 可以先去重
if (i > 0 && nums[i] == nums[i - 1]) {
continue;
}
// two sum;
int start = i + 1, end = nums.size() - 1;
int target = -nums[i];
while (start < end) {
if (start > i + 1 && nums[start - 1] == nums[start]) {
start++;
continue;
}
if (nums[start] + nums[end] < target) {
start++;
} else if (nums[start] + nums[end] > target) {
end--;
} else {
vector<int> triple;
triple.push_back(nums[i]);
triple.push_back(nums[start]);
triple.push_back(nums[end]);
result.push_back(triple);
start++;
}
}
}
return result;
}
};
给定一个整数数组,在该数组中,寻找三个数,分别代表三角形三条边的长度,问,可以寻找到多少组这样的三个数来组成三角形?
思路:先排序,再对i做循环,讨论j和k,k从i+2开始增加,当i+j<=k&&k<len时,个数增加k-j-1个。此时只需要j+1,k从当前位置继续去增加!
class Solution {
public:
/**
* @param S: A list of integers
* @return: An integer
*/
int triangleCount(vector<int> &S) {
if (S.size() < 3) return 0;
sort(S.begin(), S.end());
int result=0;
for (int i = 0; i < S.size()-2; i++) {
int k = i+2;
for(int j=i+1;j<S.size()-1;j++){
while(k<S.size()&&S[i] + S[j] > S[k]){
k++;
}
result+=k-j-1;
}
}
return result;
}
};
partition array划分阵列,可以用快速排序
class Solution {
public:
int partitionArray(vector<int> &nums, int k) {
int i = 0, j = nums.size() - 1;
while (i <= j) {
while (i <= j && nums[i] < k) i++;
while (i <= j && nums[j] >= k) j--;
if (i <= j) {
int temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
i++;
j--;
}
}
return i;
}
};
quick select
大致上与快速排序相同
#include <stdio.h>
#include <vector>
#include <algorithm>
using namespace std;
class Solution
{
public:
int findKthLargest(vector<int> &nums, int k)
{
int result = 0;
int numsSize = int(nums.size());
if (numsSize == 0 || k > numsSize)
{
return 0;
}
//寻找第kMIN小的数
int kMin = numsSize - k + 1;
result = select(nums, 0, numsSize - 1, kMin);
return result;
}
int select(vector<int> &nums, int left, int right, int target)
{
if (left == right)
{
return nums[left];
}
int cut = partition(nums, left, right);
//当前第currentResult小的元素
int currentResult = cut - left + 1;
if (target == currentResult)
{
return nums[cut];
}
else if (target < currentResult)
{
return select(nums, left, cut - 1, target);
}
else
{
//寻找接下来第target - currentResult小的数
return select(nums, cut + 1, right, target - currentResult);
}
return 0;
}
int partition(vector<int> &nums, int left, int right)
{
int cut = nums[right];
//i指向大堆的最左边的数,j指向下一个判断的数
int i = left;
for (int j = left; j < right; j++)
{
if (nums[j] <= cut)
{
exchange(nums[i], nums[j]);
i++;
}
}
exchange(nums[i], nums[right]);
return i;
}
void exchange(int &a, int &b)
{
int tmpInt = a;
a = b;
b = tmpInt;
return;
}
};
作者:pinku-2
链接:https://leetcode-cn.com/problems/kth-largest-element-in-an-array/solution/shu-zu-zhong-de-di-kge-zui-da-yuan-su-cshi-xian-sa/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
286

被折叠的 条评论
为什么被折叠?



