Lintcode 二分练习

457 经典二分查找问题

https://www.lintcode.com/problem/457

  • 模板一
public class Solution {
    public int findPosition(int[] nums, int target) {
        if (nums == null || nums.length == 0) return -1;

        //输入:nums = [1,2,2,4,5,5], target = 2
        //nums[1...2]这个区间的数字都等于target

        int l = 0, r = nums.length - 1;
        while (l < r) {                             //当循环结束时,l == r
            int mid = l + r + 1 >> 1;
            if (nums[mid] <= target) l = mid;       //用变量l从左向右寻找target,找到的是最右边的下标2
            else r = mid - 1;
        }
        
        if (nums[l] == target) return l;
        else return -1;
    }
}
public class Solution {
    public int findPosition(int[] nums, int target) {
        if (nums == null || nums.length == 0) return -1;

        //输入:nums = [1,2,2,4,5,5], target = 2
        //nums[1...2]这个区间的数字都等于target

        int l = 0, r = nums.length - 1;
        while (l < r) {                             //当循环结束时,l == r
            int mid = l + r >> 1;
            if (nums[mid] >= target) r = mid;       //用变量r从右向左寻找target,找到的是最左边的下标1
            else l = mid + 1;
        }
        
        if (nums[r] == target) return r;
        else return -1;
    }
}
  • 模板二
public class Solution {
    public int findPosition(int[] nums, int target) {
        if (nums == null || nums.length == 0) return -1;

        //输入:nums = [1,2,2,4,5,5], target = 2
        //nums[1...2]这个区间的数字都等于target

        int l = 0, r = nums.length - 1, ans = 0;
        while (l <= r) {                                        //当循环结束时,l == r + 1
            int mid = l + r >> 1;
            if (nums[mid] <= target) {ans = mid; l = mid + 1;}  //用变量ans从左向右寻找target,找到的是最右边的下标2
            else r = mid - 1;
        }
        
        if (nums[ans] == target) return ans;
        else return -1;
    }
}
public class Solution {
    public int findPosition(int[] nums, int target) {
        if (nums == null || nums.length == 0) return -1;

        //输入:nums = [1,2,2,4,5,5], target = 2
        //nums[1...2]这个区间的数字都等于target

        int l = 0, r = nums.length - 1, ans = 0;
        while (l <= r) {                                        //当循环结束时,l == r + 1
            int mid = l + r >> 1;
            if (nums[mid] >= target) {ans = mid; r = mid - 1;}  //用变量ans从右向左寻找target,找到的是最左边的下标1
            else l = mid + 1;
        }
        
        if (nums[ans] == target) return ans;
        else return -1;
    }
}
  • 模板三
public class Solution {
    public int findPosition(int[] nums, int target) {
        if (nums == null || nums.length == 0) return -1;

        //输入:nums = [1,2,2,4,5,5], target = 2
        //nums[1...2]这个区间的数字都等于target

        int l = 0, r = nums.length;                 //左闭右开[l, r)
        while (l + 1 < r) {                         //当循环结束时,l + 1 == r
            int mid = l + r >> 1;
            if (nums[mid] <= target) l = mid;       //用变量l从左向右寻找target,找到的是最右边的下标2
            else r = mid;
        }
        
        if (nums[l] == target) return l;
        else return -1;
    }
}
public class Solution {
    public int findPosition(int[] nums, int target) {
        if (nums == null || nums.length == 0) return -1;

        //输入:nums = [1,2,2,4,5,5], target = 2
        //nums[1...2]这个区间的数字都等于target

        int l = -1, r = nums.length - 1;            //左开右闭(l, r]
        while (l + 1 < r) {                         //当循环结束时,l + 1 == r
            int mid = l + r >> 1;
            if (nums[mid] >= target) r = mid;       //用变量r从右向左寻找target,找到的是最左边的下标1
            else l = mid;
        }
        
        if (nums[r] == target) return r;
        else return -1;
    }
}
  • 模板四(无逻辑可言)
