hot100——双指针法专题

3.无重复字符的最长子串

解题思路

本题主要还是用到了滑动窗口+双指针的方法

python代码思路

首先构造哈希表,在python中哈希表一般用set或者dict来表示:

  • 哈希表 :Python 的 setdict 都是基于哈希表实现的。

    • 当只需要记录元素是否存在时,用 set

    • 当需要记录元素的位置或其他附加信息时,用 dict(如 char -> index)。

在"无重复字符的最长子串"中,最简单的做法是用 set 存储当前窗口内的字符。当遇到重复字符时,从 set 中移除左指针指向的字符,直到重复字符被移出

C++代码思路

在C++中一般是使用unordered_set或者是unordered_map作为哈希表来进行映射的。

  • 哈希表 :C++ 标准库提供 std::unordered_set(无序集合)和 std::unordered_map(无序映射),底层也是哈希表。

具体思路和上述基本一致,但是还是存在细微差别:

首先遍历字符串s,并且在哈希表中对当前字符的出现次数进行计数,如果当前字符的出现次数大于1的话,证明当前字符在前面已经出现过,因此需要从 unordered_map 中移除左指针指向的字符,直到重复字符被移出。

代码

python

python 复制代码
class Solution(object):
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        c = set()
        left, maxlen = 0, 0
        for right in range(len(s)):
            while s[right] in c:
                c.remove(s[left])
                left += 1
            c.add(s[right])
            maxlen = max(maxlen, right - left + 1)
        return maxlen

C++

cpp 复制代码
class Solution {
public:
    int lengthOfLongestSubstring(string s) {
        unordered_map<char, int> cnt;
        int left = 0;
        int n = s.size();
        int maxlen = 0;
        for(int right = 0;right < n;right++)
        {
            char c = s[right];
            cnt[c]++;
            // 说明当前窗口中存在重复元素
            while(cnt[c] > 1)
            {
                cnt[s[left]]--;// 移除窗口左边的字符
                left++;// 窗口缩小
            }
            maxlen = max(maxlen, right - left + 1);
        }
        return maxlen;

    }
};

5.最长回文子串

解题思路

我们用中心扩展法,因为如果是回文字符串的话,那么从中心往两边走的话,逐步比较左右元素是否相同,这样就可以找到最长回文子串。

而关于中心的话:

对于一个长度为n的字符串,回文的中心可以分为以下2类:

  • 字符中心 :每个字符本身可以作为一个奇数长度回文的中心,例如 "aba" 的中心是 'b'。一共有 n 个这样的中心。
  • 间隙中心 :每两个相邻字符之间的位置可以作为一个偶数长度回文的中心,例如 "abba" 的中心在 'b''b' 之间。一共有 n-1 个这样的中心。

所以总的中心数是n+n-1=2n-1

那么如何一个循环遍历所有中心呢?

我们用一个整数 i02n-2(共 2n-1 个值)来代表所有中心。

关键是将 i 映射到左右指针 (l, r),使得:

当i为奇数的时候,中心落在2个字符的间隙;(偶数回文串)

当i为偶数时,中心落在1个字符上;(奇数回文串)

python 复制代码
l = i // 2
r = (i + 1) // 2

当i = 2k(偶数)时,l = k,r = k,此时中心在s[k]上;

当i = 2K +1(奇数)时,l = k,r = k + 1,此时中心落在s[k],s[k+1]之间。

这样一个i就对应了一个中心。

代码

python(注意python字符串区间是左闭右开)

python 复制代码
class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        n = len(s)
        ans_left, ans_right = 0, 0
        for i in range(2*n - 1):
            l, r = i//2, (i+1)//2
            while l>=0 and r<n and s[l] == s[r]:
                l -= 1
                r +=1
            if r - l -1 > ans_right - ans_left:
                ans_left, ans_right = l+1, r  # 左闭右开
        return s[ans_left:ans_right]

C++(取子串用的是substr[起始位置,长度])

cpp 复制代码
class Solution { 
public:
    
    string longestPalindrome(string s) {
        // 由中间向两边回溯
        int n = s.size();
        int ans_left = 0;
        int ans_right = 0;
        for(int i = 0; i < 2*n -1; i++)
        {
            int l = i / 2;
            int r = (i+1)/2;
            while(l>=0&&r<n&&s[l]==s[r])
            {
                l--;
                r++;
            }
            if(r - l - 1 > ans_right - ans_left)
            {
                ans_left = l+1;
                ans_right = r - 1;
            }
        }

        return s.substr(ans_left, ans_right - ans_left + 1);

    }
};

