当前位置: 首页 > news >正文

今日分享 整数二分

1. 二分法的核心思想

 

二分法就像猜数字游戏。每次猜中间数,根据大小提示排除一半答案。

 

这种方法将 O(n) 的线性查找,优化到 O(log n) 的对数级别。

 

2. 整数二分的"奥义"

 

整数二分的精髓在于边界处理。因为整数没有"中点",必须明确:

 

查找区间是  [left, right]  (闭区间)

每次排除时,边界如何更新才不会漏掉答案

 

处理不好边界,就会导致死循环或漏掉正确答案。

 

3. 两种经典模板与技巧

 

根据要找的目标不同,分为两种模板:

 

模板一:查找第一个满足条件的值

 

用于查找"左边界",例如:数组中第一个大于等于 x 的数。

 

 

int findFirst(int *nums, int n, int x) {

    int left = 0, right = n - 1;

    int ans = n; // 初始化为一个不可能的位置

    while (left <= right) {

        int mid = left + (right - left) / 2; // 防止溢出

        if (nums[mid] >= x) { // 满足条件,尝试找更左边的

            ans = mid;

            right = mid - 1;

        } else { // 不满足,去右边找

            left = mid + 1;

        }

    }

    return ans;

}

 

 

模板二:查找最后一个满足条件的值

 

用于查找"右边界",例如:数组中最后一个小于等于 x 的数。

 

 

int findLast(int *nums, int n, int x) {

    int left = 0, right = n - 1;

    int ans = -1; // 初始化为一个不可能的位置

    while (left <= right) {

        int mid = left + (right - left) / 2;

        if (nums[mid] <= x) { // 满足条件,尝试找更右边的

            ans = mid;

            left = mid + 1;

        } else { // 不满足,去左边找

            right = mid - 1;

        }

    }

    return ans;

}

 

 

4. 解题技巧总结

 

1. 确定区间:永远使用闭区间  [left, right] ,逻辑最清晰。

2. 循环条件:使用  left <= right ,保证退出时所有元素都被检查。

3. 计算中点:用  mid = left + (right - left) / 2  避免  left + right  溢出。

4. 边界移动:根据"找左边界"还是"找右边界"选择移动  left  或  right 。

5. 验证答案:退出循环后,记得检查  ans  是否在合理范围内。

 

 

 

例题实战:在排序数组中查找元素的第一个和最后一个位置

 

题目描述:

给定一个按照升序排列的整数数组  nums ,和一个目标值  target 。找出给定目标值在数组中的开始位置和结束位置。如果数组中不存在目标值,返回  [-1, -1] 。

 

示例:

输入: nums = [5,7,7,8,8,10] ,  target = 8 

输出: [3, 4] 

 

 

 

C 语言实现

 

 

#include <stdio.h>

#include <stdlib.h>

 

int* searchRange(int* nums, int numsSize, int target, int* returnSize) {

    *returnSize = 2;

    int* result = (int*)malloc(sizeof(int) * 2);

    result[0] = -1;

    result[1] = -1;

    

    // 找左边界

    int left = 0, right = numsSize - 1;

    while (left <= right) {

        int mid = left + (right - left) / 2;

        if (nums[mid] >= target) {

            right = mid - 1;

        } else {

            left = mid + 1;

        }

    }

    if (left < numsSize && nums[left] == target) {

        result[0] = left;

    } else {

        return result;

    }

    

    // 找右边界

    left = 0;

    right = numsSize - 1;

    while (left <= right) {

        int mid = left + (right - left) / 2;

        if (nums[mid] <= target) {

            left = mid + 1;

        } else {

            right = mid - 1;

        }

    }

    result[1] = right;

    

    return result;

}

 

int main() {

    int nums[] = {5,7,7,8,8,10};

    int target = 8;

    int returnSize;

    int* result = searchRange(nums, 6, target, &returnSize);

    printf("[%d, %d]\n", result[0], result[1]);

    free(result);

    return 0;

}

 

 

C++ 实现

 

 

#include <iostream>

#include <vector>

using namespace std;

 

