探索算法系列 - 二分查找算法

news2024/9/23 11:22:36

目录

二分查找(原题链接)

在排序数组中查找元素的第一个和最后一个位置(原题链接)

搜索插入位置(原题链接)

x 的平方根(原题链接)

山脉数组的峰顶索引(原题链接)

寻找峰值(原题链接)

寻找旋转排序数组中的最小值(原题链接)

点名(原题链接)


二分查找(原题链接)

给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target  ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 -1

解题思路

        该算法实现的是二分查找算法,用于在一个有序数组中查找目标值的位置。二分查找的核心思想是每次将查找范围缩小一半,从而在对数时间内找到目标值。

步骤说明

  1. 初始化指针

    • left 指向数组的起始位置,right 指向数组的末尾位置。这样定义指针是为了确定搜索区间。
  2. 进入循环

    • left 指针小于等于 right 指针时,继续循环。循环的目的是不断缩小查找区间,直到找到目标值或区间无效。
  3. 计算中间位置

    • 计算 mid 的位置作为当前查找的中间位置,使用 (left + right) / 2 的方式,但为了避免整数溢出,改用 left + (right - left) / 2
  4. 判断中间值

    • 如果 nums[mid] 等于目标值 target,直接返回 mid,表示找到了目标值。
    • 如果 nums[mid] 大于目标值,说明目标值在左半部分,将 right 指针移动到 mid - 1
    • 如果 nums[mid] 小于目标值,说明目标值在右半部分,将 left 指针移动到 mid + 1
  5. 返回结果

    • 如果在循环结束后仍未找到目标值,则返回 -1,表示数组中不存在目标值。

具体代码

class Solution 
{
public:
    int search(vector<int>& nums, int target)
    {
        // 初始化 left 与 right 指针
        int left = 0, right = nums.size() - 1;
        // 由于两个指针相交时,当前元素还未判断,因此需要取等号
        while (left <= right)
        {
            // 先找到区间的中间元素
            int mid = left + (right - left) / 2;    //防止溢出
            // 判断中间元素是否为目标值
            if (nums[mid] == target)
                return mid;
            // 如果中间元素大于目标值,缩小右边界
            else if (nums[mid] > target)
                right = mid - 1;
            // 如果中间元素小于目标值,缩小左边界
            else
                left = mid + 1;
        }
        // 如果未找到目标值,返回 -1
        return -1;
    }
};

在排序数组中查找元素的第一个和最后一个位置(原题链接)

给你一个按照非递减顺序排列的整数数组 nums,和一个目标值 target。请你找出给定目标值在数组中的开始位置和结束位置。

如果数组中不存在目标值 target,返回 [-1, -1]

你必须设计并实现时间复杂度为 O(log n) 的算法解决此问题。

解题思路

        该算法的目的是找到目标值在有序数组中的起始位置和结束位置。为了达到这个目的,算法使用了二分查找的方法,分别寻找目标值的左端点和右端点。由于二分查找在有序数组中可以高效地定位目标值,因此这种方法非常适合这个问题。

步骤说明

  1. 处理边界情况

    • 如果数组为空,直接返回 {-1, -1}
  2. 查找左端点

    • 使用二分查找找到目标值的第一个出现位置(左端点)。如果 nums[mid] 小于目标值,说明左半部分不可能包含目标值,移动左指针。否则,右半部分可能包含目标值或正好是目标值,因此右指针移动到 mid
    • 最后检查 nums[left] 是否等于目标值来验证是否找到目标值。
  3. 查找右端点

    • 使用二分查找找到目标值的最后一个出现位置(右端点)。为了保证找到的右端点是最后一个目标值的位置,计算 mid 时取 (left + (right - left + 1) / 2)。如果 nums[mid] 小于等于目标值,左指针移动到 mid;否则,右指针移动到 mid - 1
    • 由于二分查找结束时 left 指向目标值的最后一个位置,因此返回 {begin, right},其中 begin 是左端点,right 是右端点。

具体代码 