public class Solution {
    public int findPosition(int[] nums, int target) {
        if (nums == null || nums.length == 0) return -1;

        //输入:nums = [1,2,2,4,5,5], target = 2
        //nums[1...2]这个区间的数字都等于target

        int l = 0, r = nums.length - 1;
        while (l + 1 < r) {                        
            int mid = l + r >> 1;
            if (nums[mid] == target) r = mid;
            else if (nums[mid] < target) l = mid + 1;
            else r = mid - 1;
        }
        //循环结束时l = 0, r = 1

        if (nums[l] == target) return l;
        if (nums[r] == target) return r;
        else return -1;
    }
}
447 在大数组中查找
public class Solution {
    public int searchBigSortedArray(ArrayReader reader, int target) {
        int k = 1;
        while (reader.get(k - 1) < target) k *= 2;
        
        int l = 0, r = k - 1;
        while (l < r) {
            int mid = l + r >> 1;
            if (reader.get(mid) >= target) r = mid;
            else l = mid + 1;
        }

        if (reader.get(r) == target) return r;
        else return -1;
    }
}
460 在排序数组中找最接近的K个数
public class Solution {
    public int[] kClosestNumbers(int[] A, int target, int k) {
        int res[] = new int[k];

        int l = 0, r = A.length - 1, ans = -1;
        //目标是寻找 < target的数中最右边一个
        //也就是寻找 <= target - 1的数中最右边一个
        while (l <= r) {                
            int mid = l + r >> 1;
            if (A[mid] <= target - 1) {ans = mid; l = mid + 1;}
            else r = mid - 1;
        }

        int i = ans, j = ans + 1;       //A[i] < target <= A[j]
        for (int t = 0; t < k; t ++) {
            if (i == -1) res[t] = A[j ++];
            else if (j == A.length) res[t] = A[i --];
            else if (target - A[i] <= A[j] - target) res[t] = A[i --];
            else res[t] = A[j ++];
        }
        return res;
    }
}
585 山脉序列中的最大值
public class Solution {
    //并不需要特殊考虑讲义里说的,只有两个数的情况
    public int mountainSequence(int[] nums) {
        if (nums == null || nums.length == 0) return -1;

        int l = 0, r = nums.length - 1;
        while (l < r) {
            int mid = l + r >> 1;

            //从右往左,找满足(nums[mid] > nums[mid + 1])条件的最左边的数
            if (nums[mid] > nums[mid + 1]) r = mid;
            else l = mid + 1;
        }

        return nums[l];
    }
}
public class Solution {
    public int mountainSequence(int[] nums) {
        if (nums == null || nums.length == 0) return -1;

        int l = 0, r = nums.length - 1;
        while (l < r) {
            if (l + 1 == r) return Math.max(nums[l], nums[r]);

            int mid = l + r >> 1;
            if (nums[mid] > nums[mid - 1] && nums[mid] > nums[mid + 1]) return nums[mid];
            else if (nums[mid] > nums[mid - 1] && nums[mid] < nums[mid + 1]) l = mid + 1;
            else r = mid - 1;
        }

        return nums[l];
    }
}
159 寻找旋转排序数组中的最小值
public class Solution {
    public int findMin(int[] nums) {
        if (nums == null || nums.length == 0) return -1;

        int l = 0, r = nums.length - 1, target = nums[r];
        while (l < r) {
            int mid = l + r >> 1;

            //从右往左,找满足(nums[mid] < target)条件的最左边的数
            if (nums[mid] < target) r = mid;
            else l = mid + 1;
        }

        return nums[l];
    }
}
62 搜索旋转排序数组
public class Solution {
    public int search(int[] A, int target) {
        if (A == null || A.length == 0) return -1;

        int l = 0, r = A.length - 1, left = A[l], right = A[r];
        while (l < r) {
            int mid = l + r >> 1;

            if (A[mid] > right) {
                if (left <= target && target <= A[mid]) r = mid;
                else l = mid + 1;
            }
            else {
                if (A[mid] < target && target <= right) l = mid + 1;
                else r = mid;
            }
        }

        if (A[l] == target) return l;
        else return -1;
    }
}
75 寻找峰值
public class Solution {
    public int findPeak(int[] A) {
        int l = 0, r = A.length - 1;

        while (l < r) {
            int mid = l + r >> 1;
            if (A[mid] < A[mid - 1]) r = mid;   //如果满足条件,则左侧一定有山峰
            else l = mid + 1;
        }
        
        return r - 1;
    }
}
183 · 木材加工
public class Solution {
    public int count(int[] L, int x) {
        int res = 0;
        for (int i = 0; i < L.length; i ++) res += L[i] / x;
        return res;
    }

    public int woodCut(int[] L, int k) {
        int l = 1, r = 0;
        for (int i = 0; i < L.length; i ++) r = Math.max(r, L[i]);

        while (l < r) {
            int mid = l + (r - l + 1 >> 1);
            if (count(L, mid) >= k) l = mid;
            else r = mid - 1;
        }
        
        if (count(L, l) < k) return 0;
        else return l;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值