Search code examples
c++algorithmbinary-search

UVA 10077 - Why is it Binary search?


I am trying to get better in CP. I came across this problem - Link. While I had a naive BFS solution in mind O(2^N) it obviously gave me a TLE.

string bfs(int t1,int t2)
{
    queue<pair<VII,string>> st;
    st.push({{0,1,1,2,1,1},"L"});
    st.push({{1,1,2,1,1,0},"R"});
    while(!st.empty())
    {
        VII u=st.front().first;
        string v=st.front().second;
        st.pop();
        //cout<<u[2]<<' '<<u[3]<<endl;
        if(u[2]==t1 && u[3]==t2)
        return v;
        st.push({{u[0],u[1],u[0]+u[2],u[1]+u[3],u[2],u[3]},v+"L"});
        st.push({{u[2],u[3],u[2]+u[4],u[3]+u[5],u[4],u[5]},v+"R"});
    }
    return "";
}

The above is the code I was able to come up with. I am aware that there is binary search solution, But I could not understand how to divide the search space. It would be great if anybody could explain me the intuition behind this. Thank you!


Solution

  • You're trying to find the target number in the infinite interval lo=(0,1) hi=(1,0). As the PDF says, you can find the mid-point of the interval by doing mid = (lo[0]+hi[0])/(lo[1]+hi[1]). The decision to go left or right depends on the comparison of mid and your target number. If you go left, you emit a L and start searching in the interval lo=lo hi=mid. If you go right, you emit a R and start searching in the interval lo=mid hi=hi. Repeat until mid == target.

    Here's a quick solution in Python:

    from fractions import Fraction
    def walk(lo, hi, tgt):
        mid = (lo[0] + hi[0], lo[1] + hi[1])
        fmid = Fraction(mid[0], mid[1])
        if tgt == fmid:
            return
        if tgt < fmid:
            yield 'L'
            yield from walk(lo, mid, tgt)
        else:
            yield 'R'
            yield from walk(mid, hi, tgt)
    
    print(list(walk((0,1), (1,0), Fraction(878, 323))))