class Solution 
{
public:
    vector<int> searchRange(vector<int>& nums, int target) 
    {
        // 处理边界情况:如果数组为空,直接返回 {-1, -1}
        if (nums.empty())
            return {-1, -1};

        int begin = 0;
        // 1. 二分查找左端点
        int left = 0, right = nums.size() - 1;
        while (left < right) 
        {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target)
                left = mid + 1;  // 目标值在右半部分
            else
                right = mid;     // 目标值在左半部分或正好是中间值
        }
        // 检查找到的左端点是否为目标值
        if (nums[left] != target)
            return {-1, -1};  // 目标值不存在
        else
            begin = left;    // 标记左端点

        // 2. 二分查找右端点
        left = 0, right = nums.size() - 1;
        while (left < right) 
        {
            int mid = left + (right - left + 1) / 2;
            if (nums[mid] <= target)
                left = mid;      // 目标值在右半部分或正好是中间值
            else
                right = mid - 1; // 目标值在左半部分
        }
        // 返回目标值的起始和结束位置
        return {begin, right};
    }
};

搜索插入位置(原题链接)

给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。

请必须使用时间复杂度为 O(log n) 的算法。

解题思路

        这个算法的目标是找到目标值 target 应该插入到有序数组 nums 的位置,使得插入后的数组仍然保持有序。这个问题可以通过修改的二分查找算法来解决。算法会找到目标值插入的位置,确保所有小于目标值的元素在它前面,所有大于目标值的元素在它后面。

步骤说明

  1. 初始化指针

    • 使用两个指针 leftright 来表示当前查找的区间,初始值分别为数组的起始位置和末尾位置。
  2. 二分查找

    • left 小于 right 时,计算中间位置 mid
    • 如果 nums[mid] 小于目标值 target,说明目标值在右半部分,因此将 left 指针移动到 mid + 1
    • 如果 nums[mid] 大于或等于目标值,说明目标值在左半部分或正好是中间值,因此将 right 指针移动到 mid
  3. 确定插入位置

    • 循环结束时,left 应该是目标值应该插入的位置。如果 nums[left] 小于目标值,则 right + 1 为插入位置;否则,right 为插入位置。
具体代码
class Solution 
{
public:
    int searchInsert(vector<int>& nums, int target) 
    {
        int left = 0, right = nums.size() - 1;
        
        // 二分查找插入位置
        while (left < right) 
        {
            int mid = left + (right - left) / 2;
            if (nums[mid] < target)
                left = mid + 1;  // 目标值在右半部分
            else
                right = mid;     // 目标值在左半部分或正好是中间值
        }
        
        // 确定目标值的插入位置
        // 如果 nums[left] 小于目标值,插入位置是 right + 1
        // 否则,插入位置是 right
        if (nums[left] < target)
            return right + 1;
        return right;
    }
};

x 的平方根(原题链接)

给你一个非负整数 x ,计算并返回 x 的 算术平方根 。

由于返回类型是整数,结果只保留 整数部分 ,小数部分将被 舍去 。

注意:不允许使用任何内置指数函数和算符,例如 pow(x, 0.5) 或者 x ** 0.5 。

解题思路

        要找到一个非负整数 x 的平方根,我们可以使用二分查找算法。目标是找到最大的整数 y,使得 y^2 小于或等于 x。在有序的整数区间 [0, x] 上进行二分查找可以有效地找到这个整数 y

步骤说明

  1. 处理边界情况

    • 如果 x 小于 1,则平方根应该是 0(这是因为平方根在负数或零范围内的定义)。
  2. 初始化指针

    • left 初始化为 1(对于 x >= 1 的情况),right 初始化为 x。这些指针定义了二分查找的区间。
  3. 二分查找

    • 使用二分查找来找到最大整数 y,使得 y^2 <= x。计算中间位置 mid 时使用 (left + (right - left + 1) / 2) 来避免整数溢出。
    • 如果 mid * mid 小于或等于 x,说明 mid 可以是平方根,或者在 mid 右侧的值也有可能是平方根,因此移动左指针到 mid
    • 否则,目标平方根只能在 mid 的左侧,因此移动右指针到 mid - 1
  4. 返回结果

    • 循环结束时,left 就是最大整数,使得 left^2 小于或等于 x,即所求的平方根。

具体代码

