1->合并两个有序数组
void Merge(int A[],int m,int B[],int n){
int ia=m-1,ib=n-1,icur=m+n-1;
while(ia>=0 && ib>=0){
A[icur--]=A[ia]>=B[ib]?A[ia--]:B[ib--];
}
while(ib>=0){A[icur--]=B[ib--];}
}
2->合并两个有序的链表
ListNode *mergeTwoLists(ListNode *l1,ListNode* l2){
if(l1==NULL) return l2;
if(l2==NULL) return l1;
ListNode dummy(-1); //辅助链表头结点
ListNode* p=&dummy;
for(;l1!=NULL&&l2!=NULL;p=p->next){
if(l1->val>l2->val){p->next=l2; l2=l2->next;}
else{p->next=l1; l1=l1->next;}
}
p->next=l1!=NULL?l1:l2;
return dummy.next;
}
3->合并K个已经排序好的链表
解题方法:先写出合并两个链表的程序,用循环逐个合并两个链表
ListNode *mergeTwoLists(ListNode* l1,ListNode *l2){
ListNode head(-1); //辅助头结点
ListNode* p=&head;
for(;l1!=NULL &&l2!=NULL;p=p=>next){
if(l1>val<l2->val){p->next=l1; l1=l1->next;}
else {p->next=l2;l2=l2->next;}
}
p->next=l1!=NULL?l1:l2;
return head->next;
}
ListNode *mergeKLists(vector<ListNode *> &lists){
if(lists.size()==0) return NULL;
ListNode *p=lists[0];
for(int i=1;i<lists.size();i++){
p=mergeTwoLists(p.lists[i]);
}
return p;
}
4->采用插入法排序一个链表
解题方法:插入法排序,基本思想选取一个结点,找到要插入的位置,将结点插入即可
ListNode* findInsertPos(ListNode *head,int x){ //查找要插入的位置的前一个结点
ListNode *pre=NULL;
for(ListNode* cur=head;cur!=NULL;cur=cur->next){
if(cur->val<=x) {pre=cur; continue;}
else break;
}
retun pre;
}
ListNode *insertionSortList(ListNode* head){
ListNode dummy(INT_MIN); //辅助头结点
for(ListNode *cur=head;cur!=NULL;){
ListNode *pre=findInsertPos(dummy,cur-val);
ListNode *tmp=cur->next;
cur->next=pre->next; pre->next=cur; cur=tmp;
}
return dummy.next;
}
6->在O(nlogn)的时间内排序一个链表
解题方法:这一可以用归并算法实现,假若链表是双向链表则可以采用快排的实现方式
ListNode *mergeTwoLists(ListNode* l1,ListNode *l2){
ListNode dummy(-1);
ListNode*p=&dummy;
for(;l1!=NULL &&l2!=NULL;p=p->next){
if(l1->val<l2->val){p->next=l1; l1=l1->next;}
else{p->next=l2;l2=l2->next;}
}
p->next=l1!=NULL?l1:l2;
return dummy.next;
}
ListNode* sortList(ListNode *head){
if(head==NULL ||head->next==NULL) return head; //只有一个结点或者是空链表就没有必要排序
ListNode *fast=head,*slow=head; //两个指针,作用将链表分成两段再进行归并
while(fast->next!=NULL && fast->next->next!=NULL){
fast=fast->next->next; slow=slow->next; //fast指针遍历的速度是slow指针的两倍,所以当fast指针达到链表尾巴的时候,slow达到链表的中部
}
fast=slow; slow=slow->next; fast->next=NULL; //将链表从中间断开
ListNode *l1=sortList(head); ListNode *l2=sortList(slow);
return mergeTwoLists(l1,l2);
}
6->在O(n)的时间内找到一个无序数组的第一个缺失的数值
解题方法:要找到连续数列的第一个断点,正常的思想是先排序,然后遍历数组,然而常见的排序算法快排的时间复杂度较低,需要O(nlogn)不符合题目的要求,又由于题目中主要涉及整数,所以可以采用桶排序算法
7->一个数组中只包含0,1,2三个数字,要求O(n)将这个数组排序
解题方法:计数排序
void sortColors(int A[],int n){
int count[3]={0};
for(int i=0;i<n;i++) count[A[i]]++;
for(int i=0,index=0;i<3;i++)
for(int j=0;j<count[i];j++) A[index++]=i;
}
8->在O(logn)的时间内在一个已经排序的数组内找出给定值的开始和结束位置,该值在数组中可能出现不只一次
解题方法:已经排序好了,那么用二分查找就可以使时间复杂度达到O(logn),先采用2分查找定位到目标数值,然后用左右扩展的方式找到起始和结束的位置
vector<int> searchRange(int A[],int n,int target){
int low=0,high=n-1;
vector<int> ret;
while(low<=high){
int mid=(low+high)/2;
if(A[mid]==target) {low=mid; break;}
if(A[mid]>target) high=mid-1;
else low=mid+1;
}
if(low>high) {ret.push_back(-1);ret.push_back(-1); return ret;}
high=low;
while(low>=0&& high<n&&(A[low]==target || A[high]==target)){
if(A[low-1]==target) low--;
if(A[high+1]==target) high++;
}
ret.push_back(low+1,high-1); return ret;
}
10->一个已经排序的数组,一个目标数组若存在这个数组中,返回在数组中的位置,否则返回应该插入的位置
int lower_bound(int A[],int n,int target){ //二分查找,若吧存在则返回应当插入的
int low=0,,high=n;
while(low!=high){
int mid=(low+high)/2;
if(target>A[mid]) low=mid+1;
else high=mid;
}
return low;
}