后来再看题目发现要求是常数空间复杂度,但是实际上mergesort也过了,也可能是只加了一个数组的缘故。
qsort其实比mergesort在链表上更好实现,但是还是需要便利一遍找tail指针,这次是常数空间,然而却TLE了。。。。
要么是lumoto版本导致比较次数多了,但是hoare真心有点记忆感觉。还是说递归的原因,但是mergesort也是递归都没超时,不解啊。。
另外今天还和高富帅考虑qsort的非递归算法的问题。
void qsort(ListNode* low, ListNode* high)
{
if(low==high || (high!=NULL&&high->next==low)) return;
else
{
int x=0;
ListNode *p=new ListNode(x);
p->next=low;
ListNode *i=p,*j;
for(j=low;j!=high;j=j->next)
{
if(j->val<high->val)
{
i=i->next;
swap(i->val,j->val);
}
}
swap(i->next->val,j->val);
//int tmp=i->next->val;
//i->next->val=j->val;
//j->val=tmp;
//Swap(i->next->val,j->val);
qsort(low,i);
qsort(i->next->next,high);
delete p;
}
}
ListNode* sortList(ListNode* head)
{
if(head==NULL||head->next==NULL) return head;
ListNode*p=head;
while(p->next!=NULL)
p=p->next;
qsort(head,p);
return head;
}
而且里面由于之前从while改成for循环,我又受fwaks大神的影响,习惯了for里面定义变量,变量近一点确实好,但是外面的忘记删了,关键是compiler还不提醒= =于是就悲剧了。。。我还到群里找各路找问题,一直以为不能交换值是因为不是左值,但是那明显是左值。。。
所以代码还是要仔细,还是建议for里面写比较好,变量离得近一点,除非像上面,在loop外还要用,才把他改过来。
另外提到一个二分查找自己的不解,例如找一个元素,如果出现多次,返回index最小的,后来和高富帅讨论,可以找到后加一点判断就可以了,如果左边一个不等mid,就返回,说明一点是最小的index,如果相等,这high=mid-1 这继续找。一定会定位到的。大概是这样,没有严格的证明正确,也没找到OJ的题来测。照这样,找最大index的题目也可以做了,这是编程之美改错题的两小问。
int BinarySearch(int low, int high, double x,double *a)
{
while(low<=high)
{
int mid=(low+high)/2;
if(a[mid]<x)
{
low=mid+1;
}
else if(a[mid]>x)
{
high=mid-1;
}
else
{
if(a[mid-1]!=x)
return mid;
else
{
high=mid-1;
}
}
}
return -1;
}
稍改一下,返回最大index
int BinarySearch(int low, int high, double x,double *a)
{
while(low<=high)
{
int mid=(low+high)/2;
if(a[mid]<x)
{
low=mid+1;
}
else if(a[mid]>x)
{
high=mid-1;
}
else
{
if(a[mid+1]!=x)
return mid;
else
{
low=mid+1;
}
}
}
return -1;
}
另外看了另外两问,返回<x 的最大index,如果x不存在,最后一定是[low, high] 其中high=low+1 从二分的查找树可以看出,然后mid=(low+mid)/2=low, 所以返回low-1 或high-1, 如果找得到的话,考虑返回=x的最小index的前一个index,所以上面代码2 while出口加上 return low(high)-1, 然后里面找到case返回,return mid-1。 返回最小的i使得a[i]>v
同理,在代码3按照上述一样修改即可。可惜编程之美没找到答案,然后也没有OJ测。
调整次数: 1*(h-1)+2*(h-2)+2^(h-2)*1=h*(1+2+2^2+...2^(h-2))- (1*1+2*2+2^2*3+...2^(h-2)*(h-1))
后面是等差乘等比,用下公式,前面等比求和,最后算出来 O(2n)=O(n), 其中h~logn), 比算导那么繁琐的好理解。