class Solution 
{
public:
    int mySqrt(int x) 
    {
        // 处理边界情况:x 小于 1 的平方根是 0
        if (x < 1)
            return 0;
        
        int left = 1, right = x;
        
        // 二分查找平方根
        while (left < right) 
        {
            // 防止中间值计算溢出
            long long mid = left + (right - left + 1) / 2;
            
            // 检查 mid^2 是否小于等于 x
            if (mid * mid <= x)
                left = mid;   // mid 可能是答案,尝试右边
            else
                right = mid - 1; // mid 不是答案,调整右边界
        }
        
        // 返回找到的最大平方根整数
        return left;
    }
};

山脉数组的峰顶索引(原题链接)

给定一个长度为 n 的整数 山脉 数组 arr ,其中的值递增到一个 峰值元素 然后递减。

返回峰值元素的下标。

你必须设计并实现时间复杂度为 O(log(n)) 的解决方案。

解题思路

        山脉数组的特性是存在一个峰值元素,使得在峰值左边的元素严格递增,右边的元素严格递减。我们可以利用二分查找来高效地找到这个峰值。通过比较中间元素与其相邻的元素,我们可以判断当前元素是在上升序列中还是下降序列中,从而调整搜索区间。

步骤说明

  1. 初始化指针

    • left 初始化为 0,right 初始化为数组的最后一个索引。这两个指针用于定义搜索区间。
  2. 二分查找

    • 计算中间位置 mid,为了防止溢出,使用 left + (right - left + 1) / 2
    • 判断 arr[mid]arr[mid - 1] 的关系:
      • 如果 arr[mid] > arr[mid - 1],说明 mid 处于山脉的上升部分,峰值在 mid 右侧或者就是 mid,因此移动 left 指针到 mid
      • 如果 arr[mid] <= arr[mid - 1],说明 mid 处于山脉的下降部分,峰值在 mid 左侧,因此移动 right 指针到 mid - 1
  3. 返回结果

    • left == right 时,leftright 指向的就是峰值元素的索引。

具体代码 

class Solution 
{
public:
    int peakIndexInMountainArray(vector<int>& arr) 
    {
        int left = 0, right = arr.size() - 1;
        
        // 二分查找山脉数组的峰值
        while (left < right) 
        {
            // 防止溢出计算中间位置
            int mid = left + (right - left + 1) / 2;
            
            // 判断 mid 是否处于上升部分
            if (arr[mid] > arr[mid - 1])
                left = mid;  // 峰值在右侧或就是 mid
            else
                right = mid - 1; // 峰值在左侧
        }
        
        // 返回找到的峰值索引
        return left;
    }
};

寻找峰值(原题链接)

峰值元素是指其值严格大于左右相邻值的元素。

给你一个整数数组 nums,找到峰值元素并返回其索引。数组可能包含多个峰值,在这种情况下,返回 任何一个峰值 所在位置即可。

你可以假设 nums[-1] = nums[n] = -∞ 。

你必须实现时间复杂度为 O(log n) 的算法来解决此问题。

解题思路

        在一个无序数组中寻找峰值元素,可以利用二分查找的思想。通过比较中间元素与其右侧元素的大小,可以判断峰值所在的区域,从而逐步缩小查找范围。最终找到一个峰值元素的索引。

步骤说明

  1. 初始化指针

    • left 初始化为数组的起始位置 0,right 初始化为数组的末尾位置 nums.size() - 1
  2. 二分查找

    • left 小于 right 的情况下,继续循环。
    • 计算中间位置 mid,为防止溢出,使用 left + (right - left) / 2
    • 判断 nums[mid]nums[mid + 1] 的关系:
      • 如果 nums[mid] > nums[mid + 1],说明在 mid 位置的左侧可能存在峰值(包括 mid),因此移动 right 指针到 mid
      • 如果 nums[mid] <= nums[mid + 1],说明在 mid 位置的右侧存在峰值,因此移动 left 指针到 mid + 1
  3. 返回结果

    • leftright 相等时,循环结束,left 即为峰值元素的索引。

具体代码 