11.盛最多水的容器

解题思路

首先,盛最多水的容器,容器的盛水量从题目中得到的是应该是两边的最小值*对应的下标差,

比如min(height[i], height[j]) * (j - i)

取i和j分别为height数组的2端,然后同时向内运动,直接i和j相遇。

而在此过程中,究竟是移动长的,还是短的那部分呢?

移动长的,min(height[i], height[j])可能不变或者更小,但是盛水量一定变小;而移动短的那部分,min(height[i], height[j])可能不变或者更大,盛水量可能变大。

算法流程

初始化:设定i, j分别为是水槽的两端

循环收窄:直到i, j相遇时跳出循环

更新面积值;

选两端中较短的那部分,往中间收窄一格;

返回值:返回面积最大值res

代码

python

python 复制代码
class Solution(object):
    def maxArea(self, height):
        """
        :type height: List[int]
        :rtype: int
        """
        i, j = 0, len(height) - 1
        res = 0
        while i < j:
            if height[i] < height[j]:
                res = max(res, height[i] * (j - i))
                i += 1
            else:
                res = max(res, height[j] * (j - i))
                j -= 1
        return res

C++

cpp 复制代码
class Solution {
public:
    int maxArea(vector<int>& height) {
        int i = 0;
        int j = height.size() - 1;
        int res = 0;
        while(i < j)
        {
            if(height[i] < height[j])
            {
                res = max(res, height[i]*(j - i));
                i++;
            }
            else
            {
                res = max(res, height[j]*(j - i));
                j--;
            }
        }
        return res;
    }
};

15.三数之和

解题思路

题中要求在数组中是否存在三元数能够使得nums[i] + nums[j] + nums[k] == 0,且i != j!= k;

根据题意,我们先给整个数组排序 (按从小到大的顺序排序)

取三个数k ,i , j

初始化:取k遍历整个数组,而i , j分别在数组的两端。

循环判定

结束条件:i==j

若nums[k] == nums[k-1],跳过相等的数,因为整个组合都是相同的,重复了;

取i = k+1 , j = nums.size() -1;

判断s = nums[k] + nums[i] + nums[j] ?= 0

若大于0,则需要j往中间靠,同时一样要判定nums[j]==nums[j+1],以防重复;

若小于0,则需要i往中间靠,同时一样要判定nums[i] == nums[i-1],以防重复;

若等于0,则将当前的结果存入结果中,i,j同时往中间靠,但也要同时判断nums[j]==nums[j+1]、nums[i] == nums[i-1],以防重复。

返回值:返回存入的列表

代码

C++

cpp 复制代码
class Solution {
public:
    vector<vector<int>> threeSum(vector<int>& nums) {
        // 排序
        sort(nums.begin(), nums.end());
        vector<vector<int>> res;
        if(nums.size() < 3)
            return res;
        for(int k = 0;k<nums.size()-2;k++)
        {
            if(nums[k]>0) 
                break; // j > i > k
            if(k>0 && nums[k] == nums[k-1])//跳过nums[k]==nums[k-1]的值,跳过相等的值
                continue;
            int i = k + 1;
            int j = nums.size() - 1;
            while(i < j)
            {
                int s = nums[k] + nums[i] + nums[j];
                if(s < 0)
                {
                    i++;
                    while(i < j && nums[i] == nums[i-1])
                    {
                        i++;
                    }
                }
                else if(s > 0)
                {
                    j--;
                    while(i < j && nums[j] == nums[j+1])
                    {
                        j--;
                    }
                }
                else
                {
                    res.push_back({nums[k],nums[i],nums[j]});
                    i++;
                    j--;
                    while(i < j && nums[i] == nums[i-1])    i++;
                    while(i < j && nums[j] == nums[j+1])    j--;
                }
            }
            
        }
        return res;

    }
};

python

