算法复习:归并排序 & 分治
leetcode 面试题51. 数组中的逆序对
本质上就是归并排序,并在合并区间过程中统计交换的逆序对的数目
归并排序需要开o(n)的辅助空间
class Solution { public: int deal(vector<int>&nums,vector<int>&tmp,int ll,int rr) { if(ll>=rr)//返回条件 return 0; int mid=ll+(rr-ll)/2; int count=deal(nums,tmp,ll,mid)+deal(nums,tmp,mid+1,rr); if(nums[mid]<nums[mid+1])//已经有序不需要再比了 return count; int x=ll,y=mid+1,i; for(i=0;x<=mid&&y<=rr;i++)//合并两个数组到新的数组 { if(nums[x]<=nums[y]) { tmp[i]=nums[x]; x++; } else { tmp[i]=nums[y]; y++; count+=(mid-x+1); } } for(;x<=mid;x++) { tmp[i]=nums[x]; i++; } for(;y<=rr;y++) { tmp[i]=nums[y]; i++; } int yy=ll; for(int k=0;k<i;k++) { nums[yy]=tmp[k]; yy++; } return count; } int reversePairs(vector<int>& nums) { int size=nums.size(); if(size<2) return 0; vector<int>tmp(size,0); return deal(nums,tmp,0,size-1); } };
leetcode 23. 合并K个排序链表
本质上是分治,先将整体分成两两一组,然后逐层合并,利用递归的返回值,典型题目
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* merge(ListNode* L,ListNode* R) { if(L==nullptr) return R; if(R==nullptr) return L; if(L->val<=R->val) { L->next=merge(L->next,R); return L; } else { R->next=merge(L,R->next); return R; } } ListNode* merge_main(vector<ListNode*>& list,int start,int end) { if(start==end) return list[start]; int mid=(start+end)/2; ListNode* left=merge_main(list,start,mid); ListNode* right=merge_main(list,mid+1,end); return merge(left,right); } ListNode* mergeKLists(vector<ListNode*>& lists) { if(lists.size()==0) return nullptr; return merge_main(lists,0,lists.size()-1); } };
参考 leetcode 剑指 Offer 25. 合并两个排序的链表
/** * Definition for singly-linked list. * struct ListNode { * int val; * ListNode *next; * ListNode(int x) : val(x), next(NULL) {} * }; */ class Solution { public: ListNode* mergeTwoLists(ListNode* L, ListNode* R) { if(L==nullptr) return R; else if(R==nullptr) return L; if(R->val<=L->val) { R->next=mergeTwoLists(L,R->next); return R; } else { L->next=mergeTwoLists(L->next,R); return L; } } };