双指针篇

简单

验证回文串

leetcode直达

class Solution {public:bool isPalindrome(string s) {int left = 0;int right = s.size() - 1;while (left <= right) {while (!isalnum(s[left]) && left<right) {left++;}while (!isalnum(s[right]) && left<right) {right--;}if (s[left] != s[right] && toupper(s[left]) != toupper(s[right])) {return false;}left++;right--;}return true;}
};

成绩:86.71 64.39
思路:
采用双指针
left指针从左向右遍历,right指针从右向左遍历,当left大于right时跳出循环
当left所指字符非字母或数字时,往后遍历,直到找到字母或数字;
right同理,不同的地方只有往前遍历;
当left和right均找到字母或数字时,对两者进行比较,若符合要求,继续遍历;反之,跳出并返回false。

只出现一次的数字

leetcode直达

class Solution {public:int singleNumber(vector<int>& nums) {int res = 0;for (int i : nums) {res = res ^ i;}return res;}
};

成绩:94.17 69.79
思路:
这题吧,想到用异或就很简单,想不到异或感觉用哈希表也不难。
能想到异或主要是看了提示:位运算 数组。
反正按照我一开始的思路,遍历数组所有元素,用哈希表存储并统计(数组元素作为键,个数作为值),最后找到值为1的键输出即可。
还有一种就是用位运算的异或:两个位相同为0,相异为1;这意味着什么,意味着异或能够消去两个相同的数字。那和这题不就对上了么。除了需要得到的只出现一次的数字,其余出现两次的数字都会被消去。

环形链表

leetcode直达

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {public:bool hasCycle(ListNode *head) {if(!head) return false;ListNode *fast = head;ListNode *slow = head;while(fast->next && fast->next->next){if(fast->next->next == slow->next){return true;}else{fast=fast->next->next;slow=slow->next;}}return false;}
};

成绩:94 28
思路:
想象一下你们学校开运动会,当碰到3000米这种项目时,是不是就会有套圈的现象出现。究其原因时套圈的跑得快,被套圈的跑得慢。这题就用了这样的思想。
设置快慢两个指针。快指针一次走两个节点,慢指针一次走一个节点。
如果该链表没有环,那么快指针会走到头。
如果有环,那么快指针和慢指针都会进入环(跑道),在跑几次后,慢指针会被快指针追上,此时就能说明该链表有环。
至于为什么要选取走一个节点和走两个节点,因为比较简单。其他选取方案可能会更快,到时候想想。

相交链表

leetcode直达

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode(int x) : val(x), next(NULL) {}* };*/
class Solution {public:int getLength(ListNode *head){int length = 0;while(head){length++;head=head->next;}return length;}ListNode *getIntersectionNode(ListNode *headA, ListNode *headB) {int lengthA = getLength(headA);int lengthB = getLength(headB);int distract = abs(lengthA-lengthB);if(lengthA>lengthB){while(distract--){headA = headA->next;}}else{while(distract--){headB = headB->next;}}while(headA && headA!=headB){headA = headA->next;headB = headB->next;}return headA;}
};

成绩:58 95
思路:
这个题就很难受,也没用到啥技巧,就是经过一遍遍历,统计两条链表的长度,长的那条先走差值个节点,使两条链表的头节点在统一逻辑位置,然后往后遍历就可以。
当两个头节点遍历到同一节点(说明有交叉)或遍历到结尾(说明无节点)时,就返回其中一个头节点即可。
明天看看官方题解。

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

leetcode直达

class Solution {public:vector<int> twoSum(vector<int>& numbers, int target) {int left = 0;int right = numbers.size()-1;while(left<right){if(numbers[left]+numbers[right]<target){left++;}else if(numbers[left]+numbers[right]>target){right--;}else{return {left+1,right+1};}}return {};}
};

成绩:
思路:
按照leetcode第一题那么做肯定也可以,但是没有用到非降数组的性质。
一左一右两个指针;
若当前所指两数大于target,右指针左移;
若当前所指两数小于target,左指针右移。
直至找到(题中所示为必定找到)和为target的两数。

