leetcode1755:最接近目标值的子序列和

此题查看范围,不能使用动态规划

而观察发现,数组长度很小,因此使用二分

static class Solution {
    //使用二分
    public int minAbsDifference(int[] nums, int goal) {
        int N = nums.length;
        int M = N >> 1;

        ArrayList<Integer> leftNums = new ArrayList<>();
        ArrayList<Integer> rightNums = new ArrayList<>();
        generateAllNums(leftNums, 0, M, nums, 0);
//            System.out.println(leftNums.size());
//            for (Integer leftNum : leftNums) {
//                System.out.print(leftNum + " ");
//            }
//            System.out.println();
        generateAllNums(rightNums, M, N, nums, 0);
//            System.out.println(rightNums.size());
//            for (Integer rightNum : rightNums) {
//                System.out.print(rightNum + " ");
//            }
//            System.out.println();
        //左边排序
        Collections.sort(leftNums);
        //右侧排序
        Collections.sort(rightNums);

        //在左侧找接近goal的最大值
        int leftNear = binarySearchNearGoal(0, leftNums.size() - 1, leftNums, goal);
        //System.out.println("left: " + leftNear);
        if (leftNear == goal)
            return 0;
        //在右侧找接近goal的最大值
        int rightNear = binarySearchNearGoal(0, rightNums.size() - 1, rightNums, goal);
        //System.out.println("right: " + rightNear);
        if (rightNear == goal)
            return 0;
        //两边同时找
        int near = Math.abs(leftNear - goal) <= Math.abs(rightNear - goal) ? leftNear : rightNear;
        for (Integer leftNum : leftNums) {
            int allNear = binarySearchNearGoal(0, rightNums.size() - 1, rightNums, goal - leftNum);
            if (allNear + leftNum == goal)
                return 0;
            near = Math.abs(allNear + leftNum - goal) <= Math.abs(near - goal) ? allNear + leftNum : near;
            //System.out.println(near);
        }
        return Math.abs(near - goal);
    }

    private void generateAllNums(ArrayList<Integer> res, int index, int maxLen, int[] nums, int total) {
        if (index >= maxLen) {
            res.add(total);
            return;
        }
        //用
        generateAllNums(res, index + 1, maxLen, nums, total + nums[index]);
        //不用
        generateAllNums(res, index + 1, maxLen, nums, total);
    }

    private int binarySearchNearGoal(int i, int j, ArrayList<Integer> nums, int goal) {
        int left = i;
        int right = j;

        while (left <= right) {
            int mid = left + ((right - left) >> 1);
            if (nums.get(mid) > goal) {
                right = mid - 1;
            } else if (nums.get(mid) == goal) {
                return nums.get(mid);
            } else {
                left = mid + 1;
            }
        }
        left = left > j ? j : left;
        right = right < 0 ? 0 : right;

        int rightNear = nums.get(right);
        int leftNear = nums.get(left);
        return Math.abs(goal - rightNear) <= Math.abs(goal - leftNear) ? rightNear : leftNear;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值