第三课 哈希表、集合、映射

news2024/7/6 19:13:42

文章目录

  • 第三课 哈希表、集合、映射
    • lc1.两数之和--简单
      • 题目描述
      • 代码展示
    • lc30.串联所有单词的子串--困难
      • 题目描述
      • 代码展示
    • lc49.字母异位分组--中等
      • 题目描述
      • 代码展示
    • lc874.模拟行走机器人--中等
      • 题目描述
      • 代码展示
    • lc146.LRU缓存--中等
      • 题目描述
      • 相关补充
      • 思路讲解
      • 代码展示
      • 图示理解

第三课 哈希表、集合、映射

lc1.两数之和–简单

题目描述

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 target 的那 两个 整数,并返回它们的数组下标。

你可以假设每种输入只会对应一个答案。但是,数组中同一个元素在答案里不能重复出现。

你可以按任意顺序返回答案。

示例 1:

输入:nums = [2,7,11,15], target = 9
输出:[0,1]
解释:因为 nums[0] + nums[1] == 9 ,返回 [0, 1] 。

示例 2:

输入:nums = [3,2,4], target = 6
输出:[1,2]

示例 3:

输入:nums = [3,3], target = 6
输出:[0,1]

提示:

  • 2 <= nums.length <= 104
  • -109 <= nums[i] <= 109
  • -109 <= target <= 109
  • 只会存在一个有效答案

代码展示

class Solution {
public:      //HaspMap实现
    vector<int> twoSum(vector<int>& numbers, int target) {
        // j < i
        // for i = 0 ~ n - 1:
        //      search if (target - numbers[i]) exists in numbers[0..i-1]

        unordered_map<int, int> value_to_index; // 值到下标的映射

        for (int i = 0; i < numbers.size(); i++) {
            // 不等于尾部,就是找到了,存在
            // Java: value_to_index.containsKey(target-numbers[i])
            // Pythong: target-numbers[i] in value_to_index
            if (value_to_index.find(target - numbers[i]) != value_to_index.end()) {
                return {value_to_index[target - numbers[i]], i};
            }
            // 边循环i,边插入,维护的是对于numbers[0..i-1]的映射
            // 本质上是在i之前查找,防止查找i本身
            value_to_index[numbers[i]] = i;
        }
        return {};
    }
};

lc30.串联所有单词的子串–困难

题目描述

给定一个字符串 s 和一个字符串数组 words words 中所有字符串 长度相同

s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。

  • 例如,如果 words = ["ab","cd","ef"], 那么 "abcdef""abefcd""cdabef""cdefab""efabcd", 和 "efcdab" 都是串联子串。 "acdbef" 不是串联子串,因为他不是任何 words 排列的连接。

返回所有串联子串在 s 中的开始索引。你可以以 任意顺序 返回答案。

示例 1:

输入:s = "barfoothefoobarman", words = ["foo","bar"]
输出:[0,9]
解释:因为 words.length == 2 同时 words[i].length == 3,连接的子字符串的长度必须为 6。
子串 "barfoo" 开始位置是 0。它是 words 中以 ["bar","foo"] 顺序排列的连接。
子串 "foobar" 开始位置是 9。它是 words 中以 ["foo","bar"] 顺序排列的连接。
输出顺序无关紧要。返回 [9,0] 也是可以的。

示例 2:

输入:s = "wordgoodgoodgoodbestword", words = ["word","good","best","word"]
输出:[]
解释:因为 words.length == 4 并且 words[i].length == 4,所以串联子串的长度必须为 16。
s 中没有子串长度为 16 并且等于 words 的任何顺序排列的连接。
所以我们返回一个空数组。

示例 3:

输入:s = "barfoofoobarthefoobarman", words = ["bar","foo","the"]
输出:[6,9,12]
解释:因为 words.length == 3 并且 words[i].length == 3,所以串联子串的长度必须为 9。
子串 "foobarthe" 开始位置是 6。它是 words 中以 ["foo","bar","the"] 顺序排列的连接。
子串 "barthefoo" 开始位置是 9。它是 words 中以 ["bar","the","foo"] 顺序排列的连接。
子串 "thefoobar" 开始位置是 12。它是 words 中以 ["the","foo","bar"] 顺序排列的连接。

提示:

  • 1 <= s.length <= 104
  • 1 <= words.length <= 5000
  • 1 <= words[i].length <= 30
  • words[i]s 由小写英文字母组成

代码展示