vector<int> searchRange(vector<int>& nums, int target) {

    vector<int> result(2, -1);

    int n = nums.size();

    if (n == 0) return result;

    

    // 找左边界

    int left = 0, right = n - 1;

    while (left <= right) {

        int mid = left + (right - left) / 2;

        if (nums[mid] >= target) {

            right = mid - 1;

        } else {

            left = mid + 1;

        }

    }

    if (left < n && nums[left] == target) {

        result[0] = left;

    } else {

        return result;

    }

    

    // 找右边界

    left = 0;

    right = n - 1;

    while (left <= right) {

        int mid = left + (right - left) / 2;

        if (nums[mid] <= target) {

            left = mid + 1;

        } else {

            right = mid - 1;

        }

    }

    result[1] = right;

    

    return result;

}

 

int main() {

    vector<int> nums = {5,7,7,8,8,10};

    int target = 8;

    vector<int> res = searchRange(nums, target);

    cout << "[" << res[0] << ", " << res[1] << "]" << endl;

    return 0;

}

 

 

Python 实现

 

 

def searchRange(nums, target):

    result = [-1, -1]

    n = len(nums)

    if n == 0:

        return result

    

    # 找左边界

    left, right = 0, n - 1

    while left <= right:

        mid = left + (right - left) // 2

        if nums[mid] >= target:

            right = mid - 1

        else:

            left = mid + 1

    if left < n and nums[left] == target:

        result[0] = left

    else:

        return result

    

    # 找右边界

    left, right = 0, n - 1

    while left <= right:

        mid = left + (right - left) // 2

        if nums[mid] <= target:

            left = mid + 1

        else:

            right = mid - 1

    result[1] = right

    

    return result

 

nums = [5,7,7,8,8,10]

target = 8

print(searchRange(nums, target))

 

 

Java 实现

 

 

import java.util.Arrays;

 

public class SearchRange {

    public static int[] searchRange(int[] nums, int target) {

        int[] result = {-1, -1};

        int n = nums.length;

        if (n == 0) return result;

        

        // 找左边界

        int left = 0, right = n - 1;

        while (left <= right) {

            int mid = left + (right - left) / 2;

            if (nums[mid] >= target) {

                right = mid - 1;

            } else {

                left = mid + 1;

            }

        }

        if (left < n && nums[left] == target) {

            result[0] = left;

        } else {

            return result;

        }

        

        // 找右边界

        left = 0;

        right = n - 1;

        while (left <= right) {

            int mid = left + (right - left) / 2;

            if (nums[mid] <= target) {

                left = mid + 1;

            } else {

                right = mid - 1;

            }

        }

        result[1] = right;

        

        return result;

    }

    

    public static void main(String[] args) {

        int[] nums = {5,7,7,8,8,10};

        int target = 8;

        int[] res = searchRange(nums, target);

        System.out.println(Arrays.toString(res));

    }

}

 

 

 

 

http://www.dtcms.com/a/429213.html

相关文章:

  • 中国建设银行济南招聘信息网站企业网站 单页
  • 老外做汉字网站做网站大概
  • 永久免费自助建站推荐岳阳网站平台设计
  • 门户网站 jsp长沙百度推广公司
  • 优秀网站下载专业app制作开发公司
  • 给个能看的网站《php网站开发》课程资料
  • 品牌网站建设 十蝌蚪小长春网站建设开发的有哪些
  • 开发软件的网站平台怎么自己做淘宝网站吗
  • 建站开发工具标杆建设网站
  • 青岛专业设计网站公司网站蜘蛛屏蔽怎样恢复
  • 网站建设开发背景网页做推广
  • 【UVA - 11636】Hello World!
  • 新天力:定制化+创新工艺,解锁食品容器行业无限可能
  • 怎么提高网站加载速度慢邢台市教育局官网
  • 福建公司网站开发网络营销案例分析ppt
  • 网站数据库5gwordpress手机版网站
  • 电子商务网站建设技术解决方案网站建设 58同城
  • 共生伙伴还是致病元凶?——全面认识葡萄球菌属(Staphylococcus)
  • 付费网站 源码 下载链接化妆品网站建设规划书范文
  • 工信部网站登陆网易企业邮箱手机上登录不了
  • 网站建设的课程设计报告甘肃网站建设企业推荐
  • 网站设计公司怎样提高网站点击率
  • 南阳企业网站学广告设计难不难
  • 网站建设 设计 优化 维护移动论坛网站模板免费下载
  • 教人做甜点的网站东莞网络科技公司有哪些
  • 怎么编辑网页里面内容杭州百度seo代理
  • 基础算法---【双指针】
  • 做地方网站论坛赚钱广东建设厅官网查询平台
  • 杭州企业网站建设方案城阳做网站的
  • 信息公开 强化网站建设珠宝首饰网站建设