平方数之和
分析:
本题可以理解为在0-target的有序数组中查找两个数,使其平方和为target,左指针初始化为0,右指针需要剪枝降低时间复杂度初始化为(int)(target)^0.5,遍历过程中如果平方和大于target则右指针往前移,如果平方和小于target则左指针往后移。
class Solution {
public:
bool judgeSquareSum(int c) {
if(c<0) return false;
long i=0,j = sqrt(c);
while(i<=j){
if(i*i+j*j==c) return true;
else if(i*i+j*j>c) j--;
else i++;
}
return false;
}
};
反转字符串中的元音字符
分析
两个索引值分别位于字符串数组的最前端和最末端,分别向前和向后遍历,遇到元音字母则停下,没遇到元音字母的一端则继续遍历,直到两个指针相遇
class Solution {
public:
void swap(string& s, int i, int j){
char tmp = s[i];
s[i] = s[j];
s[j] = tmp;
}
string reverseVowels(string s) {
if(s.empty()) return s;
int i=0,j=s.length()-1;
string target="aeiouAEIOU";
while(i<j){
if(target.find(s[j]) != string::npos && target.find(s[i]) != string::npos)
{
swap(s,i,j);
i++;j--;
continue;
}
else if(target.find(s[j]) == string::npos && target.find(s[i]) != string::npos)
{
j--;
continue;
}
else if(target.find(s[j]) != string::npos && target.find(s[i]) == string::npos)
{
i++;
continue;
}
else if(target.find(s[j]) == string::npos && target.find(s[i]) == string::npos)
{
j--;i++;
continue;
}
}
return s;
}
};
回文字符串
分析
两个索引值分别位于字符串数组的最前端和最末端,分别向前和向后遍历,遇到相同的字符则跳过,遇到不同的字符需要判断是左边删除一个字符能否构成回文字符串,右边删除一个字符能否构成回文字符串,以此来确定字符串是否满足题意
class Solution {
private:
bool isValid(string s,int i,int j){
while(i<j){
if(s[i++]!=s[j--]) return false;
}
return true;
}
public:
bool validPalindrome(string s) {
int i=0,j=s.length()-1;
while(i<j){
if(s[i] == s[j]){
i++;j--;
}
else{
return isValid(s,i,j-1)||isValid(s,i+1,j);
}
}
return true;
}
};
归并两个有序数组
分析
一开始考虑从前面开始逐个比较然后再插入数据,但这样的就需要很多运行时。其实可以尝试着将两个索引值分别指向两个有序数组的末端,然后往目标数组末端进行逐个数值插入,要是某一个有序数组已经遍历到最前端,此时还不能终止插入,还需将另外一个有序数组的剩余元素也全部插入到目标数组中才算完成插入。
class Solution {
public:
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {
int _m=m-1,_n=n-1,merge=m+n-1;
while(_m>=0||_n>=0){
if(_m<0) nums1[merge--]=nums2[_n--];
else if(_n<0) nums1[merge--]=nums1[_m--];
else if(nums1[_m]>nums2[_n]) nums1[merge--]=nums1[_m--];
else nums1[merge--]=nums2[_n--];
}
}
};
判断链表是否存在环
class Solution {
public:
bool hasCycle(ListNode *head) {
//由于采用了快慢指针,必须要排除快慢指针起始为空的情况
if(head==nullptr || head->next==nullptr) return false;
//快慢指针的出发点不能一样,不然一开始两指针相遇直接判断链表存在环
ListNode* slow=head;
ListNode* fast=head->next;
while(slow!=fast){
if(fast==nullptr || fast->next==nullptr) return false;
slow=slow->next;
fast=fast->next->next;
}
return true;
}
};
最长子序列
class Solution {
private:
bool isMatch(string s,string s_arr){
int i=0,j=0;
for(;i<s.size()&&j<s_arr.size();){
if(s[i]!=s_arr[j]) i++;
else {i++;j++;}
}
return j==s_arr.size();
}
public:
string findLongestWord(string s, vector<string>& d) {
if(d.empty()==true) return "";
//将初始的目标字符串的长度降到最低
//保证首个符合条件的字符串可以保存到s_tmp中
string s_tmp="";
for (int i = 0; i <= d.size() - 1; i++) {
//由于要求返回长度最长的目标字符串,故字符串太短就算匹配也无用
if(d[i].size()<s_tmp.size()) continue;
//若字符串与目标字符串长度相同且满足匹配条件则需看字典排序
else if(d[i].size()==s_tmp.size() && isMatch(s,d[i]) && s_tmp>d[i]) s_tmp=d[i];
//若字符串满足条件且长度大于目标字符串则更新目标字符串
else if(d[i].size()>s_tmp.size() && isMatch(s,d[i])) s_tmp=d[i];
}
return s_tmp;
}
};
剑指offer 22.链表中倒数第k个节点
分析
class Solution {
public:
ListNode* getKthFromEnd(ListNode* head, int k) {
ListNode* low = head;
ListNode* fast = head;
//快指针提前走k步
while(k > 0){
fast = fast->next;
k--;
}
//快慢指针同时出发
while(fast != nullptr){
low = low->next;
fast = fast->next;
}
return low;
}
};