五、双指针
-
剑指18,删除链表的节点
//时间O(n),空间O(1) //基本操作,情况要考虑清楚 class Solution { public: ListNode* deleteNode(ListNode* head, int val) { if(!head) return nullptr; if(head->val == val) return head->next; auto cur = head->next; auto pre = head; while(cur) { if(cur->val == val) { pre->next = cur->next; break; }; pre = cur; cur = cur->next; } return head; } };
-
剑指21,奇数在前,偶数在后
//时间O(n),空间O(1) //基本操作,快速排序中的一部分 class Solution { public: vector<int> exchange(vector<int>& nums) { int i = 0; int j = nums.size()-1; while(i < j) { while(i < j && nums[i]%2 == 1) ++i; while(i < j && nums[j]%2 == 0) --j; swap(nums[i],nums[j]); } return nums; } };
-
剑指22,链表中倒数第k个节点
//时间O(n),空间O(1) //一次遍历,cur先走k步,pre=head,然后一起走直到cur指向nullptr,pre所指即为倒数第k个节点 class Solution { public: ListNode* getKthFromEnd(ListNode* head, int k) { if(!head) return nullptr; auto cur = head; for(int i=0;i<k;++i) { cur = cur->next; } auto pre = head; while(cur) { cur = cur->next; pre = pre->next; } return pre; } };
-
剑指25,合并两个排序链表
//时间O(m+n),空间O(1) //感觉写的又臭又长,虽然都能写出来 class Solution { public: ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) { ListNode* head1 = new ListNode(-1); ListNode* head2 = new ListNode(-1); ListNode* phead = new ListNode(-1); head1->next = l1; head2->next = l2; auto plast = phead; ListNode* p = nullptr; //1 while(head1->next && head2->next) { if(head1->next->val < head2->next->val) { p = head1->next; head1->next = p->next; } else { p = head2->next; head2->next = p->next; } plast->next = p; p->next = nullptr; plast = plast->next; } //2 if(!head1->next && head2->next) { plast->next = head2->next; } //3 if(head1->next && !head2->next) { plast->next = head1->next; } return phead->next; } };
-
剑指52,两个链表的第一个公共节点
//时间O(n),空间O(1) //head1走完走head2,head2走完走head1,如果相遇就是第一个公共节点,如果没有,返回nullptr class Solution { public: ListNode *getIntersectionNode(ListNode *head1, ListNode *head2) { if(!head1 || !head2) return nullptr; auto p1 = head1; auto p2 = head2; int cnt1 = 0; while(p1 != p2) { p1 = p1->next; if(!p1 && cnt1 == 0) { p1 = head2; ++cnt1; } else if(!p1 && cnt1 == 1) { return nullptr; } p2 = p2->next; if(!p2) p2 = head1; } return p1; } };
-
剑指57,和为s的两个数字
//时间O(n),空间O(1) //此题为升序,因此使用对撞指针即可 //若为无序,需要使用哈希表,空间复杂度为O(n) class Solution { public: vector<int> twoSum(vector<int>& nums, int target) { if(nums.size() <= 1) return {}; int i = 0; int j = nums.size()-1; int sum; while(i < j) { sum = nums[i] + nums[j]; if(sum == target) { return {nums[i],nums[j]}; } else if(sum < target) { ++i; } else { --j; } } return {}; } };
-
剑指58,翻转单词顺序
//时间O(n),空间O(n) //简单,但是有许多点需要注意 class Solution { public: string reverseWords(string s) { string str; auto iter2 = s.crbegin(); for(auto iter1 = s.crbegin();iter1 != s.crend();++iter1) { if(*iter1 == ' ') continue; iter2 = iter1; while(iter1 != s.crend() && *iter1 != ' ') { ++iter1; } str.append(iter1.base(),iter2.base()); str.push_back(' '); //--防止下一次*iter1越界访问 --iter1; } //只有非空的str才能erase if(!str.empty()) str.erase(str.size()-1); return str; } };