class Solution {
public:      //测试用例通过了,但耗时太长。
    vector<int> findSubstring(string s, vector<string>& words) {
        wordsMap = countWords(words);
        int tot = words.size() * words[0].size();
        vector<int> ans;
        // 枚举开始位置
        for (int start = 0; start + tot <= s.length(); start++) {
            if (isSame(s.substr(start, tot), words)) {
                ans.push_back(start);
            }
        }
        return ans;
    }

private:
    unordered_map<string, int> wordsMap;

    // 想判断一个字符串t,是否由words拼成
    // 把t分解成若干个单词,然后看跟words数组是否相同(顺序无关)
    bool isSame(string t, vector<string>& words) {
        // cout << "isSame: " << t << " and words" << endl;
        int m = words[0].length(); // 每个单词的长度
        unordered_map<string, int> tMap; // 单词出现次数
        // 把t,每m个字符分解成一个单词
        // foothe 分解为 foo, the
        for (int i = 0; i < t.length(); i += m) {
            // i开始的m个字符,组成一个单词
            tMap[t.substr(i, m)]++;
        }
        return equals(tMap, wordsMap);
    }

    // 判断两个map是否一样的方法
    // a.size() == b.size()
    // size: key的个数
    // a里面有的b里全有,且值一样
    bool equals(unordered_map<string, int>& a, unordered_map<string, int>& b) {
        if (a.size() != b.size()) return false;
        for (auto& key_value_pair : a) {
            auto& key = key_value_pair.first;
            auto& value = key_value_pair.second;
            // 如果b里面没有,或者value不相等(次数不一样)
            if (b.find(key) == b.end() || value != b[key]) return false;
        }
        return true;
    }

    unordered_map<string, int> countWords(vector<string>& words) {
        unordered_map<string, int> ans;
        for (string& word : words) {
            ans[word]++;
        }
        return ans;
    }
};

//bar foo
//arf oot
//rfo oth
//...

优化方法:image-20231006134744326

class Solution {
public:      //优化解法
    vector<int> findSubstring(string s, vector<string>& words) {
        vector<int> ans;
        words_map = getMap(words);

        int n = s.size();
        int m = words[0].size();
        int tot = m * words.size();
        for (int first = 0; first < m; first++) {
            if (first + tot > n) break;
            unordered_map<string, int> s_map;
            int curr = first;
            for (int i = 0; i < words.size(); i++) {
                s_map[s.substr(curr, m)]++;
                curr += m;
            }
            for (int start = first, end = curr; start + tot <= n; start += m, end += m) {
                if (isSame(s_map, words_map)) ans.push_back(start);
                s_map[s.substr(end, m)]++;
                s_map[s.substr(start, m)]--;
            }
        }

        return ans;
    }

private:
    unordered_map<string, int> getMap(vector<string>& words) {
        unordered_map<string, int> res;
        for (string& word : words) {
            res[word]++;
        }
        return res;
    }

    bool isSame(unordered_map<string, int>& a, unordered_map<string, int>& b) {
        for (auto& pr : a) {
            if (b[pr.first] != pr.second) return false;
        }
        for (auto& pr : b) {
            if (a[pr.first] != pr.second) return false;
        }
        return true;
    }

    unordered_map<string, int> words_map;
};

lc49.字母异位分组–中等

题目描述

给你一个字符串数组,请你将 字母异位词 组合在一起。可以按任意顺序返回结果列表。

字母异位词 是由重新排列源单词的所有字母得到的一个新单词。

示例 1:

输入: strs = ["eat", "tea", "tan", "ate", "nat", "bat"]
输出: [["bat"],["nat","tan"],["ate","eat","tea"]]

示例 2:

输入: strs = [""]
输出: [[""]]

示例 3:

输入: strs = ["a"]
输出: [["a"]]

提示:

  • 1 <= strs.length <= 104
  • 0 <= strs[i].length <= 100
  • strs[i] 仅包含小写字母

代码展示

class Solution {
public:
    vector<vector<string>> groupAnagrams(vector<string>& strs) {
        // HashMap可用于分组
        // 从排序以后的字符串(aet)到一个数组(["ate","eat","tea"])的map
        unordered_map<string, vector<string>> group;
        for (string& str : strs) {
            string copy = str;
            // 字符串里面的字符排序
            // Java: toCharArray()
            sort(copy.begin(), copy.end());
            // 分组
            group[copy].push_back(str);
            // cout << "Added " << str << " into group " << copy << endl;
        }

        vector<vector<string>> ans;
        // Java .keySet()
        // Python for .. in ...
        for (auto pr : group) {
            // pr.first == key
            // pr.second == value
            ans.push_back(pr.second);
        }
        return ans;
    }

