二分写法很多,很容易写错,以后就固定下面的这种写法。
首先二分的区间定为[x,y),然后mid值取下界x+(y-x)/2,循环条件是x<y。这样的好处是退出时x=y,有些问题里不用考虑是返回x还是y;而且在有些问题中,比如说插入的位置,可能会需要返回y这个位置。去下界是必须的,否则会访问到不在查询区间y位置。最后是剪短区间的地方,这个地方写错经常会导致死循环。由于选的mid是下界,mid不会等于y,所以不会出现[x,mid]=[x,y]的死循环情况,为了避免[mid,y]=[x,y]的情况,x更新的时候更新成x=mid+1。下面以递增序列为例写几种常见的二分。
1需要返回value所在上限的下一个位置,或者如果不存在value返回大于value的第一个位置。
1 while(x < y) 2 { 3 mid = x + (y - x) / 2; 4 if(num[mid] > value) y = mid; 5 else x = mid + 1; 6 }
2需要返回value所在的下限的位置,或者大于value的第一个位置。
1 while(x < y) 2 { 3 mid = x + (y - x) / 2; 4 if(num[mid] >= value) y = mid; 5 else x = mid + 1; 6 }
在回忆最长递增序列的nlogn写法时,要求在更新D[k]即最长递增值为k的最小元素时,二分找到(很明显D[]数组是递增的)其新元素插入的位置,然后就发现二分一直写的很撮。。。