class Solution 
{
public:
    int findPeakElement(vector<int>& nums) 
    {
        int left = 0, right = nums.size() - 1;
        
        // 二分查找峰值元素
        while (left < right) 
        {
            // 防止溢出计算中间位置
            int mid = left + (right - left) / 2;
            
            // 判断 mid 是否处于下降坡度
            if (nums[mid] > nums[mid + 1])
                right = mid; // 峰值在左侧,包括 mid 位置
            else
                left = mid + 1; // 峰值在右侧
        }
        
        // 返回找到的峰值索引
        return left;
    }
};

寻找旋转排序数组中的最小值(原题链接)

已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums = [0,1,2,4,5,6,7] 在变化后可能得到:

  • 若旋转 4 次,则可以得到 [4,5,6,7,0,1,2]
  • 若旋转 7 次,则可以得到 [0,1,2,4,5,6,7]

注意,数组 [a[0], a[1], a[2], ..., a[n-1]] 旋转一次 的结果为数组 [a[n-1], a[0], a[1], a[2], ..., a[n-2]] 。

给你一个元素值 互不相同 的数组 nums ,它原来是一个升序排列的数组,并按上述情形进行了多次旋转。请你找出并返回数组中的 最小元素 。

你必须设计一个时间复杂度为 O(log n) 的算法解决此问题。

解题思路

        旋转排序数组中的最小元素是所有元素中最小的值,且它右侧的元素都大于它。利用二分查找,可以在 O(log n) 时间复杂度内找到这个最小值。关键是判断中间元素的位置,以确定缩小搜索区间的方向。

步骤说明

  1. 初始化指针

    • left 初始化为数组的起始位置 0,right 初始化为数组的末尾位置 nums.size() - 1
  2. 选择基准值

    • 选择数组末尾的元素 nums[right] 作为基准值 x。在未旋转的情况下,最小值就是这个基准值。
  3. 二分查找

    • left 小于 right 时,继续循环。
    • 计算中间位置 mid,为防止溢出,使用 left + (right - left) / 2
    • 如果 nums[mid] > x,说明最小元素在右侧,因此 left 移动到 mid + 1
    • 如果 nums[mid] <= x,说明最小元素在左侧或中间位置,因此 right 移动到 mid
  4. 返回结果

    • leftright 相等时,循环结束,此时 left 指向的元素就是最小元素。

具体代码

 

class Solution 
{
public:
    int findMin(vector<int>& nums) 
    {
        int left = 0, right = nums.size() - 1;
        int x = nums[right]; // 基准值设为数组末尾元素
        
        // 二分查找最小元素
        while (left < right) 
        {
            // 防止溢出计算中间位置
            int mid = left + (right - left) / 2;
            
            // 判断 mid 位置的元素与基准值的关系
            if (nums[mid] > x)
                left = mid + 1; // 最小元素在右侧
            else
                right = mid; // 最小元素在左侧或 mid 位置
        }
        
        // 返回最小元素
        return nums[left];
    }
};

点名(原题链接)

某班级 n 位同学的学号为 0 ~ n-1。点名结果记录于升序数组 records。假定仅有一位同学缺席,请返回他的学号。

解题思路

        这段代码的主要目的是在一个有序数组 records 中查找一个满足特定条件的位置。具体来说,数组 records 中的元素表示某种记录,每个元素的值表示某种“出勤”记录。在这个问题中,要求找到一个位置 i 使得 records[i] 不等于 i,并返回该位置。如果所有位置 i 都满足 records[i] == i,则返回数组的长度。

步骤说明

  1. 初始化指针: 定义两个指针 leftright,分别指向数组的开头和结尾。

  2. 二分查找: 使用二分查找的方法逐步缩小查找范围。通过计算 mid,即中间位置的索引,来分割数组。

  3. 条件判断:

    • 如果 records[mid] == mid,说明在 mid 及其左侧的元素都满足 records[i] == i,因此将 left 移动到 mid + 1 继续查找。
    • 如果 records[mid] != mid,则可能的解在 mid 及其左侧,因此将 right 移动到 mid
  4. 返回结果: 最后,检查 leftrecords[left] 的关系:

    • 如果 left == records[left],则说明找到了一个最后满足 records[i] == i 的位置,返回 left + 1
    • 否则,返回 left 作为结果。

 具体代码

