[LEECODE]算法进阶自练习1-2 数组&链表&Map&Set
1.数组、链表
简单
删除排序数组中的重复项 leetcode 26
因为数组中有重复的,所以最终的数据都得往前移动,因此,可以用双指针来解决。
int removeDuplicates(vector<int>& nums) {int nsize = nums.size();if(nsize == 0) return 0;int fast=0, slow=0;for(; fast<nsize; fast++) if(nums[fast] != nums[slow]) nums[++slow] = nums[fast]; // 先++ 后填数字return ++slow; // 这里注意是下标+1的概念}
旋转数组 leetcode 189
最简单的方式是一个一个循环来移动,但是实际上可以将数组看成无限长或者环状的数组,index往后移动k就是(index+k)%nsize (nsize为数组长度);
void rotate(vector<int>& nums, int k) {int nsize = nums.size();vector<int> ret(nsize, 0);for(int i=0; i<nsize; i++) ret[(i+k)%nsize] = nums[i];ret.swap(nums);}
合并两个有序链表 leetcode 21
两个比较大小然后串起来即可,记得处理下最后没有遍历完的链表就行了,这里注意用一个哑元节点可能写代码更好处理一点。
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {ListNode* head = new ListNode(-1);ListNode* dummyHead = head;while(l1 && l2){if(l1->val < l2->val){dummyHead->next = l1;l1 = l1->next;}else{dummyHead->next = l2;l2 = l2->next;}dummyHead = dummyHead->next;}dummyHead->next = l1 ? l1: l2;return head->next;}
合并两个有序数组 leetcode 88
合并两个有序数组和上面合并链表差不多,但是注意合并数组后面处理剩余的尾巴元素的时候是用循环的,和链表不一样的就在这里了。
void merge(vector<int>& nums1, int m, vector<int>& nums2, int n) {vector<int> ret(m+n,0);int i=0, j=0, k=0;while(i<m && j<n) ret[k++] = (nums1[i] < nums2[j]) ? nums1[i++] : nums2[j++];while(i<m) ret[k++] = nums1[i++];while(j<n) ret[k++] = nums2[j++];nums1.swap(ret);}
中等
两两交换链表中的节点 leetcode 24
ListNode* swapPairs(ListNode* head) {if(!head || !head->next) return head;// 1->2->3->4->5 nil// ret: 2->1 3->4ListNode* prev = nullptr;ListNode* ret = nullptr;while(head && head->next){ListNode* node = head;ListNode* next = head->next;ListNode* tmp = head->next->next;if(prev != nullptr) prev->next = next; // 这里是处理每次两个节点翻转之间的连接next->next = node;if(prev == nullptr) ret = next; // 这里要设置头指针prev = node;head = tmp;}prev->next = head != nullptr ? head : nullptr; // 这里一定要注意 如果双数节点要设置下最终链表以nullptr结尾。return ret;}
递归解法:
ListNode* swapPairs(ListNode* head) {if(!head || !head->next) return head;ListNode* node = head, *next = node->next;node->next = swapPairs(next->next);next->next = node;return next;// 1 , 2 , 3}
三数之和 leetcode 15
整体思路是排序后以O(n)的时间复杂度来遍历,但是要注意去重,去重要靠下面两点来保证。
vector<vector<int>> twoSumTarget(vector<int>& nums, int target, int start){vector<vector<int>> ret;int nsize=nums.size(), i=start, j=nsize-1;while(i < j){int left = nums[i], right = nums[j], sum = left + right;if(sum < target) while(i<j && nums[i] == left) i++; // 去重第一点if(sum > target) while(i<j && nums[j] == right) j--; // 去重第一点if(sum == target){ret.push_back({nums[i],nums[j]});while(i<j && nums[i] == left) i++; // 去重第一点while(i<j && nums[j] == right) j--; // 去重第一点}}return ret;}vector<vector<int>> threeSum(vector<int>& nums) {sort(nums.begin(),nums.end());vector<vector<int>> ret;int nsize = nums.size();for(int i=0; i<nsize; i++){vector<vector<int>> tmp = twoSumTarget(nums, 0-nums[i], i+1); // 去重第二点,注意这里有个start。for(auto& x:tmp){x.push_back(nums[i]);ret.push_back(x);while(i<nsize-1 && nums[i] == nums[i+1]) i++;}}return ret;}
2. Map & Set
简单
有效的字母异位词 leetcode 242
这个题目两种做法:1.排序后判断是否相等 2.map字母奇数
bool isAnagram(string s, string t) {sort(s.begin(),s.end());sort(t.begin(),t.end());return s == t;}
bool isAnagram(string s, string t) {int ssize = s.size(), tsize = t.size();if(s.size() != t.size()) return false;map<char,int> mp;for(int i=0; i<ssize; i++){if(mp.count(s[i]) > 0){mp[s[i]]++;}else{mp[s[i]] = 1;}}for(int i=0; i<tsize; i++){if(mp.count(t[i]) > 0){mp[t[i]]--;if(mp[t[i]] == 0){mp.erase(t[i]);}}else{return false;}}return mp.empty();}
中等
字母异位词分组 leetcode 49
利用map<string, vector
vector<vector<string>> groupAnagrams(vector<string>& strs) {vector<vector<string>> ret;map<string, vector<string>> mp;for(auto& str: strs){string tmp = str;sort(tmp.begin(), tmp.end());mp[tmp].push_back(str);}for(map<string, vector<string>>::iterator it = mp.begin(); it != mp.end(); it++){ret.push_back(it->second);}return ret;}
文章转载自小马爸爸的笔记,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