python 复制代码
class Solution(object):
    def threeSum(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        nums.sort()
        res, k = [], 0
        for k in range(len(nums) -2):
            if len(nums)<3:
                break
            if nums[k] > 0:
                break
            # 判断是否重复
            if k > 0 and nums[k] == nums[k-1]:
                continue
            i, j= k + 1, len(nums) - 1
            while i < j:
                s = nums[k] + nums[i] + nums[j]
                if s < 0:
                    i += 1
                    while i < j and nums[i] == nums[i-1]:
                        i += 1
                elif s > 0:
                    j -= 1
                    while i < j and nums[j] == nums[j+1]:
                        j -= 1
                else:
                    res.append([nums[k], nums[i], nums[j]])
                    i += 1
                    j -= 1
                    while i < j and nums[i] == nums[i-1]: i += 1
                    while i < j and nums[j] == nums[j+1]: j -= 1
        return res
         

75.颜色分类

解题思路------边界覆盖

题目的要求最后要实现的效果是[0,0,0,0,0,......,1,1,1,1,1,......,2,2,2,2,2]

也就是三个连续区域红色、白色、蓝色。

初始化

开始的时候我们需要维护以下2个变量:

p1:下一个1应该放置的位置(白色区域的边界)

p0:下一个0应该放置的位置(红色区域的边界)

i:当前位置;

开始p1=p0=i = 0,红色、白色区域都是空。

遍历整个数组

取当前元素的值保存,并把当前位置的值设置为蓝色。

将当前值与1和0作比较,若<=1,说明它不应该在这个位置,应该放到前面的红色/白色区域,那么则在p1的位置置1,p1++;

若当前值==0,说明当前值应该放到前面的红色区域去,则在p0的位置置0,p0++。

疑问------为什么当前值为0时,还是要先经过nums[p1++] = 1??

首先p0, p1代表红色白色边界,当当前值为0时,因为p0代表红色区域的边界,那么当前值放到红色区域就会和白色区域的第一个元素重叠,导致白色区域第一个数值被覆盖,使得整体报错;

因此,我们需要让p1先往右边移一位,这样当把0放到p0边界的时候,1的**数值区域已经是右移了一位,原本的1值不会被覆盖,**能够避免上述情况的发生。

代码

python

python 复制代码
class Solution(object):
    def sortColors(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        p0, p1 = 0, 0
        for i,x in enumerate(nums):
            nums[i] = 2
            if x<=1:
                nums[p1] = 1
                p1 += 1
            if x==0:
                nums[p0] = 0
                p0 += 1
                

C++

cpp 复制代码
class Solution {
public:
    void sortColors(vector<int>& nums) {
        int p0 = 0;
        int p1 = 0;
        for(int i = 0;i<nums.size();i++)
        {
            int x = nums[i];
            nums[i] = 2;
            if(x <= 1)
                nums[p1++] = 1;
            if(x==0)
                nums[p0++] = 0;

        }
    }
};

解题思路------三指针

取左右指针left, right,分别指向数组的开头以及结尾,对于数组中为0的数值和left指针指向值进行交换,对于数组中为2的数值和right指针指向的值进行交换。

三指针法的分区定义

  • [0, left):已经排好的 0

  • [left, i):已经排好的 1

  • [i, right]:待处理的元素

  • (right, n-1]:已经排好的 2

初始:left = 0i = 0right = n-1。

为什么与 left 交换后可以 i++,而与 right 交换后 i 不动?

关键在于交换来的元素是否"已知"。

  • 与 left 交换left 指向的元素来自 已处理过的 1 区域 (或自身)。

    根据分区定义,[left, i) 区间内的元素都是 1(或者为空)。所以 nums[left] 的值只能是 1 (如果 left < i)或者就是 nums[i] 本身(如果 left == i,此时值为 0)。

    交换后,nums[i] 变成 1(或保持 0),这个值是已经"就绪"的,不需要再次检查,因此可以放心地 i++ 去处理下一个位置。

  • 与 right 交换right 指向的元素来自 尚未处理的区域 [i, right]

    这个区域的值可能是 0、1 或 2,完全未知。交换后,nums[i] 变成了一个未检查过的新值 ,必须留在当前位置重新判断,所以不能 i++,只能 right-- 缩小右边的 2 区域。

在三指针法(荷兰国旗问题)中,lefti 的初始值都为 0。随着算法进行,left 始终指向第一个不是 0 的位置 (即 1 区域的起点),而 i 指向当前正在检查的元素。它们的关系是:left ≤ i。当 left == i 时,表示 1 区域为空,当前检查的位置正好是 0 区域的边界。

代码

python

python 复制代码
class Solution(object):
    def sortColors(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        '''
        p0, p1 = 0, 0
        for i,x in enumerate(nums):
            nums[i] = 2
            if x<=1:
                nums[p1] = 1
                p1 += 1
            if x==0:
                nums[p0] = 0
                p0 += 1
        '''
        n = len(nums)
        left, right = 0, n -1
        i = 0
        while i <= right:
            if nums[i] == 0:
                nums[i], nums[left] = nums[left], nums[i]
                left += 1
                i += 1
            elif nums[i] ==  2:
                nums[i], nums[right] = nums[right], nums[i]
                right -= 1
            else:
                i += 1

C++

cpp 复制代码
class Solution {
public:
    void sortColors(vector<int>& nums) {
        /*
        int p0 = 0;
        int p1 = 0;
        for(int i = 0;i<nums.size();i++)
        {
            int x = nums[i];
            nums[i] = 2;
            if(x <= 1)
                nums[p1++] = 1;
            if(x==0)
                nums[p0++] = 0;

        }
        */
        int left = 0;
        int right = nums.size() - 1;
        int i = 0;
        while(i<= right)
        {
            if(nums[i]==0)
            {
                swap(nums[i],nums[left]);
                left++;
                i++;
            }
            else if(nums[i] == 2)
            {
                swap(nums[i], nums[right]);
                right--;
            }
            else{
                i++;
            }
        }
    }
};

76.最小覆盖子串

解题思路------滑动窗口

由题意可知,我们需要的是在母串S中找到包含子串t中每一个字符的最小子串,如果没有则返回""。

这道题明显应该使用滑动窗口来解决,具体思路如下:

首先统计子串t中每个字符的出现次数,用unordered_map need来表示,以及用valid来记录t中每种字符的种类,用start以及len来表示最小子串的起点以及长度;

遍历s,如果当前字符是需要的字符,则更新当前窗口中该字符的值,并判断当前字符的出现次数和need中是否一致,若一致,则valid++。

当valid的值等于t中的字符种类的时候,这个时候我们已经找到了满足条件的子串,但并非是最优解,因此需要我们不断更新迭代判断。

若valid值等于t中字符的个数,则 更新最小子串:起始点,最小长度。

然后不断缩小这个满足条件的次优解子串,判断每一次缩小窗口时弹出的元素的值是否是子串计数need中的值?若是,如果窗口中该数的值和need中相等,那么由于该数的滑出,valid必须要--,因此此时的窗口不满足条件了。

最后返回滑动之后得到的最优解。

deepseek的总结:

  1. 初始化left=0, right=0, valid=0,窗口为空。

  2. 外层 while(右指针移动)

    • 取字符 c = s[right],右移 right

    • 如果 c 是需要的字符,增加 window[c],并检查是否恰好达到需求(window[c] == need[c]),若是则 valid++

  3. 内层 while(当窗口可行时,尝试收缩左边界)

    • 记录当前窗口长度(right - left),如果比 minLen 小,则更新 startminLen

    • 准备移出左边界字符 d = s[left],左移 left

    • 如果 d 是需要的字符,且移出前 window[d] == need[d](即移出后就不够了),则 valid--,然后 window[d]--

    • 继续收缩,直到窗口不再可行(valid < need.size())。

  4. 重复 ,直到 right 到达末尾。

  5. 返回 s.substr(start, minLen)

代码

C++------窗口:左闭右开

这里需要注意一个地方,就是在C++中我们的代码是:

while(right < s.size())

{

char c = s[right++];

right指向的永远是下一个,最后是s.size()对应的部分,所以C++中窗口是[left, right),是左闭右开

所以对应的窗口长度是right - left。

python------窗口:左闭右闭

python代码则是如下:

for right,c in enumerate(s):

right永远是当前数组的元素,不会出现越界情况。因此对应的窗口是[left, right],是左闭右闭。

对应的窗口长度是right - left + 1。

python

python 复制代码
class Solution(object):
    def minWindow(self, s, t):
        from collections import defaultdict
        """
        :type s: str
        :type t: str
        :rtype: str
        """
        left, right = 0, 0
        start = 0
        minlen = float('inf')
        valid = 0
        need = defaultdict(int) 
        window = defaultdict(int) 

        # 统计t中每个字符的出现的数量
        for ch in t:
            need[ch]+=1

        # 滑动窗口
        for right,c in enumerate(s):
            if c in need:
                window[c] += 1
                if window[c] == need[c]:
                    valid += 1

            # <==============注意python是左闭右开的区间========================>
            # 窗口中亦含有t中所有元素,缩小左边界,优化,以得到最优解
            # right - left +1: 当前窗口的长度
            while valid== len(need):
                if right - left +1 < minlen:
                    start = left
                    minlen = right - left + 1
                d = s[left]
                left += 1
                # 当d是t中的元素的时候再做下面的判断、处理
                if d in need:
                    if window[d]==need[d]:
                        valid -= 1
                    window[d] -= 1
        
        return "" if minlen==float('inf') else s[start:start+minlen]

            
            

C++

cpp 复制代码
class Solution {
public:
    string minWindow(string s, string t) {
        unordered_map<char, int> need, window;
        int valid = 0; //字符串t中的字符种类数目
        int start = 0;
        int minLen = INT_MAX;
        int left = 0;
        int right = 0;

        for(char c : t)
            need[c]++;
        //寻找满足条件的最小覆盖字串
        while(right < s.size())
        {
            char c = s[right++];

            //若当前字符是need中需要的,则进行下一步
            //当前字符的数目和need中次数一致,则有效种类数目+1
            if(need.count(c))
            {
                window[c]++;
                if(window[c] == need[c])
                    valid++;
            }

            // 更新得到最优解
            while(valid==need.size())
            {
                if(right - left < minLen)
                {
                    start = left;
                    minLen = right - start;
                }

                char d = s[left];
                left++;
                //移出前满足,移除后便不满足,因此valid需要-1
                if(need.count(d))
                {
                    if(window[d] == need[d])
                        valid--;
                    window[d]--;
                }

                
            }
        }
        return minLen==INT_MAX? "": s.substr(start, minLen);

    }
};

283.移动零

解题思路

题目中要求必须在不复制数组的情况下原地对数组进行操作,那就是要求空间复杂度时O(1),此处我们使用一次遍历:

这里参考了快速排序的思路:快速排序是选取一个中间点x,把小于等于x的结果放到x的左边,把大于x的结果放到x的右边。

那么这道题,我们选取0作为这个中间点,不等于0的数放到数组的左边,那么余下的数放到0的右边。

我们取i, j这两个指针,遍历nums中不是0的数,将nums[i]的值和nums[j]的值做交换。

代码

python

python 复制代码
class Solution(object):
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: None Do not return anything, modify nums in-place instead.
        """
        if nums is None:
            return
        j = 0
        for i in range(len(nums)):
            if nums[i] != 0:
                t = nums[i]
                nums[i] = nums[j]
                nums[j] = t
                j += 1
        

C++

cpp 复制代码
class Solution {
public:
    void moveZeroes(vector<int>& nums) {
        if(nums.empty())
            return;
        // 两个指针i, j
        int j = 0;
        for(int i =0; i < nums.size();i++){
            // 把nums[i]中不等于0的值放到前面,之后的就都是0
            if(nums[i] != 0)
            {
                int t = nums[i];
                nums[i] = nums[j];
                nums[j++] = t;
            }
        }
    }
};

参考

动画演示 283.移动零

287.寻找重复数

解题思路

本题其实还是使用双指针法,但是在这个地方,需要理清以下情况:

对于任意的数组,按照当前下标--->当前下标所指向的值,这样可以构成序列。

题目中nums含有n+1个数,下标从0~n,数值是[1, n],其中只有一个整数出现2次或者更多,其余正数均只出现一次。

如果nums中出现了不同下标对应的值相同 的情况,那么这个nums所对应的序列中就会出现

重复的数就是这个环的入口。

举例说明一下:

nums = [1, 3, 4, 2 , 2]

下标 值

0 1

1 3

2 4

3 2

4 2

形成的序列就是:

0 -> 1 -> 3 -> 2 -> 4

| |

4 <- 2

最后一个徘徊在2-4-2-4-2......这个环当中,其中环的入口就是2,也就是nums中的重复的数。

那么如何得到这个重复的数呢?

首先,我们取快慢指针fast, slow;

初始化:快慢指针都初始化为0,然后快指针每一次往前走2步,而慢指针每一次往前走1步。

如果有重复元素的话,那么快慢指针最终一定会在环内某个部分相遇,假设快慢指针最终在据环的入口处c相遇:

假设环外的元素长度是a ,环的长度是b,那么

快指针走过的距离:a+m*b + c

慢指针走过的距离:a+n*b + c

其中n一定小于m。

由上述2个式子可以得到a+m*b + c = 2(a+n*b + c) ====> a+c = (m-n)*b ==>a+c是环的整数倍长度

那如何得到这个重复元素呢?

我们让一个元素从起点开始走(pre1),让另一个元素从slow和fast指针相遇的地方开始走(pre2)。

当pre1走过的距离是a,到达环的入口处时,那么pre2走过的距离是c+a, 而c+a正好是换的长度的整数倍,也就是说此时pre2也正好走到了环的入口处,所以这俩一定会在环的入口处相遇,最终pre1指向的值就是nums中的重复元素。

代码

python

python 复制代码
class Solution(object):
    def findDuplicate(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        # 快慢指针都从起点开始出发,快指针一次走2步,慢指针一次走1步
        fast, slow = 0, 0
        fast = nums[nums[fast]]
        slow = nums[slow]
        while fast != slow:
            fast = nums[nums[fast]]
            slow = nums[slow]
        
        # 这时快慢指针相等,也即找了重复元素
        pre1, pre2 = 0, slow
        while pre1 != pre2:
            pre1 = nums[pre1]
            pre2 = nums[pre2]
        
        # 找到了重复元素pre1 = nums[pre1]
        return pre1

C++

cpp 复制代码
class Solution {
public:
    int findDuplicate(vector<int>& nums) {
        int slow = 0;
        int fast = 0;
        slow = nums[slow];
        fast = nums[nums[fast]];
        while(slow != fast)
        {
            slow = nums[slow];
            fast = nums[nums[fast]];
        }

        int pre1 = 0;
        int pre2 = slow;
        while(pre1 != pre2)
        {
            pre1 = nums[pre1];
            pre2 = nums[pre2];
        }
        return pre1;
    }
};

参考

287.寻找重复数

647.回文子串

解题思路

本题思路和最长回文子串的思路一致,我们使用的是中心扩展法,其中这里的中心有2*n-1个,为什么有这么多中心,可以看我上面的最长回文子串的讲解,里面有,在这个地方我们只需要在每一个判断是回文串的时候,计数就行。

代码

python

python 复制代码
class Solution(object):
    def countSubstrings(self, s):
        """
        :type s: str
        :rtype: int
        """
        n = len(s)
        count = 0
        # 中心扩展法
        for i in range(2*n-1):
            left = i // 2
            right = (i+1)//2
            while left >= 0 and right < n and s[left]==s[right]:
                count += 1
                left -= 1
                right += 1
        
        return count

C++

cpp 复制代码
class Solution {
public:
    int countSubstrings(string s) {
        int left = 0;
        int right = 0;
        int count = 0;
        // 中心扩展法
        for(int i = 0;i < (2*(s.size()) - 1);i++)
        {
            left = i / 2;
            right = (i + 1) / 2;
            while(left>=0 && right<s.size()&&s[right]==s[left])
            {
                left--;
                right++;
                count++;
            }
        }
        return count;
    }
};
相关推荐
KevinCyao2 小时前
Ruby短信营销接口示例代码:Ruby开发环境下营销短信API接口的集成与Demo演示
开发语言·前端·ruby
M1nat0_2 小时前
Linux基础 Ext 文件系统:从磁盘硬件到目录路径的全链路解析
linux·服务器·网络·数据库
蜡台2 小时前
macOS 无法启动 MySQL服务解决
数据库·mysql·macos
执笔论英雄2 小时前
vLLM V1 Scheduler的调度逻辑&优先级分析
数据库·mysql
Omics Pro2 小时前
基因集(模块)活性量化:R语言+Java原生
大数据·开发语言·前端·javascript·数据库·r语言·aigc
chushiyunen2 小时前
llama-index 数据清洗示例、数据清洗等
java·大数据·llama
wdfk_prog2 小时前
MCU内核电压不稳导致程序跑飞的现象、原因与影响
数据库·单片机·嵌入式硬件
晓13132 小时前
React篇——第六章 React进阶特性与状态管理
前端·react.js·性能优化
zhangphil2 小时前
Kotlin高阶函数作为参数与Java普通接口interface等效性
java·kotlin