class Solution 
{
public:
    int takeAttendance(vector<int>& records) 
    {
        int left = 0, right = records.size() - 1;
        // 使用二分查找方法
        while( left < right)
        {
            int mid = left + (right - left) / 2;
            if(records[mid] == mid)
                left = mid + 1;  // 更新left指针,因为此时mid及左边的元素都满足条件
            else
                right = mid;  // 更新right指针,因为可能的解在mid及左边
        }
        // 最终检查left位置是否满足条件,返回结果
        return left == records[left] ? left + 1 : left;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1966709.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

数据结构(面试)

线索二叉树 原理&#xff1a;利用树节点的n1个左右空指针指向其遍历序列的前驱和后继&#xff08;线索&#xff09; 哈夫曼树 哈夫曼树定义&#xff1a;在含有n个带权叶节点的二叉树中&#xff0c;其中带权路径&#xff08;WPL&#xff09;最小的二叉树称为哈夫曼树&#x…

协程的八种创建方式

协程简介 在深入了解创建方式之前&#xff0c;我们先简要回顾一下协程是什么。协程是轻量级的线程。它们在协作式多任务处理中运行&#xff0c;允许在不阻塞线程的情况下挂起和恢复。这使得协程非常适合进行异步编程和高性能的并发任务。&#x1f310; Kotlin中创建协程的方式…

IDA相关

IDA相关 IDA pro 7.7 链接: https://pan.baidu.com/s/14F0M1lxZMCoCAmR3AFmm-A?pwdjk14 提取码: jk14 lazy ida https://github.com/P4nda0s/LazyIDA pip install yara pip install keystone24.0.0.0 可以把ida目录里python site-package的内容复制到本机python的lib/si…

html写table表格,后端数据中涉及到身份证号或者电话号的情况,生成excel变成1+e17或者###等类似的加密或科学计数法情况

效果展示&#xff08;对比图&#xff09;&#xff1a; 原&#xff1a; 新&#xff1a; 解决办法&#xff1a; 加以下样式即可展示原来的 style"vnd.ms-excel.numberformat:" 如若想知道…

链表的实现(C++版)

对于链表的学习,之前在C语言部分的时候就已经有学习过,也学会了使用C语言来打造一个链表.如今学了C 则想通过C来打造一个链表,以达到锻炼自己的目的. 1.链表的初步实现 1.节点模板的设置 template <class T> struct ListNode{ListNode <T>* _next;ListNode <T…

【Linux 网络】应用层

文章目录 应用层协议序列化的概念jsoncpp 1. HTTP1.1URLURL编解码 1.2 HTTP的格式HTTP请求格式HTTP响应格式 1.3 HTTP的方法GET/POST 1.4 HTTP的状态码1.5 HTTP的报头cookie和session1.6 简单HTTP服务器 2. HTTPS2.1 加密方式对称加密非对称加密全对称加密混合加密密钥协商对称…

CSS画箭头

向右示例 .arrows {height: 7px;width: 7px;background-color: transparent;border-top: 2px solid rgba(0, 0, 0, 0.3);border-right: 2px solid rgba(0, 0, 0, 0.3);transform: rotate(45deg);margin-left: 6px; } 可以尝试将其封装为组件&#xff08;以微信小程序为例&…

上位机《1》 步进电机、步进驱动器,连接端子(接线盒子)等

正运动技术 固高控制卡 雷赛控制卡 步进电机 电机内部的线圈数不同&#xff0c;组成的电机相数也不同&#xff0c;两相步进电机电机内部是由2个线圈组成&#xff0c;而三相步进电机内部是由3个线圈。 相数越多&#xff0c;步进角越小。所有精度就越高。步进电机转速越快&…

经验分享:大数据多头借贷风险对自身的不利影响?

在现代金融体系中&#xff0c;大数据技术的应用使得多头借贷成为一种普遍现象。多头借贷指的是个人或企业在短时间内同时或近期内申请多笔贷款或信用产品&#xff0c;这种行为可能带来一系列财务和信用风险。以下是大数据多头借贷风险对个人自身可能产生的不利影响&#xff1a;…

花了2小时,自己做了一个出入库系统

出入库管理是库存管理工作的重中之重&#xff0c;但在刚做产品出入库时&#xff0c;我可是踩了不少坑—— 库存管理不精确仓库作业效率低下货物追踪困难报表统计繁琐... 后来我就自学了下&#xff0c;花了两个小时自己做了一套织信出入库管理系统&#xff0c;全程没有敲一个代…

帆软10.0报表部署到正式环境后,不显示数据集的数据。

修改正式环境的数据连接 1&#xff09;数据连接的「编码」类型设置为「默认」。 2&#xff09;数据连接的「数据连接URL」后加后缀&#xff0c;如下图所示。格式为&#xff1a; jdbc:mysql://hostname:port/database?generateSimpleParameterMetadatatrue&useUnicodetru…

运维工程师,刚入职一个之前没有运维的公司,该做什么?

运维工程师&#xff0c;刚入职一个之前没有运维的公司&#xff0c;该做什么&#xff1f; 下面内容&#xff0c;只谈技术工作方面的&#xff0c;人情世故的方面自己体会吧。。。。 前言 写这个&#xff0c;主要是有一个朋友&#xff0c;也是运维工程师&#xff0c;五年以上运…

【STL】之 list 使用方法和模拟实现

目录 前言&#xff1a; list是什么&#xff1f; 节点类 迭代器类&#xff1a; list类 list的迭代器失效问题 前言&#xff1a; 之前我们分别手撕了string类和vector类&#xff0c;今天我们来跟list类打打交道~ list是什么&#xff1f; 通过查c文档可知&#xff0c;list…

(2)基于巴法云+MQTT+微信小程序控制esp8266点灯

目录 1、wifi配置指令表 2、连接连接wifi网络 3、连接巴法云MQTT &#xff08;1&#xff09;配置用户属性ATMQTTUSERCFG ① 命令格式&#xff1a; ② 命令参数&#xff1a; ③ 实际配置方式&#xff1a; &#xff08;2&#xff09;配置ESP 设备连接的 MQTT broker ① 命令格式…

【AI大模型】自动辅助驾驶的“大模型”时代

&#x1f388;边走、边悟&#x1f388;迟早会好 一、自动辅助驾驶实现与设计 1. 系统架构 1.1. 传感器系统 摄像头&#xff1a;提供前视、侧视、后视等多角度图像数据&#xff0c;用于检测车道线、交通标志、行人和其他车辆。雷达&#xff08;RADAR&#xff09;&#xff1a…

【python】PyQt5中QRadioButton的详细用法教程与应用实战

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

论文速递 | Operations Research 6月文章合集

编者按&#xff1a; 在本系列文章中&#xff0c;我们梳理了运筹学顶刊Operations Research在2024年6月份发布的9篇相关文章的基本信息&#xff0c;旨在帮助读者快速洞察领域新动态。 推荐文章1 题目&#xff1a;Tight Guarantees for Multiunit Prophet Inequalities and On…

list模拟实现--用节点封装的迭代器问题

目录 一、list的使用 1.1list的构造 1.2list的iterator ​编辑 1.3 list的capacity 1.4 list的element access ​编辑 1.5list的mdifiers ​编辑 二、list的迭代器失效问题 三、list的模拟实现 3.1定义一个节点类 3.2用节点去封装迭代器 编译器对->的优化问题 …

JavaScript做网页是否过期的处理

通过路由上的参数生成唯一md5和路由上token做验证_md5 token-CSDN博客 前言&#xff1a;基于这篇文章我们做网页是否超时&#xff0c;网页是否过期的处理。打开一个网页允许他在一定时间内可以访问&#xff0c;过了这个时间就不可以访问了&#xff0c;encrypt是h5加密方法&…

数据仓库基础理论—维度建模(图文详解)

数据仓库基础理论—维度建模 维度建模是数据仓库设计中的一种核心方法&#xff0c;旨在以业务角度组织数据&#xff0c;使其更易于理解、查询和分析。 1. 维度模型的基本概念 1.1 事实表&#xff08;Fact Table&#xff09;&#xff1a; 事实表是维度模型的核心&#xff0…