    // 字符串长度分别是n1, n2, n3,....,总和是n
    // n1 log n1 + n2 log n2 + ....
    // <= n1 log n + n2 log n + ....
    // = (n1 + n2 + ...) log n
    // = n log n
};

/*
["eat", "tea", "tan", "ate", "nat", "bat"]
["aet", "aet", "ant", "aet", "ant", "abt"]
*/

lc874.模拟行走机器人–中等

题目描述

机器人在一个无限大小的 XY 网格平面上行走,从点 (0, 0) 处开始出发,面向北方。该机器人可以接收以下三种类型的命令 commands

  • -2 :向左转 90
  • -1 :向右转 90
  • 1 <= x <= 9 :向前移动 x 个单位长度

在网格上有一些格子被视为障碍物 obstacles 。第 i 个障碍物位于网格点 obstacles[i] = (xi, yi)

机器人无法走到障碍物上,它将会停留在障碍物的前一个网格方块上,并继续执行下一个命令。

返回机器人距离原点的 最大欧式距离平方 。(即,如果距离为 5 ,则返回 25

注意:

  • 北方表示 +Y 方向。
  • 东方表示 +X 方向。
  • 南方表示 -Y 方向。
  • 西方表示 -X 方向。
  • 原点 [0,0] 可能会有障碍物。

示例 1:

输入:commands = [4,-1,3], obstacles = []
输出:25
解释:
机器人开始位于 (0, 0):
1. 向北移动 4 个单位,到达 (0, 4)
2. 右转
3. 向东移动 3 个单位,到达 (3, 4)
距离原点最远的是 (3, 4) ,距离为 32 + 42 = 25

示例 2:

输入:commands = [4,-1,4,-2,4], obstacles = [[2,4]]
输出:65
解释:机器人开始位于 (0, 0):
1. 向北移动 4 个单位,到达 (0, 4)
2. 右转
3. 向东移动 1 个单位,然后被位于 (2, 4) 的障碍物阻挡,机器人停在 (1, 4)
4. 左转
5. 向北走 4 个单位,到达 (1, 8)
距离原点最远的是 (1, 8) ,距离为 12 + 82 = 65

示例 3:

输入:commands = [6,-1,-1,6], obstacles = []
输出:36
解释:机器人开始位于 (0, 0):
1. 向北移动 6 个单位,到达 (0, 6).
2. 右转
3. 右转
4. 向南移动 6 个单位,到达 (0, 0).
机器人距离原点最远的点是 (0, 6),其距离的平方是 62 = 36 个单位。

提示:

  • 1 <= commands.length <= 104
  • commands[i] 的值可以取 -2-1 或者是范围 [1, 9] 内的一个整数。
  • 0 <= obstacles.length <= 104
  • -3 * 104 <= xi, yi <= 3 * 104
  • 答案保证小于 231

代码展示

class Solution {
public:
    int robotSim(vector<int>& commands, vector<vector<int>>& obstacles) {
        // {(x1,y1), (x2,y2), ...}
        // (-200, 30000)
        // string: "-200,30000"
        // long long: (-200, 300) -->  (-200+30000, 300+30000) --> (-200+30000)*60000 + 300 + 30000
        unordered_set<long long> blockers;
        for (auto& obstacle : obstacles) {
            blockers.insert(calcHash(obstacle[0], obstacle[1]));
        }
    
        // 方向数组技巧
        //           N, E, S,  W
        int dx[4] = {0, 1, 0, -1}; // 偏移量(单位向量)
        int dy[4] = {1, 0, -1, 0};
        int x = 0, y = 0;
        int dir = 0; // N
        int ans = 0;
        for (int cmd : commands) {
            if (cmd > 0) {
                for (int i = 0; i < cmd; i++) {
                    // 尝试走到nextx, nexty
                    // 想向dir走一步,就加dir方向的偏移量
                    int nextx = x + dx[dir];
                    int nexty = y + dy[dir];
                    // 有障碍物
                    // calcHash(nextx, nexty) in blockers
                    if (blockers.find(calcHash(nextx, nexty)) != blockers.end()) {
                        break;
                    }
                    // 走一步
                    x = nextx;
                    y = nexty;
                    ans = max(ans, x * x + y * y);
                }
            } else if (cmd == -1) {
                // 0->1->2->3->0 
                // N->E->S->W->N
                // 右转(顺时针)
                dir = (dir + 1) % 4;
            } else {
                // 左转,避免负数,加一个mod数
                dir = (dir - 1 + 4) % 4;
            }
        }
        return ans;
    }

private:
    /*string calcHash(int x, int y) {
        return to_string(x) + "," + to_string(y);
    }*/
    long long calcHash(int x, int y) {
        return (x + 30000) * 60000ll + y + 30000; 
    }
};

lc146.LRU缓存–中等

题目描述

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。

实现 LRUCache 类:

  • LRUCache(int capacity)正整数 作为容量 capacity 初始化 LRU 缓存
  • int get(int key) 如果关键字 key 存在于缓存中,则返回关键字的值,否则返回 -1
  • void put(int key, int value) 如果关键字 key 已经存在,则变更其数据值 value ;如果不存在,则向缓存中插入该组 key-value 。如果插入操作导致关键字数量超过 capacity ,则应该 逐出 最久未使用的关键字。

函数 getput 必须以 O(1) 的平均时间复杂度运行。

示例:

输入
["LRUCache", "put", "put", "get", "put", "get", "put", "get", "get", "get"]
[[2], [1, 1], [2, 2], [1], [3, 3], [2], [4, 4], [1], [3], [4]]
输出
[null, null, null, 1, null, -1, null, -1, 3, 4]

解释
LRUCache lRUCache = new LRUCache(2);
lRUCache.put(1, 1); // 缓存是 {1=1}
lRUCache.put(2, 2); // 缓存是 {1=1, 2=2}
lRUCache.get(1);    // 返回 1
lRUCache.put(3, 3); // 该操作会使得关键字 2 作废,缓存是 {1=1, 3=3}
lRUCache.get(2);    // 返回 -1 (未找到)
lRUCache.put(4, 4); // 该操作会使得关键字 1 作废,缓存是 {4=4, 3=3}
lRUCache.get(1);    // 返回 -1 (未找到)
lRUCache.get(3);    // 返回 3
lRUCache.get(4);    // 返回 4

提示:

  • 1 <= capacity <= 3000
  • 0 <= key <= 10000
  • 0 <= value <= 105
  • 最多调用 2 * 105getput

相关补充

image-20231006135422553

image-20231006135431503

image-20231006135443864

思路讲解

image-20231006135851757

代码展示

public class LRUCache {
    class DLinkedNode {
        int key;
        int value;
        DLinkedNode prev;
        DLinkedNode next;
        public DLinkedNode() {}
        public DLinkedNode(int _key, int _value) {key = _key; value = _value;}
    }

    private Map<Integer, DLinkedNode> cache = new HashMap<Integer, DLinkedNode>();
    private int size;
    private int capacity;
    private DLinkedNode head, tail;

    public LRUCache(int capacity) {
        this.size = 0;
        this.capacity = capacity;
        // 使用伪头部和伪尾部节点
        head = new DLinkedNode();
        tail = new DLinkedNode();
        head.next = tail;
        tail.prev = head;
    }

    public int get(int key) {
        DLinkedNode node = cache.get(key);
        if (node == null) {
            return -1;
        }
        // 如果 key 存在,先通过哈希表定位,再移到头部
        moveToHead(node);
        return node.value;
    }

    public void put(int key, int value) {
        DLinkedNode node = cache.get(key);
        if (node == null) {
            // 如果 key 不存在,创建一个新的节点
            DLinkedNode newNode = new DLinkedNode(key, value);
            // 添加进哈希表
            cache.put(key, newNode);
            // 添加至双向链表的头部
            addToHead(newNode);
            ++size;
            if (size > capacity) {
                // 如果超出容量,删除双向链表的尾部节点
                DLinkedNode tail = removeTail();
                // 删除哈希表中对应的项
                cache.remove(tail.key);
                --size;
            }
        }
        else {
            // 如果 key 存在,先通过哈希表定位,再修改 value,并移到头部
            node.value = value;
            moveToHead(node);
        }
    }

    private void addToHead(DLinkedNode node) {
        node.prev = head;
        node.next = head.next;
        head.next.prev = node;
        head.next = node;
    }

    private void removeNode(DLinkedNode node) {
        node.prev.next = node.next;
        node.next.prev = node.prev;
    }

    private void moveToHead(DLinkedNode node) {
        removeNode(node);
        addToHead(node);
    }

    private DLinkedNode removeTail() {
        DLinkedNode res = tail.prev;
        removeNode(res);
        return res;
    }
}

/**
 * Your LRUCache object will be instantiated and called as such:
 * LRUCache obj = new LRUCache(capacity);
 * int param_1 = obj.get(key);
 * obj.put(key,value);
 */

图示理解

img

img

img

img

img

img

img

img

img

img

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

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

相关文章

提升您的 Go 应用性能的 6 种方法

优化您的 Go 应用程序 1. 如果您的应用程序在 Kubernetes 中运行&#xff0c;请自动设置 GOMAXPROCS 以匹配 Linux 容器的 CPU 配额 Go 调度器 可以具有与运行设备的核心数量一样多的线程。由于我们的应用程序在 Kubernetes 环境中的节点上运行&#xff0c;当我们的 Go 应用程…

美国各流域边界下载,并利用arcgis提取与处理

一、边界数据的下载 一般使用最普遍的流域边界数据是从HydroSHEDS官网下载: HydroBASINS代表一系列矢量多边形图层&#xff0c;以全球尺度呈现次级流域边界。该产品的目标是提供一种无缝的全球覆盖&#xff0c;其中包含了不同尺度&#xff08;从数十到数百万平方千米&#xf…

Docker 配置基础优化

Author&#xff1a;rab 为什么要优化&#xff1f; 你有没有发现&#xff0c;Docker 作为线上环境使用时&#xff0c;Docker 日志驱动程序的日志、存储驱动数据都比较大&#xff08;尤其是在你容器需要增删比较频繁的时候&#xff09;&#xff0c;动不动就好几百 G 的大小&…

P3-Python学习当中的两大法宝函数

P3-Python学习当中的两大法宝函数 实战操作 打开pycharm&#xff0c;在命令行当中先检测是否是在envs当中的pytorch环境里面&#xff0c;或者导入torch包是否成功 dir(torch)//展示torch以下的分隔的工具包证明torch目录以下有cuda包 dir(torch.cuda.is_available())//可以展示…

Springboot学生成绩管理系统idea开发mysql数据库web结构java编程计算机网页源码maven项目

一、源码特点 springboot 学生成绩管理系统是一套完善的信息系统&#xff0c;结合springboot框架和bootstrap完成本系统&#xff0c;对理解JSP java编程开发语言有帮助系统采用springboot框架&#xff08;MVC模式开发&#xff09;&#xff0c;系统 具有完整的源代码和数据库&…

golang gin——controller 模型绑定与参数校验

controller 模型绑定与参数校验 gin框架提供了多种方法可以将请求体的内容绑定到对应struct上&#xff0c;并且提供了一些预置的参数校验 绑定方法 根据数据源和类型的不同&#xff0c;gin提供了不同的绑定方法 Bind, shouldBind: 从form表单中去绑定对象BindJSON, shouldB…

【MVC】C# MVC基础知识点、原理以及容器和管道

给自己一个目标&#xff0c;然后坚持一段时间&#xff0c;总会有收获和感悟&#xff01; 国庆假期马上结束&#xff0c;闲暇时间&#xff0c;重温一遍C#关于MVC的技术&#xff0c;控制器、视图、模型&#xff0c;知识点和原理&#xff0c;小伙伴们还记得吗 目录 一、MVC知识点1…

纸质书籍OCR方案大揭秘,快来看看有哪些神奇的黑科技

随着数字化时代的来临&#xff0c;纸质书籍逐渐被电子书所替代。在将纸质书籍转换为电子格式的过程中&#xff0c;扫描电子书目录并进行文字识别&#xff08;OCR&#xff0c;Optical Character Recognition&#xff09;成为了一项重要的工作。OCR技术能够将纸质书籍中的文字内容…

如何使用 Overleaf 编写 LaTeX 文档

如何使用 Overleaf 编写 LaTeX 文档 &#x1f607;博主简介&#xff1a;我是一名正在攻读研究生学位的人工智能专业学生&#xff0c;我可以为计算机、人工智能相关本科生和研究生提供排忧解惑的服务。如果您有任何问题或困惑&#xff0c;欢迎随时来交流哦&#xff01;&#x1f…

Firefly-LLaMA2-Chinese - 开源中文LLaMA2大模型

文章目录 关于模型列表 & 数据列表训练细节增量预训练 & 指令微调数据格式 & 数据处理逻辑增量预训练指令微调模型推理权重合并模型推理部署关于 github : https://github.com/yangjianxin1/Firefly-LLaMA2-Chinese本项目与Firefly一脉相承,专注于低资源增量预训练…

模糊搜索利器:Python的thefuzz模块详解

文章目录 thefuzz模块简介thefuzz模块的参数和方法使用thefuzz实现模糊搜索在Python中,thefuzz模块是一个用于实现模糊搜索的强大工具。它可以帮助我们在处理字符串时,快速找到相似的匹配项。本文将详细介绍thefuzz模块的功能和用法,并结合代码示例演示如何实现模糊搜索。 t…

有自动交易股票的软件么,怎么实现全自动交易?

随着技术的发展&#xff0c;我们经常会在看到一些关于自动交易股票软件的宣传。那么&#xff0c;这些软件是否真的存在&#xff1f;如何实现全自动交易呢&#xff1f; 股票量化程序化自动交易接口 一、自动交易股票软件存在吗&#xff1f; 答案是有&#xff0c;部分券商已经对…

Python数据容器——集合的相关操作

作者&#xff1a;Insist-- 个人主页&#xff1a;insist--个人主页 本文专栏&#xff1a;Python专栏 专栏介绍&#xff1a;本专栏为免费专栏&#xff0c;并且会持续更新python基础知识&#xff0c;欢迎各位订阅关注。 目录 一、理解集合 1. 集合是什么&#xff1f; 2. 为什么…

typora + picgo + 对象存储 OSS

文章目录 一、安装软件二、使用阿里云 oss 存储图片三、picgo 设置四、typora 设置自动上传 一、安装软件 Typora1.3.8 &#xff08;安装即破解&#xff09; picgo 2.3.0 安装 阿里云盘&#xff08;软件安装包&#xff09;&#xff1a; https://www.aliyundrive.com/s/saQoS…

Windows10实用的12个快捷组合键

Windows10实用的12个快捷组合键 1、网页多标签切换 CTRL TAB 2、恢复不小心关闭的标签页 CTRLSHIFT T 3、新建标签页 CTRL T 4、高亮选择地址栏 ALT D 5、打开设置 WIN I 6、打开任务管理器 CTRLSHIFT ESC 7、打开文件资源管理器 WIN E 8、黑屏或屏幕卡顿无响应&#x…

python实验(超详细)

目录 实验一 python编程基础实验二 python序列、字符串处理实验三 函数及python类的定义与使用实验四 python综合应用 实验一 python编程基础 在交互式环境中打印“Hello world”字符串。记录操作过程。 略 创建脚本helloworld.py&#xff0c;在命令符提示环境中执行程序&…

【Oracle】Oracle系列十八--Oracle RAC

文章目录 往期回顾前言1. Oracle RAC介绍1.1 基本概念1.2 Oracle RAC应用场景1.3 Oracle RAC的优缺点 2. Oracle RAC架构3. Oracle RAC 的安装 往期回顾 【Oracle】Oracle系列之一–Oracle数据类型 【Oracle】Oracle系列之二–Oracle数据字典 【Oracle】Oracle系列之三–Orac…

CDN网络基础入门:CDN原理及架构

背景 互联网业务的繁荣让各类门户网站、短视频、剧集观看、在线教育等内容生态快速发展&#xff0c;互联网流量呈现爆发式增长&#xff0c;自然也面临着海量内容分发效率上的挑战&#xff0c;那么作为终端用户&#xff0c;我们获取资源的体验是否有提升呢&#xff1f; 答案是…

网络层·IP协议

承接前文TCP协议-CSDN博客 简介 协议头格式 网段划分(重要) 划分方法 IP地址的数量限制(背景介绍) 私有IP地址和公网IP地址(提出解决思路) NAT技术(解决方法) 路由 网络层 在复杂的网络环境中确定一个合适的路径 IP协议 主机: 配有IP地址, 可以认为就是你的电脑; 路由器:…

2.SpringBoot项目搭建

SpringBoot项目搭建 JavaEE对新手非常友好的 搭建框架。 集成了JavaEE开发中大部分的功能。 1.进行创建 2.进行配置 点击创建&#xff0c;springboot项目创建完成&#xff0c;下篇是安装lombok & maven镜像设置 设置完成后之后便可以启动项目了。 3.各个部分说明