回文链表

leetcode直达

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {public:bool isPalindrome(ListNode* head) {int count = 0;stack<int> stack;ListNode* cur = head;while(head){ //统计总节点数count++; head = head->next;}int half = count/2;while(half--){ //前半进栈stack.push(cur->val);cur = cur->next;}if(count%2 == 1) cur = cur->next; //奇数位就跳过中间位while(cur){if(cur->val != stack.top()) return false;else{stack.pop();cur = cur->next;}}return true;}
};

成绩:43.48 43.82
思路:
把前一半节点先进栈
若为奇数个节点,则跳过中间节点
对后半节点进行遍历,若当前节点和栈顶元素不相等,则说明非回文链表,返回false;
若遍历完所有节点,说明为回文链表,返回true。
上述方法是用栈做的,但是毕竟最近在集中做双指针的题,所以用双指针再做一遍

移动零

leetcode直达
思路一:

class Solution {public:void moveZeroes(vector<int>& nums) {int right = 0;int left = 0;while(right<nums.size()){if(nums[right]){nums[left++] = nums[right];}right++;}while(left<nums.size()){nums[left++] = 0;}}
};

成绩:43 85.8
思路:
快慢指针:慢指针指向已完成排列字段末尾(即待插入的位置),快指针指向下一个非零元素(即需要往前插入的元素)。
当快指针便利到末尾时,说明往前插值已经完成了。开始移动慢指针,将最后元素均变为零。

思路二:
思路:不同于思路一的往前插值,思路二直接将非零元素和零元素互换(其实就是将快指针指向的元素直接赋0),这样能省去最后换0的过程,能快一些。

反转字符串

leetcode直达

class Solution {public:void reverseString(vector<char>& s) {int left = 0;int right = s.size()-1;while(left<right){swap(s[left++], s[right--]);}}
};

成绩:87.4 18.4
思路:
这个就很简单,左右指针换就行,这么简单的题放这么后面。

反转字符串中的元音字母

leetcode直达

class Solution {public:bool judge(char s){string w = "aeiouAEIOU";if(w.find(s) != string::npos) return true; //找到了,说明是元音else return false;}string reverseVowels(string s) {int left = 0;int right = s.length()-1;while(left<right){if(judge(s[left]) && judge(s[right])){swap(s[left++], s[right--]);}else if(!judge(s[left])) left++;else if(!judge(s[right])) right--;}return s;}
};

成绩:5.8 100
思路:
和上一题夜没差,无非多了个找元音字母的步骤。
这里想讲讲的是判断元音的judge函数中的下述代码

string w = "aeiouAEIOU";
if(w.find(s) != string::npos) return true; //找到了,说明是元音
else return false;

这里面的string::npos指的是string的结束位置。和find一起用的作用就是检查给定字符s是否在给定字符串w里。
类似于python里的in操作。

两个数组的交集

leetcode直达

思路一

class Solution {public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {unordered_set<int> hash;for(int num : nums1){hash.insert(num);}vector<int> res;for(int num : nums2){if(hash.count(num) > 0){if(!count(res.begin(),res.end(),num)){res.push_back(num);}}}return res;}
};

成绩:89.69 80.58
思路:
拿哈希表做就很简单,把其中一个数组存入哈希表,然后遍历另一数组,检查当前元素是否在哈希表中。若在,则说明为相交元素,存入res数组;反之,则说明非相交数组,继续遍历。
有一点要说明,从实例中可以看出,相同相交元素只存一个,所以在存入res数组前还需要检查是否已存在。

思路二:

class Solution {public:vector<int> intersection(vector<int>& nums1, vector<int>& nums2) {sort(nums1.begin(),nums1.end());sort(nums2.begin(),nums2.end());int key1 = 0; int key2 = 0;vector<int> res;while(key1<nums1.size()&&key2<nums2.size()){if(nums1[key1] == nums2[key2]){if(res.size() == 0 || nums1[key1] != res.back()){res.push_back(nums1[key1]);}key1++;key2++;}else if(nums1[key1] > nums2[key2]){key2++;}else if(nums1[key1] < nums2[key2]){key1++;}}return res;}
};

成绩:51.24 89.41
思路:
双指针,key1指nums1,key2指nums2;
先对两数组进行排序;
若当前所指两数相同且为存入res,则存入res;
若不相同,所指数较小的指针后移。

两个数组的交集

class Solution {public:vector<int> intersect(vector<int>& nums1, vector<int>& nums2) {sort(nums1.begin(),nums1.end());sort(nums2.begin(),nums2.end());int key1 = 0; int key2 = 0;vector<int> res;while(key1<nums1.size()&&key2<nums2.size()){if(nums1[key1] == nums2[key2]){res.push_back(nums1[key1]);key1++;key2++;}else if(nums1[key1] > nums2[key2]){key2++;}else if(nums1[key1] < nums2[key2]){key1++;}}return res;}
};

成绩:88.27 95.41
思路:
这题用先排序再双指针遍历的办法会好做很多,因为同时遍历的情况下,能够被对应上的相交元素一定是按照数量较少的数组来对应的,超出的部分是对应不上的。

判断子序列

leetcode直达

class Solution {public:bool isSubsequence(string s, string t) {int keys = 0;int keyt = 0;int slen = s.size();int tlen = t.size();while(keyt < tlen){if(s[keys] == t[keyt]){keys++;}keyt++;}return keys == slen;}
};

成绩:100 90.57
思路:
双指针keys,keyt
对应比较,若两指针所指的字符相同,则一起向后遍历;
反之,则向后遍历主串。
当主串遍历完时,若模式串指针指向模式串末,则说明为子序列;反之,则非子序列。

反转字符串Ⅱ

leetcode直达

class Solution {public:string reverseStr(string s, int k) {int n = s.length();for(int slow = 0;slow<n;slow+=2*k){reverse(s.begin()+slow, s.begin() + min(slow+k, n));}return s;}
};

成绩:9 42.19
思路:
主要是正确定位需要反转字符串的首末位置,其中末位置又因字符长度会有不同(不同情况题里也写了)。其他的就不多说了。

反转字符中的单词Ⅲ

leetcode直达

class Solution {public:string reverseWords(string s) {int n = s.length();int slow = 0;int fast = 0;while(fast<n){while(s[fast] != ' ' && fast < n) fast++;reverse(s.begin()+slow, s.begin()+fast);fast++;slow = fast;}return s;}
};

成绩:70.80 33
思路:快慢指针,抓住单词之间均用空格隔开的特点即可。
慢指针指单词头,快指针找单词结尾后的空格,两指针之间的即为需要反转的单词。
反转其中一个单词后,快指针+1即为下一指针头,慢指针指向快指针位置。重复即可。

验证回文字符串Ⅱ

leetcode直达

class Solution {public:bool judge(string s, int left, int right){while(left<right){if(s[left] != s[right]){return false;}left++;right--;}return 1;}bool validPalindrome(string s) {int left = 0;int right = s.length()-1;while(left < right){if(s[left] != s[right]) break;left++;right--;}return judge(s, left+1, right) || judge(s, left, right-1);}
};

成绩:94.81 8.69
思路:
核心步骤就是跳过第一个不匹配的字符,然后就和最简单的判断回文串步骤一样了;
那么问题就在于怎么跳过第一个不匹配的字符,有两种跳过的情况:
1、多余字符在左半边,则左指针往右跳;
eg.aebcba
2、多余字符在右半边,则右指针往左跳。
跳完这一次之后,若剩余字符串为回文串,则符合题意;反之则说明跳一次不够,不符合题意。

字符的最短距离

leetcode直达

class Solution {public:vector<int> shortestToChar(string s, char c) {int len = s.length();vector<int> res;for(int i = 0;i<len;i++){int left = i;int right = i;while(s[left]!=c && s[right]!=c){if(left>0) left--;if(right<len) right++;}res.push_back(max(abs(i-left),abs(i-right)));}return res;}
};

成绩:100 21
思路:
遍历每一个字符,对当前字符设左右双指针,返回较近c和当前字符距离。
有一点需要注意,可能左指针或右指针在向左向右遍历时,会遍历到字符头和尾,此时就需要处理距离异常的问题。通过下面这行代码就能确保得到最短且正确(某一指针遍历到边界但另一指针仍在找c这一情况)的距离:

res.push_back(max(abs(i-left),abs(i-right)));

翻转图像

leetcode直达

class Solution {public:void reserve(vector<int>& vec){int left = 0;int right = vec.size()-1;while(left<right) swap(vec[left++],vec[right--]);}vector<vector<int>> flipAndInvertImage(vector<vector<int>>& image) {int len = image.size();for(int i=0;i<len;i++){reserve(image[i]);for(int j=0;j<len;j++){image[i][j] ^= 1;}}return image;}
};

成绩:88 40
思路:
这题就没啥可说的,就是模拟,题目有啥要求直接实现就完事儿了。
唯一一点要说的就是“0” 和“1”的替换可以用^(异或)1来完成。

比较含退格的字符串

leetcode直达

class Solution {public:bool backspaceCompare(string s, string t) {stack<int> res1;stack<int> res2;int scur = 0;int slen = s.length();int tcur = 0;int tlen = t.length();while(scur<slen){if(!res1.empty() && s[scur] == '#'){res1.pop();}else if(s[scur] != '#') res1.push(s[scur]);scur++;}while(tcur<tlen){if(!res2.empty() && t[tcur] == '#'){res2.pop();}else if(t[tcur] != '#') res2.push(t[tcur]);tcur++;}return res1 == res2;}
};

成绩:100 15
思路:
两个栈,遇到’#‘且栈非空就pop,非’#'就push。
最后比较两个栈即可。

链表的中间节点

/*** Definition for singly-linked list.* struct ListNode {*     int val;*     ListNode *next;*     ListNode() : val(0), next(nullptr) {}*     ListNode(int x) : val(x), next(nullptr) {}*     ListNode(int x, ListNode *next) : val(x), next(next) {}* };*/
class Solution {public:ListNode* middleNode(ListNode* head) {ListNode* slow;ListNode* fast;slow = fast = head;while(fast && fast->next){slow = slow->next;fast = fast->next->next;}return slow;}
};

成绩:34.46 30.58
思路:
就挺简单的,快慢指针,慢指针一次走一个节点,快指针一次走一个节点。
对于奇数个节点来说,判断条件是一样的,即

while(!fast->next) break;

但如果是偶数个节点,应该有两个中间节点,取第一个和取第二个的判断条件是不一样的;

//取第一个:
while(!fast->next->next) break;
//取第二个
while(!fast->next) break;

按奇偶排列数组

leetcode直达

class Solution {public:vector<int> sortArrayByParity(vector<int>& nums) {int slow = 0;int fast = 0;int numslen = nums.size();while(fast<numslen){if(nums[fast]%2 == 0){swap(nums[slow], nums[fast]);slow++;}fast++;}return nums;}
};

成绩:83.62 49.24
思路:
就是我感觉,我做这类需要按条件前后换的题目,总是下意识的会有这种想法:左指针(慢指针)找到符合条件的那个节点;接着右指针(快指针)找到符合条件的节点;然后两指针所指节点互换。乍一看好像没毛病,但是仔细一琢磨肯定是错了。
这类题,像这题和移动零,其实两题是一个道理,无非前者是换奇偶,后者是换零一。那其实我们不需要去管指针符合什么条件才能换,而是关注应该把谁换上来。比如这题就是把偶数换上来,不需要去管左指针(慢指针)指向的是奇数还是偶数,只需要确保右指针(快指针)当前所指的是偶数即可。这样能达到一种什么效果:左指针左边都是偶数,没有奇数;左指针到右指针之间都是奇数。这就是我们想要的效果。

仅仅反转字母

leetcode直达

class Solution {public:string reverseOnlyLetters(string s) {int left = 0;int right = s.length()-1;while(left<right){if(isalpha(s[left]) && isalpha(s[right])){swap(s[left++], s[right--]);}else if(!isalpha(s[left])) left++;else if(!isalpha(s[right])) right--;}return s;}
};

成绩:100 72.92
思路:很简单,不说了

按奇偶排序数组

leetcode直达

class Solution {public:vector<int> sortArrayByParityII(vector<int>& nums) {int slow = 0;int fast = 0;int len = nums.size();while(fast < len){if(slow%2 == 0){if(nums[fast]% 2 == 0){swap(nums[slow++], nums[fast]);fast = slow;}}else{if(nums[fast]% 2 == 1){swap(nums[slow++], nums[fast]);fast = slow;}}fast++;}return nums;}
};

成绩:9.76 40
思路:
快慢指针,慢指针遍历数组,快指针找对应就数,然后进行替换。其实核心和按奇偶排列数组是一样的,无非是多了两个点(体现在我的代码里):
1、奇偶交替
2、快指针需要被拉回来
但是这样肯定很慢,从成绩里也体现出来了,想想怎么优化。

长按键入

leetcode直达

class Solution {public:bool isLongPressedName(string name, string typed) {int slow = 0;int fast = 0;int namelen = name.length();int typedlen = typed.length();while(slow<namelen || fast<typedlen){if(name[slow] != typed[fast]){slow--;if(slow == -1 || name[slow] != typed[fast]) return false;}slow++;fast++;}if(slow == namelen && fast == typedlen) return true;return false;}
};

成绩:35 76.4
思路:
快慢指针,这是没毛病的
一开始我想的是,用slow指name,用fast之指typed;
若匹配,则fast向右走,直到找到不匹配的位置;
当不匹配时,fast和slow的下一个匹配,直到fast遍历到末尾。
匹配失败的条件就是,当fast找到的下一个不匹配的项和slow的下一个不匹配时,return false。但是当实例3时就会发现不对了,按照这种思路,实例3就是对的。没有考虑到name中又连续相同的两个字符。
说明动fast肯定是不行,那就动slow。两指针均从头开始遍历,若匹配,则均向右走。若不匹配,则slow向左移。为什么要这样,因为长按输出的一定是name里的对应字符,不匹配的的情况要么就是碰到长按输入了;要么就是干脆错了。
为什么第二种可以,因为第二种规避了当name里有连续相同字符,typed有大于连续字符个数的输入时,第一种方法认为typed中的连续字符都是name中对应的第一个字符长按输入造成的

有序数组的平方

leetcode直达

class Solution {public:vector<int> sortedSquares(vector<int>& nums) {for(int i = 0;i<nums.size();i++){nums[i] = nums[i]*nums[i];}sort(nums.begin(),nums.end());return nums;}
};

成绩:87 71
思路:
这题就没啥好说的,平方后排序但是可以借此机会复习一下各种排序。

复写零

leetcode直达
思路1:利用vector的插入和删除操作

class Solution {public:void duplicateZeros(vector<int>& arr){int len = arr.size();int cur = 0;while(cur<len){if(!arr[cur]){arr.pop_back();arr.insert(arr.begin()+cur+1, 0);cur++;}cur++;}}
};

成绩:29 64
思路:
cur指针遍历数组,当当前指向的数字为0时,就删除最后一个元素,并在cur位置插入0;
这样当然和这道题的考察点没关系了,但是能做出来。

思路二:双指针

class Solution {public:void duplicateZeros(vector<int>& arr) {int len = arr.size();int extend = 0;  //需要插入的0的个数int cur = 0;     //当前指针while(extend+cur<len){  if(!arr[cur]){extend++;}cur++;}//跳出,统计结束,从len-extend开始往后duint left = cur-1;int right = len-1;if(cur+extend == len+1){arr[right--] = 0;}while(left>=0){arr[right] = arr[left];if(!arr[left]) arr[--right] = arr[left];left--;right--;}}
};

成绩:92 30
思路:
两次遍历
第一次遍历计算需要插入的0的个数。我的做法是定义一个遍历指针cur和需要插入的0的个数extend,当cur遍历到0时, extend加1;这时候就会遇到一个问题,什么时候停止遍历。停止遍历的点对第二次遍历来说非常重要。我的做法是当extend+cur>=len时,就跳出循环。那么这个时候会有两种情况:
情况一:插入0后长度刚好等于原数组长度
例如10230450
情况二:插入0后长度比原数组长度大1
例如84500007,那么这种情况就需要特殊处理

第二次遍历复制零。从后往前复制,这样就不会出现从前往后复制出现的覆盖问题。设置双指针left,right。left从右往左遍历数组,起始位置为cur。right指向需要插入的位置,对应第一次遍历出现的两种情况,right的起始位置有两种情况:
情况一:从末尾开始;
情况二:将末尾设为0,从倒数第二位开始。
将left指向的数复制到right位置上,两指针同时向前继续遍历。当left所指数为0时,多进行一次复制,即right多移动一次,达成复写0的效果。

删除回文子序列

对这题表示严厉谴责
leetcode直达

class Solution {public:bool palindriom(string s){int left = 0;int right = s.length()-1;while(left<right){if(s[left] != s[right]) return false;left++;right--;}return true;}int removePalindromeSub(string s) {if(s.length() == 0) return 0;if(palindriom(s)) return 1;else return 2;}
};

成绩:100 90.09
思路:
别思路了,太扯了,脑筋急转弯家人们。

检查整数及其两倍数是否存在

leetcode直达

class Solution {public:bool checkIfExist(vector<int>& arr) {for(int num:arr){if(num != 0 && count(arr.begin(), arr.end(), num*2)>0) return true;else if(num == 0 && count(arr.begin(), arr.end(), 0)>1) return true;}return false;}
};

成绩:94 91
思路:
遍历一遍就行,找是否有对应两倍数就行;
这种方法有一个需要特殊处理的情况就是0,0的两倍还是0,会找到自己。把0单独拿出来,当遍历到0时,若数组中0的个数大于1,则返回true;

两个数组间的距离值

leetcode直达
思路一:暴力但不完全暴力

class Solution {public:int findTheDistanceValue(vector<int>& arr1, vector<int>& arr2, int d) {int count = arr1.size();for (int num1 : arr1) {for (int num2 : arr2) {if (abs(num1 - num2) <= d) {count--;break;}}}return count;}
};

成绩:90 28
思路:
如果两个数组中的所有元素都符合题意,那返回的数就是arr1的size。那当arr1中有几个不符合的,就减几个即可。
那按照这个思路,两个for嵌套,最里面if判断;当出现距离不大于给定d的情况,减1。最后返回return即可。
思路2:优化了个寂寞

class Solution {public:int findTheDistanceValue(vector<int>& arr1, vector<int>& arr2, int d) {int max = *max_element(arr2.begin(), arr2.end());int min = *min_element(arr2.begin(), arr2.end());int count = 0;for (int num : arr1) {if (num > max) {if (abs(num - max) <= d) continue;}else if (num < min) {if (abs(num - min) <= d) continue;}else {sort(arr2.begin(), arr2.end());int p = 0;while (p < arr2.size() - 1) {if (arr2[p] <= num && arr2[p + 1] >= num) {break;}p++;}if (abs(num - arr2[p]) <= d || abs(num - arr2[p + 1]) <= d) continue;}count++;}return count;}
};

成绩:不写了,就很低
思路:
加入了比较的环节。
情况一当arr1中当前数比arr2中最大值大时,只需要比较前者与最大值的距离;若两者距离大于d,则arr2中其余数比符合。若两者距离小于d,则当前数不符合要求。
情况二当arr1中当前数比arr2中最小值小时,只需要比较前者与最小值的距离。原因同理;
情况三当arr1中当前数介于arr2最大值和最小值之间时,首先对arr2排序,只要比较arr1当前数与arr2中最靠近当前数的两个数的距离;若均符合距离条件,则其余也符合;反之则不符合,continue。

交替合并字符串

leetcode直达
思路一

class Solution {public:string mergeAlternately(string word1, string word2) {string res;int len1 = word1.length();int len2 = word2.length();res.resize(len1+len2);int key1 = 0;int key2 = 0;int key = 0;while(key1<len1 && key2<len2){res[key++] = word1[key1++];res[key++] = word2[key2++];}while(key1<len1){res[key++] = word1[key1++];}while(key2<len2){res[key++] = word2[key2++];}return res;}
};

成绩:100 8.19
思路:
创建一个数组res,将word1和word2两两字符串中的字符依次写入;若其中一字符串遍历完了,就把另一字符串接在后面即可。
这种方法需要额外创建一个长度为word1+word2长度的空间,可以试试在其中一个数组上进行操作。
思路二

class Solution {public:string mergeAlternately(string word1, string word2) {int len1 = word1.length();int len2 = word2.length();word1.resize(len1 + len2);int key1 = len1 - 1;int key2 = len2 - 1;int cur = len1 + len2 - 1;while (key1 != key2) {if (key1 > key2) word1[cur--] = word1[key1--];else word1[cur--] = word2[key2--];}while (key1 >= 0) {word1[cur--] = word2[key2--];word1[cur--] = word1[key1--];}return word1;}
};

成绩:100 10.92
思路:
在word1上操作,从后往前依次将word1和word2中的字符交叉写入word1对应位置。
这还只有10.92,到时候去看看解析看看还能怎么优化。

反转单词前缀

leetcode直达

class Solution {public:string reverse(string word, int left, int right){while(left<right){swap(word[left++], word[right--]);}return word;}string reversePrefix(string word, char ch) {int cur = 0;int len = word.length();while(cur<len){if(ch == word[cur]) break;cur++;}if(cur == len) return word;return  reverse(word, 0, cur);}

成绩:100 20.13
思路:
先去找word中第一次出现ch的位置;如果能找到,那就替换包括它之前的字符串;
若找不到,说明name中没有ch字符,就原原本本输出即可。

快乐数

leetcode直达

class Solution {public:int func(int n){int sum = 0;while(n>0){sum+=pow(n%10, 2);n = n/10;}return sum;}bool isHappy(int n) {//vector<int> re s = {1, 10, 13, 31, 23, 32, 100, 68, 86, 82, 28, 19, 91 };int count = 50;int temp = n;while(--count){temp = func(temp);if(temp == 1) break;}if(count) return true;return false;}
};

成绩:好久之前写的,时间成绩找不到了,反正不低就是了。
思路:
这题可以去演演算算几个数,可以发现,每位平方和导致的结果是每个数梯度下降(不要在意)的速度非常快。把int范围内9最多的数拿出来,第一次进行各位平方和就下降到了2000左右。再算几个也是这样。我就是抓住了这一点,直接循环各位平方和50此,在这50次里,如果能到1,那说明是快乐数;反之,则不是。其实根本不用50次,可以循环更小的次数。
还有一点,如果一个树不是快乐数,反复进行各位平方和实惠出现循环的,不知道是不是所有非快乐数都是这样,我去查一查。

Leetcode—双指针相关推荐

  1. Leetcode双指针滑动窗口相关题目

    滑动窗口 滑动窗口解决哪种问题? 滑动窗口解决给定两个字符串S和T,问你S中是否存在一个子串,包含T中的所有字符并且不含有其他字符. 窗口右指针向右移动,窗口增大,直到满足条件,这时候找到可行解. 窗 ...

  2. LeetCode——双指针

    双指针 双指针主要用来遍历数组,两个指针指向不同的元素,从而协同完成任务. 目录 有序数组的 Two Sum 两数平方和 反转字符串中的元音字符 回文字符串 归并两个有序数组 判断链表是否存在环 最长 ...

  3. leetcode双指针合集

    27. 移除元素 class Solution {public:int removeElement(vector<int>& nums, int val) {/**思路:使用快慢指 ...

  4. leetcode双指针(python与c++)

    1.字符串的排列 思路:双指针+滑动窗口 python: class Solution:def checkInclusion(self, s1: str, s2: str) -> bool:di ...

  5. leetcode ---双指针+滑动窗体

    一:Minimum Size Subarray Sum(最小长度子数组的和O(N)) 题目: Given an array of n positive integers and a positive ...

  6. leetcode+双指针求最大容积,思维。一左一右指针

    点击打开链接 #include<iostream> #include<stdio.h> #include<stdlib.h> #include<string& ...

  7. 备战秋招 |《百面机器学习》算法+leetcode开班报名!

    算法面试刷题班推荐: 以<百面机器学习>为教材 结合leetcode筛选刷题 秋招已经开始了!时间紧迫,也许别人已经得到offer了,你却还在不知所措?(文末重金招聘讲师) 六月份基本都是 ...

  8. 仅剩3天 | 带学《百面机器学习》葫芦书,算法+leetcode一应俱全

    或许你只要比别人准备多一点,你就可以在群体中脱颖而出. 年后基本都是春招和社招的高峰期,但好岗位招聘人数和应聘人数简直堪比春运抢票. 你总在抱怨"为什么别人机会那么好,能抢到你想要的名额?& ...

  9. 【只推荐一位】文能写诗聊妹,武可搬砖coding~

    今天给大家推荐一个双一流高校在读研究生--小詹,「一个文能写诗撩妹,武可搬砖coding」的程序猿- 可上九天揽月,可下五洋捉鳖!说点题外话,不知道各位看到这句话第一反应是什么? 估计不少人认为是可以 ...

最新文章

  1. php当前日期的时间戳,php – 获取当前的ISO8601日期/时间戳
  2. ESP32-S模块转接板设计与实现
  3. 同时买票是怎么实现的_刷脸进站,语音买票!广州地铁这波操作666~
  4. 向顺序容器vector、string、deque、list、forward_list中插入\删除元素时迭代器、引用、指针的变化
  5. 本地存储localStorage
  6. mysql utf8mb4 bin_MySQL中utf8字符集、排序规则及utf8mb4_bin列大小写不敏感方法
  7. 虚拟机上的linux里安装ngnix,虚拟机(linux)下安装nginx的步骤教程
  8. cartographer探秘第四章之代码解析(五) --- 后端优化 --- 闭环约束1 --- PrecomputationGrid2D
  9. 高德地图如何取消订单_一文教你如何爬取高德地图
  10. Linux系统安装pgp教程,在Linux系统下安装pgpcommandline
  11. 计算机文字录入在线打字,教您如何在一分钟内把书中的文字录入电脑
  12. C4D怎么设置默认工程默认场景?
  13. 我用vc+仿照金山毒霸软件工具界面(创世纪篇)
  14. ChucK初步(8)
  15. ,英式发音和美式发音有什么区别
  16. 如何在vue中优雅的使用ocx控件:结合iframe
  17. STM32-ADC-信号调理电路校准-excel-matlab
  18. 【CodeForces 1255D --- Feeding Chicken】
  19. mysql 查询练习——计算总订单价格大于100的订单号和总订单价格
  20. 安装python虚拟环境,及安装flask方法步骤

热门文章

  1. 2005/4.16/多云转晴
  2. ⑩【图神经网络×自监督×时空】视频自监督学习、时间对比图学习、多尺度时间依赖性(长期、短期) 、频域学习
  3. mysql linux 审计_MySQL审计插件的测试(mcafee和mariadb版本)
  4. ONVIF系列笔记-PTZ的控制
  5. 2022 个人目标日历定作工具 微信小程序源码
  6. 商品增加库存功能,前端页面要求显示表单修改库存(二)
  7. 计算机网页设计学什么软件,想学网页制作,要在电脑中装什么软件啊,哪儿有学习网页制作的知识...
  8. Xcode8.3支持iOS11
  9. HTML中添加点击链接 进行Skype对话的问题
  10. 分享!几招收集信息和数据的方法,阿里,瑞幸资料通通都有