代码随想录算法训练营第二十八天 | Leetcode随机抽题检测

news2025/1/16 8:09:59

Leetcode随机抽题检测--使用题库:Leetcode热题100

  • 1 两数之和
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 49 字母异位词分组
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 128 最长连续序列
    • 未看解答自己编写的青春版
    • 重点
      • 关于 left 和 right 的疑问?
      • 为什么只需要更新 num-left 和 num+right ?
    • 题解的代码
    • 日后再次复习重新写
  • 283 移动零
  • 11 盛最多水的容器
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 15 三数之和
  • 42 接雨水
    • 未看解答自己编写的青春版
    • 重点
    • 自己理解后的代码,这部分代码都是按我自己的风格编写的,会和题解有一些出入,比如大部分题解中,位置 i 的左右最大高度,初始值就是height[i],考虑了自己,但我没有考虑自己,初始值是0
      • 要注意这种双指针法的编写逻辑,和上一题,"盛最多水的容器",相似。如何确定是移动 left 还是 right ? 看当前 mexleft 和 maxright 哪个小。因为我们在计算当前位置所能接的雨水时,首先要判断 min(maxleft , maxright) ,那么当前应该计算的雨水位置,就是小值的那一侧,假如maxleft小,那么不管后面的循环中,maxright再如何变化,在当前left处,min(maxleft , maxright) 的值不会再变化了(注意,当前left位置的maxleft,是由该位置之前的元素值决定的),所以,如果maxleft小,那么就计算left处的雨水,然后更新maxleft,然后移动left。right同理。
      • 本题要让0入栈,不让0入栈是不自然的,然后计算当前能承接水的体积的方式是:当前最外层遍历的元素是 i , 叫做right ,pop()出来的元素是 mid (这个值也是下标) , 当前单调栈stack内 (pop后的单调栈,单调栈的栈顶元素 stack[-1] ),此时的栈顶元素 stack[-1],叫做 left (这个值也是下标) 。计算以当前位置 mid 为底,所能承载的水的体积是:(min(nums[left] , nums[right]) - nums[mid]) * (right-left-1) 。
    • 两篇题解的地址
    • 日后再次复习重新写
  • 84 柱状图中最大的矩形
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 3 无重复字符的最长子串
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 438 找到字符串中所有字母异位词
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 560 和为 K 的子数组
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 239 滑动窗口最大值
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 76 最小覆盖子串
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 53 最大子数组和
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 56 合并区间
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 189 轮转数组
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 238 除自身以外数组的乘积
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 41 缺失的第一个正数
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 73 矩阵置零
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 54 螺旋矩阵
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 48 旋转图像
    • 未看解答自己编写的青春版
    • 重点
    • 题解的代码
    • 日后再次复习重新写
  • 240 搜索二维矩阵 II
    • 未看解答自己编写的青春版
    • 重点
      • 还是这种思路厉害,时间复杂度是O(n),我的方法严格来说,还是O(n^2)
    • 题解的代码
    • 日后再次复习重新写

1 两数之和

未看解答自己编写的青春版

哈希哈希,觉得这题应该不用去看题解了。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        table = {}
        n = len(nums)
        for i in range(n):
            if len(table) == 0 :
                table[nums[i]] = table.get(nums[i],0) + i
            else :
                temp = target - nums[i]
                if temp in table :
                    return [i,table[temp]]
                else :
                    table[nums[i]] = table.get(nums[i],0) + i
        return None

重点

题解的代码

日后再次复习重新写

49 字母异位词分组

未看解答自己编写的青春版

但是时间上仅打败5%,是哪里出了问题?好像也没法加速了啊

class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        if len(strs) == 1 :
            return [strs]
        strs_sorted = [sorted(i) for i in strs]
        n = len(strs)
        used = [False]*n
        res = []
        for i in range(n):
            if used[i] == False :
                level = [strs[i]]
                used[i] = True
                for j in range(i+1,n):
                    if used[j] == False :
                    # 这句比较,引起了时间花费比字典直接索引大很多
                        if strs_sorted[i]==strs_sorted[j] :
                            level.append(strs[j])
                            used[j] = True
            
                res.append(level)

        return res

重点

为什么用了字典,就比我的used数组快呢?

我目前认为是:if strs_sorted[i]==strs_sorted[j] :

这句比较,引起了时间花费比字典直接索引大很多

题解的代码

class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        dic = {}
        for s in strs:
            keys = "".join(sorted(s))
            if keys not in dic:
                dic[keys] = [s]
            else:
                dic[keys].append(s)
        return list(dic.values())

日后再次复习重新写

128 最长连续序列

未看解答自己编写的青春版

没思路。错误的代码:

class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        maxlength = 1
        table = {}
        for i in nums :
            if i not in table :
                table[i] = 1
                if i-1 in table :
                    table[i] += table[i-1]
                    table[i-1] = table[i]
                if i+1 in table :
                    table[i] += table[i+1]
                    table[i+1] = table[i]
                
            maxlength = max(maxlength,table[i])
            print(table)
        return maxlength

重点

在这里插入图片描述

关于 left 和 right 的疑问?

代码中 if num not in hash_dict就保证了 left 和 right 不会有交叠 进来的这个值没有在字典中出现过,意味着目前还没有任何区间包含这个值,如果 left 和 right 出现重叠了的,就意味着这个值之前已经在区间中了,矛盾了。

不可能有交叉,不可能一个没出现过的数,既属于left又属于right

为什么只需要更新 num-left 和 num+right ?

因为我们在判断时,只看当前数的前一个数和后一个数,所以在更新时,只需要更新边界,不在序列中的新数如果要使用已有的最大长度,一定会碰到边界,碰不到边界,那么值一定就是 1 。

题解的代码

利用 get 函数,可以少写很多判断的风格:

class Solution(object):
    def longestConsecutive(self, nums):
        hash_dict = dict()
        
        max_length = 0
        for num in nums:
            if num not in hash_dict:
                left = hash_dict.get(num - 1, 0)
                right = hash_dict.get(num + 1, 0)
                
                cur_length = 1 + left + right
                if cur_length > max_length:
                    max_length = cur_length
                
                hash_dict[num] = cur_length
                hash_dict[num - left] = cur_length
                hash_dict[num + right] = cur_length
                
        return max_length

判断 i-1 和 i+1 的风格:

class Solution {
public:
    int longestConsecutive(vector<int>& nums) {
        unordered_map<int,int> consecutive;
        int maxlong=0;
        for(int x:nums){
            if(consecutive.count(x)) continue;
            int nowlong=1;
            if(consecutive.count(x+1)&&consecutive.count(x-1)){
                nowlong+=consecutive[x+1]+consecutive[x-1];
                consecutive[x-consecutive[x-1]]=nowlong;
                consecutive[x+consecutive[x+1]]=nowlong;
            }
            else{
                if(consecutive.count(x-1)){
                    nowlong+=consecutive[x-1];
                    consecutive[x-consecutive[x-1]]=nowlong;
                }
                if(consecutive.count(x+1)){
                    nowlong+=consecutive[x+1];
                    consecutive[x+consecutive[x+1]]=nowlong;
                }
            }
            consecutive[x]=nowlong;
            maxlong=max(maxlong,nowlong);
        }
        return maxlong;
    }
};

看了解答后,自己又写了一遍的风格:

class Solution:
    def longestConsecutive(self, nums: List[int]) -> int:
        maxlength = 0
        table = {}
        for i in nums :
            if i not in table :
                if i-1 in table and i+1 in table :
                    table[i] = table[i-1] + table[i+1] + 1
                    table[i-table[i-1]] = table[i] 
                    table[i+table[i+1]] = table[i]                
                elif i-1 in table :
                    table[i] = table[i-1] + 1
                    table[i-table[i-1]] = table[i]
                elif i+1 in table :
                    table[i] = table[i+1] + 1
                    table[i+table[i+1]] = table[i]
                else :
                    table[i] = 1

                
            maxlength = max(maxlength,table[i])
            
        return maxlength

日后再次复习重新写

283 移动零

双指针,过

11 盛最多水的容器

未看解答自己编写的青春版

没思路,知道是双指针,但是不清楚怎么移动。

看了解答后明白了,让高小的移动。

重点

对O(n)的算法写一下自己的理解,一开始两个指针一个指向开头一个指向结尾,此时容器的底是最大的,接下来随着指针向内移动,会造成容器的底变小,在这种情况下想要让容器盛水变多,就只有在容器的高上下功夫。 那我们该如何决策哪个指针移动呢?我们能够发现不管是左指针向右移动一位,还是右指针向左移动一位,容器的底都是一样的,都比原来减少了 1。这种情况下我们想要让指针移动后的容器面积增大,就要使移动后的容器的高尽量大,所以我们选择指针所指的高较小的那个指针进行移动,这样我们就保留了容器较高的那条边,放弃了较小的那条边,以获得有更高的边的机会。

class Solution:
    def maxArea(self, height: List[int]) -> int:
        maxv = 0
        n = len(height)
        left = 0
        right = n-1
        while left < right :
            value = min(height[left],height[right])*(right-left)
            maxv = max(maxv,value)
            if height[left] >= height[right] :
                right -= 1
            else :
                left += 1
        return maxv

题解的代码

日后再次复习重新写

15 三数之和

过。

42 接雨水

未看解答自己编写的青春版

不会。

重点

这道题是属于双指针法的题目,但是还是不清楚怎么用双指针,根本原因是对如何计算雨水,不清楚。

诸如类似计算雨水的题目,有两种计算方式,横向和竖向。
在这里插入图片描述

本题,我将会学习四种解法,暴力,DP,双指针,单调栈。其中,前三种方法属于一类,DP和双指针其实都是对暴力的优化,在本题上并没有体现出自身方法的优势。单调栈的使用,本题是一个很经典的题目。

需要注意的是,因为前三种方法,我们要做的都是依次遍历数组,所以使用的计算方式是:按列计算雨水,这也是符合直觉的。

单调栈因为涉及弹入弹出,是按行计算雨水。

自己理解后的代码,这部分代码都是按我自己的风格编写的,会和题解有一些出入,比如大部分题解中,位置 i 的左右最大高度,初始值就是height[i],考虑了自己,但我没有考虑自己,初始值是0

暴力法:超时

class Solution:
    def trap(self, height: List[int]) -> int:
        total = 0
        n = len(height)
        # 第一个和最后一个不可能接雨水
        for i in range(1,n-1):
            maxleft = 0
            maxright = 0
            j = i-1
            while j > -1 :
                maxleft = max(maxleft,height[j])
                j -= 1
            j = i+1
            while j < n :
                maxright = max(maxright,height[j])
                j += 1
            # 由于我前面编写的风格,要将结果和0做个判断,只保留非负数
            total += max(min(maxleft,maxright)-height[i],0)
        return total

DP:是不是可以提前保存好每个位置的左右最大值?其实就是对最大高度进行记忆化。

class Solution:
    def trap(self, height: List[int]) -> int:
        total = 0
        n = len(height)
        dp = [[0]*2 for _ in range(n)]
        # dp[i][0] : 第i个位置的maxleft ; dp[i][1] : 第i个位置的maxright
        for i in range(1,n):
            dp[i][0] = max(dp[i-1][0],height[i-1])
        for i in range(n-2,-1,-1): 
            dp[i][1] = max(dp[i+1][1],height[i+1])
 
        # 第一个和最后一个不可能接雨水
        for i in range(1,n-1):
            maxleft = dp[i][0]
            maxright = dp[i][1] 
            # 由于我前面编写的风格,要将结果和0做个判断,只保留非负数
            total += max(min(maxleft,maxright)-height[i],0)
        return total

双指针:这里存在了一点冲突,我参考的两篇题解,在这里有一些分歧,卡哥的双指针法,其实就是完全手册里的二维DP,都是用两个一维数组,去储存每个位置的maxleft和maxright。
但是手册中的双指针思路如下:
在这里插入图片描述

要注意这种双指针法的编写逻辑,和上一题,“盛最多水的容器”,相似。如何确定是移动 left 还是 right ? 看当前 mexleft 和 maxright 哪个小。因为我们在计算当前位置所能接的雨水时,首先要判断 min(maxleft , maxright) ,那么当前应该计算的雨水位置,就是小值的那一侧,假如maxleft小,那么不管后面的循环中,maxright再如何变化,在当前left处,min(maxleft , maxright) 的值不会再变化了(注意,当前left位置的maxleft,是由该位置之前的元素值决定的),所以,如果maxleft小,那么就计算left处的雨水,然后更新maxleft,然后移动left。right同理。

class Solution:
    def trap(self, height: List[int]) -> int:
        total = 0
        n = len(height)
        maxleft = height[0]
        maxright = height[n-1]
        left = 1
        right = n-2
        while left <= right :
            if maxleft <= maxright :
                # 由于我前面编写的风格,要将结果和0做个判断,只保留非负数
                total += max(maxleft-height[left],0)
                # 注意逻辑,注意编写顺序,这里的更新要写在left更新之前
                # 因为在我的编写逻辑中,maxleft和maxright是不考虑当前值的
                # 如果先更新left了,maxleft就会漏掉当前left位置的值
                maxleft = max(maxleft,height[left])
                left += 1
                
            else :  
                # 由于我前面编写的风格,要将结果和0做个判断,只保留非负数
                total += max(maxright-height[right],0)
                # 注意逻辑,注意编写顺序,这里的更新要写在right更新之前
                maxright = max(maxright,height[right])
                right -= 1
                
        return total

单调栈:

本题要让0入栈,不让0入栈是不自然的,然后计算当前能承接水的体积的方式是:当前最外层遍历的元素是 i , 叫做right ,pop()出来的元素是 mid (这个值也是下标) , 当前单调栈stack内 (pop后的单调栈,单调栈的栈顶元素 stack[-1] ),此时的栈顶元素 stack[-1],叫做 left (这个值也是下标) 。计算以当前位置 mid 为底,所能承载的水的体积是:(min(nums[left] , nums[right]) - nums[mid]) * (right-left-1) 。

本题还有一个要注意的是:如果两个数值相等,怎么处理?照常入栈,顶替掉前一个!

class Solution:
    def trap(self, height: List[int]) -> int:
        total = 0
        n = len(height)
        # 栈里放的是索引
        stack = [0]
        for i in range(1,n):  
            
            while stack != [] and height[i] >= height[stack[-1]] :
                mid = stack.pop()
                if stack != []:
                    left = stack[-1]
                    total += (min(height[left],height[i])-height[mid])*(i-left-1)
                
            stack.append(i)
            
        return total

两篇题解的地址

接雨水问题的超完全手册

代码随想录

日后再次复习重新写

84 柱状图中最大的矩形

未看解答自己编写的青春版

重点

题解的代码

日后再次复习重新写

3 无重复字符的最长子串

未看解答自己编写的青春版

一开始想用字典的,但是发现不行,因为要求子序列,要求必须连续,就想到了用双向队列。

from collections import deque
class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        dq = deque()
        maxcount = 0
        count = 0
        for i in s :
            if i in dq :
                while dq[0] != i :
                    dq.popleft()
                    count -= 1
                dq.popleft()
                dq.append(i)
            else :
                dq.append(i)
                count += 1
                maxcount = max(count,maxcount)
        return maxcount

重点

注意:这道题是属于滑动窗口的题目。

用 set 要比我用 deque 来的更巧妙一些。因为本题所要求为去重的子串,而 set 自带去重特性。

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        ans = left = 0
        window = set()  # 维护从下标 left 到下标 right 的字符
        for right, c in enumerate(s):
            while c in window:  # 加入 c 后,窗口内会有重复元素
                window.remove(s[left])
                left += 1  # 缩小窗口
            window.add(c)
            ans = max(ans, right - left + 1)  # 更新窗口长度最大值
        return ans

下面一版的代码解读:(下面这份代码不好理解,写的很简略,我觉得初学者还是先理解上面基于双向队列或者set的做法)

i是截至j,以j为最后一个元素的最长不重复子串的起始位置,即索引范围是[i,j]的子串是以索引j为最后一个元素的最长子串。 当索引从j-1增加到j时,原来的子串[i,j-1]新增了一个元素变为[i,j],需要判断j是否与[i,j-1]中元素有重复。所以if s[j] in st:是判断s[j]相同元素上次出现的位置,和i孰大孰小。如果i大,说明[i,j-1]中没有与s[j]相同的元素,起始位置仍取i;如果i小,则在[i,j-1]中有了与s[j]相同的元素,所以起始位置变为st[s[j]]+1,即[st[sj]+1,j]。而省略掉的else部分,由于s[j]是第一次出现所以前面必然没有重复的,仍然用i作为起始位置即可。 后面的ans=max(ans,j-i+1)中,括号中前者ans是前j-1个元素最长子串长度,j-i+1是以s[j]结尾的最长子串长度,两者(最长子串要么不包括j,要么包括j)取最大即可更新ans,遍历所有i后得到整个输入的最长子串长度。

class Solution:
    def lengthOfLongestSubstring(self, s):
        """
        :type s: str
        :rtype: int
        """
        st = {}
        i, ans = 0, 0
        for j in range(len(s)):
            if s[j] in st:
                i = max(st[s[j]], i)
            ans = max(ans, j - i + 1)
            st[s[j]] = j + 1
        return ans;

题解的代码

日后再次复习重新写

集合方法复写:

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        
        maxcount = 0
        window = set()
        left = 0
        for index,value in enumerate(s):
            while value in window :
                window.remove(s[left])
                left += 1
            window.add(value)
            maxcount = max(maxcount,index-left+1)

           
        return maxcount

438 找到字符串中所有字母异位词

未看解答自己编写的青春版

排序方法,时间复杂度过高。

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        n = len(s)
        m = len(p)
        res = []
        target = sorted(p)
        for i in range(0,n-m+1):
            temp = s[i:i+m]
            if sorted(temp) == target :
                res.append(i)
        return res

用字典记录:注意特殊情况的处理( m > n),注意初始化,不要放在循环里,放在外面初始化。注意收获结果的判断逻辑的放置位置,要放在循环逻辑的最后,所以在初始化后就应该立刻进行一次判断。

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        table = {}
        m = len(p)
        n = len(s)
        if m > n :
            return []
        left = 0
        right = 0
        res = []
        for i in p :
            table[i] = table.get(i,0)+1
        
        temp = {}
        while right < m :
            temp[s[right]] = temp.get(s[right],0)+1
            right += 1
        if temp == table :
            res.append(left)
        for i in range(right,n) :
            temp[s[left]]-=1
            if temp[s[left]] == 0 :
                del temp[s[left]]
            left += 1
            temp[s[right]] = temp.get(s[right],0)+1
            right += 1
            if temp == table :
                res.append(left)
            #print(temp)
        return res

根本不需要,上面,这么复杂的,初始化,以及 left right 走来走去,精简版:

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        table = {}
        m = len(p)
        n = len(s)
        if m > n :
            return []
        res = []
        temp = {}
        for i in range(m) :
            table[p[i]] = table.get(p[i],0)+1
            temp[s[i]] = temp.get(s[i],0)+1     
        if temp == table :
            res.append(0)
        for i in range(m,n) :
            temp[s[i-m]]-=1
            if temp[s[i-m]] == 0 :
                del temp[s[i-m]]
            temp[s[i]] = temp.get(s[i],0)+1 
            if temp == table :
                res.append(i-m+1)
            #print(temp)
        return res

用哈希,注意到题目说明:两个字符串均只包含小写字母。

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
    	if len(s) < len(p):
    		return []
    	Num = []
    	n = len(p)
    	A = [0] * 26
    	for i in range(n):
    		A[ord(p[i]) - ord('a')] += 1
    		A[ord(s[i]) - ord('a')] -= 1
    	if A == [0] * 26:
    		Num.append(0)
    	for i in range(n, len(s)):
    		A[ord(s[i]) - ord('a')] -= 1
    		A[ord(s[i - n]) - ord('a')] += 1
    		if A == [0] * 26:
    			Num.append(i + 1 - n)
    	return Num

数组哈希方法,复写:

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        
        m = len(p)
        n = len(s)
        if m > n :
            return []
        res = []
        A = [0]*26
        for i in range(m) :
            A[ord(p[i])-ord('a')] += 1
            A[ord(s[i])-ord('a')] -= 1
        if A == [0]*26 :
            res.append(0)
        for i in range(m,n) :
            A[ord(s[i])-ord('a')] -= 1
            A[ord(s[i-m])-ord('a')] += 1
            
            if A == [0]*26 :
                res.append(i-m+1)
            #print(temp)
        return res

重点

注意:这道题是属于滑动窗口的题目。

题解的代码

日后再次复习重新写

560 和为 K 的子数组

未看解答自己编写的青春版

不会。

重点

为什么这题不可以用双指针/滑动窗口:因为nums[i]可以小于0,也就是说右指针i向后移1位不能保证区间会增大,左指针j向后移1位也不能保证区间和会减小。给定j,i的位置没有二段性,vice versa。

我也想到了不可以用双指针。

暴力:超时
在这里插入图片描述

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        count = 0
        n = len(nums)
        for i in range(n):
            sums = 0
            for j in range(i,n):
                sums += nums[j]
                if sums == k :
                    count += 1
        return count

前缀和 + 哈希表优化:
在这里插入图片描述
在这里插入图片描述

这方法,如果不是见过,真的很难想到啊。

题解的代码

class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        table = {}
        table[0] = 1
        total = 0
        count = 0
        n = len(nums)
        for i in range(n):
            total += nums[i]
            if total-k in table :
                count += table[total-k]
            table[total] = table.get(total,0)+1
        return count

日后再次复习重新写

239 滑动窗口最大值

未看解答自己编写的青春版

单调队列,我觉得这题考察的就是,如何根据题意,模拟出答案更新的过程,然后发现其中有什么规律,自然而然地去设计一个这样的单调队列。只保留大的数。

以及弹出元素和加入元素的逻辑,判断条件。

from collections import deque
class DQ:
    def __init__(self):
        self.dq = deque()
    def push(self,val):
        if len(self.dq)==0 :
            self.dq.append(val)
        else :
            while self.dq and self.dq[-1] < val :
                self.dq.pop()
            self.dq.append(val)
        
    def top(self):
        return self.dq[0]
        
    def popleft(self):
        self.dq.popleft()
        
                
class Solution:
    def maxSlidingWindow(self, nums: List[int], k: int) -> List[int]:
        dq = DQ()
        n = len(nums)
        
        for i in range(k):
            dq.push(nums[i])
        res = [dq.top()]
        for i in range(k,n):
            remove = i-k
            if nums[remove]==dq.top():
                dq.popleft()
            dq.push(nums[i])
            res.append(dq.top())
        return res

重点

当然我觉得我能顺利地解决这道题,还是之前已经学过了的缘故。
滑动窗口最大值

题解的代码

日后再次复习重新写

76 最小覆盖子串

未看解答自己编写的青春版

又没写出来,这道题的巧妙不仅仅在于,用一个字典或者哈希数组,去存储每个字符,而是用字符串 t 的长度,作为一个指示变量,来指导我们什么时候该上前推进了,而不是每次加入一个元素时,都要进行比较。

错误代码:只让 t 中有的元素,进入字典,这样做完全是自己给自己添麻烦,后续的移动也是一团糟。

class Solution:
    def minWindow(self, s: str, t: str) -> str:
        n = len(s)
        m = len(t)
        if n < m :
            return ''
        table = {}
        for i in t :
            table[i] = table.get(i,0)+1
        left = 0
        
        rightmin = inf
        leftmin = 0
        while s[left] not in table :
            left += 1
        right = left
        flag = False
        while right < n :
            if s[right] in table :
                table[s[right]] -= 1
                if self.isright(table):
                    flag = True
                    break
            right += 1
        if not flag :
            return ''
        if right-left < rightmin-leftmin :
            rightmin,leftmin = right,left

        table[s[left]] += 1   
        left += 1

        while left < n and right < n :
            while s[left] not in table :
                left += 1
            if self.isright(table):
                if right-left < rightmin-leftmin :
                    rightmin,leftmin = right,left
                table[s[left]] += 1   
                left += 1
            else :
                right += 1
                flag = False
                while right < n :
                    if s[right] in table :
                        table[s[right]] -= 1
                        if self.isright(table):
                            flag = True
                            break
                    right += 1
                if flag :
                    if right-left < rightmin-leftmin :
                        rightmin,leftmin = right,left
                    table[s[left]] += 1   
                    left += 1
                else :
                    break
        return s[leftmin:rightmin+1]

    def isright(self,table):
        for i in table :
            if table[i] > 0 :
                return False
        return True
          

重点

暂时不想写了,这道题,后面再复写。看是看懂了。

题解的代码

from collections import defaultdict
class Solution:
    def minWindow(self, s: str, t: str) -> str:
        char_t = defaultdict(int)
        nt = len(t)
        ns = len(s)
        for i in range(nt):
            char_t[t[i]] += 1

        leftmin = 0
        rightmin = 2*ns
        left = 0
        right = 0
        while right < ns :
        	# 这里必须是大于0,因为对于不存在的元素,defaultdict的返回值也是0
            if char_t[s[right]] > 0 :
                char_t[s[right]] -= 1
                nt -= 1
            else :
                char_t[s[right]] -= 1 # 不是t的值也要记录

            if nt == 0 :
            # 这里必须是小于0,因为对于不存在的元素,defaultdict的返回值也是0
                while char_t[s[left]] < 0 :
                    char_t[s[left]] += 1
                    left += 1
                if rightmin - leftmin > right-left :
                    rightmin , leftmin = right , left 
                nt = 1
                # 要理解下面两行代码所代表的逻辑,如果进入判断nt==0,那么一定是在前面,新加入了一个
                # 属于t的字符,并且t中所有字符目前的值是0,而上面的while循环,只能寻找小于0的字符,
                # 当while循环终止时,找到的是最左边的为0的字符,那么此时,如果我们还想让left移动,
                # 那么就要在right的右边,找一个和该最左边字符相等的字符,所以要让char_t[s[left]] += 1
                # 同时也记得让left移动一格,这样在后面找到该字符时,向左移动的while循环是合法的
                char_t[s[left]] += 1
                left += 1
            right += 1
        
        if rightmin == 2* ns :
            return ''
        else :
            return s[leftmin:rightmin+1]


日后再次复习重新写

复写:

class Solution:
    def minWindow(self, s: str, t: str) -> str:
        table = {}
        m = len(t)
        n = len(s)
        for i in t:
            table[i] = table.get(i,0)+1
        left = 0
        right = 0
        rightmin = 2*n
        leftmin = 0
        while right < n :
            if table.get(s[right],0) > 0 :
                table[s[right]] -= 1
                m -= 1
            else :
                # 这里处理的是两种情况,一是s[right]不在t中
                # 二是s[right]是t中的值,但是前面已经出现过,将其值减为0或者更小了,
                # 这里再次出现,也要减一,举例:s='ABBBC' t='ABC',其中的后两个B
                table[s[right]] = table.get(s[right],0)-1
            if m == 0 :
                while table[s[left]] < 0 :
                    table[s[left]]+=1
                    left+=1
                if rightmin-leftmin > right-left:
                    rightmin,leftmin = right,left
                m = 1
                table[s[left]]+=1
                left+=1
            right += 1
        if rightmin == 2*n :
            return ''
        else :
            return s[leftmin:rightmin+1]

53 最大子数组和

未看解答自己编写的青春版

这份代码其实有点牵强,单独写了,如果数组中全是负数的情况。

class Solution:
    def maxSubArray(self, nums):
        maxcount = max(nums)
        if maxcount < 0 :
            return maxcount
        count = 0
        for i in nums:
            count += i
            if count < 0:
                count = 0
            maxcount = max(maxcount,count)
        return maxcount

重点

贪心 or DP 。

题解的代码

标准代码,不自主赋值,全部用数组中自己的值:

class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        result = nums[0]
        maxsum = nums[0]
        n = len(nums)

        for i in range(1,n):

            if maxsum <= 0 :    
                maxsum = nums[i]
            else :
                maxsum += nums[i]

           
            result = max(maxsum,result)

        return result


日后再次复习重新写

56 合并区间

未看解答自己编写的青春版

class Solution:
    def merge(self, intervals: List[List[int]]) -> List[List[int]]:
        intervals.sort()
        res = []
        n = len(intervals)
        temp = intervals[0]
        for i in range(1,n):
            if temp[1] >= intervals[i][0] :
                # 这里要注意,因为我只是先按照第一个坐标进行排序,所以前一个区间的右边界
                # 不一定比后一个区间的右边界小
                temp[1] = max(temp[1],intervals[i][1])
            else :
                res.append(temp)
                temp = intervals[i]
        # 这里注意,根据前面的逻辑,不管最后一层循环走的是if还是else,都没有将最后的结果放入结果集中
        res.append(temp)
        return res

重点

注意两个点就好了,都写在了代码的注释中。

题解的代码

日后再次复习重新写

189 轮转数组

未看解答自己编写的青春版

能想到两种方法,第一种是先反转整个列表,再分别反转两段。第二种是,一次移动一个,移动K次。

错误代码:

错误原因:像这种要求在原数组上修改的,那么就不能用原数组进行一些赋值操作,就必须在上面操作,赋值之后,虽然新变量名字和原数组一样,但是这也是两个变量了,所以,本题,首先不能用python自带的切片,因为倒序切片没法部分倒序,一处理就是整个序列倒序,但这是不行的,会涉及申请新空间问题 (temp = nums[0:k]) ; 那么就必须自主编写倒序函数,也不能编写为 self.reverse 的格式,因为这意味着必须要有返回值,而承接返回值就意味着赋值,就不是原数组修改了!

要学习下面这种在函数内定义函数的方式。

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        n = len(nums)
        k = k % n
        nums = nums[::-1]
        nums = self.reverse(0,k-1,nums)
        nums = self.reverse(k,n-1,nums)
        
    def reverse(self,i,j,nums):
        while i < j :
            nums[i],nums[j] = nums[j],nums[i]
            i += 1
            j -= 1
        return nums

一次向右循环移动一个数字,也是只需要O(1),但是时间复杂度上是O(k*n),这里不写这种方法的代码了。

重点

还有一种方法,就是申请一个K的空间,先把后K个数存起来。

class Solution:
    def rotate(self, nums: List[int], k: int) -> None:
        """
        Do not return anything, modify nums in-place instead.
        """
        n = len(nums)
        k = k % n
        temp = nums[n-k:n]
        if n > k :
            for i in range(n-k-1,-1,-1):
                nums[i+k] = nums[i]
            nums[:k] = temp

题解的代码

日后再次复习重新写

238 除自身以外数组的乘积

未看解答自己编写的青春版

时间复杂度和空间复杂度均是 O(n) 的方法。

class Solution:
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        n = len(nums)
        res = [0]*n
        left = [0]*n
        right = [0]*n
        temp = 1
        for i in range(1,n):
            temp = temp * nums[i-1]
            left[i] = temp
        temp = 1
        for i in range(n-2,-1,-1):
            temp = temp*nums[i+1]
            right[i] = temp
        for i in range(n):
            if i == 0 :
                res[i] = right[i]
            elif i == n-1 :
                res[i] = left[i]
            else :
                res[i] = left[i] * right[i]

        return res

进阶,空间复杂度如何优化到 O(1) ,同时保持时间复杂度还是 O(n) ?

这种方法想不到。

重点

空间复杂度 O(1) 方法:

左边走一遍,右边走一遍,其中规律,自己试一试就能发现,我一开始总想着双指针,才一直想不出来。

class Solution:
    def productExceptSelf(self, nums: List[int]) -> List[int]:
        n = len(nums)
        res = [1]*n        
        left = 1
        right = 1
        for i in range(n):
            res[i] = left
            left = left * nums[i]      
        for i in range(n-1,-1,-1):
            res[i] = res[i] * right
            right = right * nums[i]               
        return res

题解的代码

日后再次复习重新写

41 缺失的第一个正数

未看解答自己编写的青春版

不会,hard题没有思路。

间复杂度为 O(n) 并且只使用常数级别额外空间的解决方案,想不出来。

重点

主要思路:

第一遍把所有负数换成INT_MAX。第二遍,将出现的数的绝对值对应的位置的数置为负数。第三遍,不是负数就输出位置。

两个要点:

1、取abs的操作很巧妙,这样就可以避免前面的操作,覆盖了后面的值。

2、抓住本题的循环不变量:只要该元素出现过了,那么该位置的就必须是负数,所以必须加abs

题解的代码

class Solution:
    def firstMissingPositive(self, nums: List[int]) -> int:
        n = len(nums)
        for i in range(n):
            if nums[i] <= 0 :
                nums[i] = inf
        for i in range(n) :
            # 这里取abs的操作也很巧妙,这样就可以避免前面的操作,覆盖了后面的值
            temp = abs(nums[i])
            if temp > 0 and temp < n+1 :
                # 这里的abs太关键了,防止的就是多次操作的情况
                # 抓住本题的循环不变量:只要该元素出现过了,那么该位置的就必须是负数,所以必须加abs
                nums[temp-1] = -abs(nums[temp-1])
        for i in range(n) :
            if nums[i] > 0 :
                return i+1
        return n+1

日后再次复习重新写

73 矩阵置零

未看解答自己编写的青春版

O(1) 方法,用 inf 对“原本0”进行标记 :(感觉我这有些投机取巧)

class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        m = len(matrix)
        n = len(matrix[0])
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == 0 :
                    matrix[i][j] = inf
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == inf :
                    for k in range(n) :
                        if matrix[i][k] != inf :
                            matrix[i][k] = 0
                    for k in range(m) :
                        if matrix[k][j] != inf :
                            matrix[k][j] = 0
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == inf :
                    matrix[i][j] = 0

O(mn)方法

必须用深拷贝,copy.deepcopy() ,我真是涨知识了。

import copy
class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        copy_matrix = copy.deepcopy(matrix)
        m = len(matrix)
        n = len(matrix[0])
        
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == 0 and copy_matrix[i][j] == 0 :
                    
                    for k in range(n) :
                        matrix[i][k] = 0
                    for k in range(m) :
                        matrix[k][j] = 0

O(m+n)方法:

class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        
        m = len(matrix)
        n = len(matrix[0])
        exist_m = [False]*m
        exist_n = [False]*n
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == 0 :
                    exist_m[i] = True
                    exist_n[j] = True
        
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == 0 :
                    # 注意这里,对行操作还是对列操作
                    # 逻辑和前面给exist_m(n)是相反的
                    if exist_n[j] :
                        for k in range(m) :
                            # 这是对一列进行操作
                            matrix[k][j] = 0
        
                    if exist_m[i] :
                        for k in range(n) :
                            # 这是对一行进行操作
                            matrix[i][k] = 0

重点

本题要求用三种不同的空间复杂度的方法。
在这里插入图片描述
今天做了这道题真是涨知识了,原来在前面二叉树和回溯算法章节,我一直使用的,list.copy() 方法,一直都是浅拷贝,是共享内存的,卡哥一直用的 list[::-1] ,但是我经过试验,一维列表的.copy(),拷贝后数据是不随原数据的更改而更改的,但是多维列表会更改!

多维就要用深拷贝,copy.deepcopy() 。

随便找的一份讲解

题解的代码

看了一下评论的解答,为我愚蠢的矩阵赋值方式感到抓狂。

思路:
在这里插入图片描述
O(1) :

class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        
        m = len(matrix)
        n = len(matrix[0])
        row = False
        col = False

        '''错误逻辑
        for i in range(0,m):
            for j in range(0,n):
                # 注意看,这段逻辑是错误的,后面的修改逻辑可能导致 col row 的值发生错误
                # 而让每个位置都判断左右两边,是没有道理的
                if matrix[i][0] == 0 :
                    col = True
                if matrix[0][j] == 0 :
                    row = True
                if matrix[i][j] == 0 :
                    matrix[0][j] = 0
                    matrix[i][0] = 0
        '''
        for i in range(0,m):
            for j in range(0,n):
                # 正确逻辑,先判断此位置是不是0
                if matrix[i][j] == 0 :
                    if j == 0 :
                        col = True
                    if i == 0 :
                        row = True
                    matrix[0][j] = 0
                    matrix[i][0] = 0
                    
        
        for i in range(1,m):
            for j in range(1,n):
                if matrix[0][j] == 0 or matrix[i][0] == 0 :
                    matrix[i][j] = 0
        if row :
            for i in range(n):
                matrix[0][i] = 0
        if col :
            for i in range(m):
                matrix[i][0] = 0

O(m+n)方法:

class Solution:
    def setZeroes(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        
        m = len(matrix)
        n = len(matrix[0])
        exist_m = [False]*m
        exist_n = [False]*n
        for i in range(m):
            for j in range(n):
                if matrix[i][j] == 0 :
                    exist_m[i] = True
                    exist_n[j] = True
        
        for i in range(m):
            for j in range(n):
                if exist_m[i] == True or exist_n[j] == True :                
                    matrix[i][j] = 0

O(mn)的方法好难想,真的不需要这么大的空间!不考虑这种方法了,直接学习O(1)的方法不好吗!

日后再次复习重新写

54 螺旋矩阵

未看解答自己编写的青春版

加一减一好像有些乱的版本,因为我给 right 和 down 的定义都是 m n 。所以:在索引时,要记得减一。在倒序时,因为第一个值是可以取到的,所以要记得减一。在倒序时,因为最后一个值是不能取到的,所以要对 left 和 up 减一。

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        m = len(matrix)
        n = len(matrix[0])
        left = 0
        right = n
        up = 0
        down = m
        total = m*n
        res = [0]*total
        count = 0
        while count < total :
            for i in range(left,right):
                res[count] = matrix[up][i]
                count += 1
            up += 1
            if up >= down :
                break
            for i in range(up,down):
                res[count] = matrix[i][right-1]
                count += 1
            right -= 1
            if right <= left :
                break
            for i in range(right-1,left-1,-1):
                res[count] = matrix[down-1][i]
                count += 1
            down -= 1
            if up >= down :
                break
            for i in range(down-1,up-1,-1):
                res[count] = matrix[i][left]
                count += 1
            left += 1
            if right <= left :
                break
            
        return res

更改下标逻辑:给 right 和 down 的定义变为 m-1 n-1 。值得注意的是,下标逻辑改变,判断跳出的逻辑也要相应改变。

class Solution:
    def spiralOrder(self, matrix: List[List[int]]) -> List[int]:
        m = len(matrix)
        n = len(matrix[0])
        left = 0
        right = n-1
        up = 0
        down = m-1
        total = m*n
        res = [0]*total
        count = 0
        while count < total :
            for i in range(left,right+1):
                res[count] = matrix[up][i]
                count += 1
            up += 1
            if up > down :
                break
            for i in range(up,down+1):
                res[count] = matrix[i][right]
                count += 1
            right -= 1
            if right < left :
                break
            for i in range(right,left-1,-1):
                res[count] = matrix[down][i]
                count += 1
            down -= 1
            if up > down :
                break
            for i in range(down,up-1,-1):
                res[count] = matrix[i][left]
                count += 1
            left += 1
            if right < left :
                break
            
        return res

重点

本题要注意的是,对各个指标的定义,会影响判断跳出的逻辑,这个要举例来验证了。但是从直觉上说,还是第二种方法好,不管是在边界处理上更为简洁,还是在跳出逻辑上更符合直觉。

相等时,应该会再有加入元素的操作的,不能跳出。

学习上面第二种的写法。

题解的代码

日后再次复习重新写

48 旋转图像

未看解答自己编写的青春版

没思路

重点

这道题太巧妙了!已经练到这种程度了,如果做题的时候发现没思路,就不要按照老思路一直想下去了,很有可能是思路错了!改变思路,从其他方向入手!

本题思路:先转置,再镜像对称。

或者,先上下翻转,再转置也行。

先转置,再镜像对称,的代码:

class Solution:
    def rotate(self, matrix: List[List[int]]) -> None:
        """
        Do not return anything, modify matrix in-place instead.
        """
        m = len(matrix)
        n = len(matrix[0])
        for i in range(m):
            for j in range(i+1,n):
                matrix[i][j],matrix[j][i] = matrix[j][i],matrix[i][j]
        middle = n // 2
        for i in range(m):
            for j in range(middle):
                matrix[i][j],matrix[i][n-1-j] = matrix[i][n-1-j],matrix[i][j]
        

题解的代码

日后再次复习重新写

240 搜索二维矩阵 II

未看解答自己编写的青春版

倒序遍历,这道题正序遍历不行。

class Solution:
    def searchMatrix(self, matrix: List[List[int]], target: int) -> bool:
        m = len(matrix)
        n = len(matrix[0])
        row = m-1
        col = n-1
        while row > -1 and matrix[row][0] > target :
            row -= 1
        while col > -1 and matrix[0][col] > target :
            col -= 1
        for i in range(row+1):
            for j in range(col+1):
                if matrix[i][j] == target :
                    return True

        return False

重点

另一种思路:
在这里插入图片描述

class Solution:
    def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        m = len(matrix)
        if m == 0:
            return False
        n = len(matrix[0])
        if n == 0:
            return False

        i = m - 1
        j = 0
        while i >= 0 and j < n:
            if matrix[i][j] == target:
                return True
            elif matrix[i][j] < target:
                j = j + 1
            else:
                i = i - 1
        return False

还是这种思路厉害,时间复杂度是O(n),我的方法严格来说,还是O(n^2)

题解的代码

日后再次复习重新写

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

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

相关文章

谷歌浏览器提示客户端和服务器不支持一般 SSL 协议版本或加密套件(亲测有效)

目录 一、定位问题二、升级TLS1.21、原理之前架构调整架构 2、配置nginx3、配置tomcat 三、访问nginx即可 最近访问一部分网站时&#xff0c;出现如下图所示 “ 此网站无法提供案例连接&#xff0c;客户端和服务器不支持一般 SSL 协议版本或加密套件 ” 的问题。 一、定位问题…

AIGC之AI绘画行业发展研究报告(2023)

全部140页&#xff0c;完整版pdf下载见文末。 链接&#xff1a;AIGC之AI绘画行业发展研究报告&#xff08;2023&#xff09; 提取码&#xff1a;关注 未来人智慧 回复 AIGC之AI绘画行业发展研究报告&#xff08;2023&#xff09;

C语言每日一题:11.《数据结构》链表分割。

题目一&#xff1a; 题目链接&#xff1a; 思路一&#xff1a;使用带头链表 1.构建两个新的带头链表&#xff0c;头节点不存储数据。 2.循环遍历原来的链表。 3.小于x的尾插到第一个链表。 4.大于等于x尾插到第二个链表。 5.进行链表合并&#xff0c;注意第二个链表的尾的下一…

IO进程线程第四天(8.1)

作业1&#xff1a; 从终端获取一个文件的路径以及名字。 若该文件是目录文件&#xff0c;则将该文件下的所有文件的属性显示到终端&#xff0c;类似ls -l该文件夹 若该文件不是目录文件&#xff0c;则显示该文件的属性到终端上&#xff0c;类似ls -l这单个文件 #include<…

ad+硬件每日学习十个知识点(16)23.7.27 (总线保持、lin报文、逻辑器件手册解读)

文章目录 1.总线保持是怎么实现的&#xff1f;有什么需要注意的&#xff08;驱动电流和电阻&#xff09;&#xff1f;2.LIN报文3.芯片datasheet的features、applications、description看完&#xff0c;应该能大致判断逻辑器件能否满足我们的要求。4.什么是逻辑器件的传输延时&a…

系统架构设计师_备考第1天

文章目录 前言一、软考历史与体系二、考试价值与意义三、软考报名与交费四、考试介绍五、综合备考策略 前言 从今天开始&#xff0c;会认真备考系统架构设计师&#xff0c;希望95天后&#xff0c;拿下软考证书。 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可…

P3372 【模板】线段树 1(内附封面)

【模板】线段树 1 题目描述 如题&#xff0c;已知一个数列&#xff0c;你需要进行下面两种操作&#xff1a; 将某区间每一个数加上 k k k。求出某区间每一个数的和。 输入格式 第一行包含两个整数 n , m n, m n,m&#xff0c;分别表示该数列数字的个数和操作的总个数。 …

深度学习(33)——CycleGAN(1)

深度学习&#xff08;33&#xff09;——CycleGAN&#xff08;1&#xff09; 完整项目在在这里&#xff1a;欢迎造访 文章目录 深度学习&#xff08;33&#xff09;——CycleGAN&#xff08;1&#xff09;1. Generator2. Discriminator3. fake pool4. loss定义5. 模型参数量6…

Nodejs 第七章(发布npm包)

发布npm的包的好处是什么 方便团队或者跨团队共享代码&#xff0c;使用npm包就可以方便的管理&#xff0c;并且还可以进行版本控制做开源造轮子必备技术&#xff0c;否则你做完的轮子如何让别人使用难道是U盘拷贝&#xff1f;面试题我面字节的时候就问到了这个增加个人IP 让更…

消息队列之 - 消息持久化设计

目录 前言设计思想消息文件的格式垃圾回收的思想其他情况序列化和反序列化 具体代码实现测试消息文件 前言 我们之前说过, 消息队列不管要往硬盘中存储, 还要往内存中存储, 并且是以内存为主 ,硬盘为辅, 接下来, 就将消息队列如何存储到硬盘 做一个设计 设计思想 我们往硬盘…

云服务器无法远程连接服务

问题 今天刚买了华为的云服务器&#xff0c;通过宝塔安装了对应的基础服务&#xff0c;也在华为云的官网上设置了安全组。此时万事俱备只欠东风&#xff0c;我测试使用sqlyog进行远程连接。原本已经在准备部署项目了&#xff0c;现实给了我重重的一拳。 sqlyog爆2003代码错误&…

交换机VLAN技术和实验(eNSP)

目录 一&#xff0c;交换机的演变 1.1&#xff0c;最小网络单元 1.2&#xff0c;中继器&#xff08;物理层&#xff09; 1.3&#xff0c;集线器&#xff08;物理层&#xff09; 1.4&#xff0c;网桥&#xff08;数据链路层&#xff09; 二&#xff0c;交换机的工作行为 2.…

IO进线程——库的制作(静态库、动态库)

库的制作 1、静态库 ①生成二进制文件 gcc -c linkstack.c -o linkstack.o②制作静态库文件&#xff0c;把.o文件转换为.a文件 ar crs liblinkstack.a linkstack.o③编译时链接 gcc linkstack_main.c -L. -llinkstack2、动态库 ①生成地址无关二进制文件 gcc -fPIC -c l…

《工具箱-VNCServer》配置VNCServer,使用VNCViewer实现局域网内页面共享

VNCServer设置 通过VNCServer配置&#xff0c;与VNCviewer配套使用 1.下载并安装VNCServer 2.邮箱密码注册后用户登录 3.设置VNC密码 4.设置viewer不能控制本机 5.打开VNClicensewiz&#xff0c;选择“Enter a license key …” BQ24G-PDXE4-KKKRS-WBHZE-F5RCA BQ24G-PDXE4-…

mysql进阶-修改linux服务器中MySQL的字符集

1.背景 linux中mysql8默认的字符集是latin1&#xff0c;在插入中文时会报错&#xff0c;所以一般在配置好mysql时需要修改字符集为utf8【又叫utfmb3,一般开发够用&#xff0c;一个字符用3个字节表示】或者utfmb4【一个字符用4个字节表示&#xff0c;如果存储emoji表情&#xf…

Linux实战:五子棋

一、五子棋原理 采用二维数组保存棋盘信息,棋盘上面的任何一个位置,里面可以放置三类信息。 空用户1的落子(黑子)用户2的落子(白子)下棋就是在二维数组中找对应的空位置,进行落子落完子之后下来就要考虑该落子位置是否有”五子连珠“,进而进行输赢判定,每一次走棋,多…

如何让python在手机上运行,python在手机上怎么运行

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;python程序如何在手机上运行&#xff0c;如何让python在手机上运行&#xff0c;现在让我们一起来看看吧&#xff01; 在计算机语言的运用过程中PythonS60手机是经常被使用的计算机语言&#xff0c;以下的文章是介绍Pyth…

华为OD机试真题 JavaScript 实现【明明的随机数】【2023Q1 100分】,附详细解题思路

目录 一、题目描述二、输入描述三、输出描述四、解题思路五、JavaScript算法源码 华为OD机试 2023B卷题库疯狂收录中&#xff0c;刷题点这里 刷的越多&#xff0c;抽中的概率越大&#xff0c;每一题都有详细的答题思路、详细的代码注释、样例测试&#xff0c;发现新题目&#x…

Python超实用!批量重命名文件/文件夹,只需1行代码

大家好&#xff0c;这里是程序员晚枫&#xff0c;之前在小破站给大家分享了一个视频&#xff1a;批量重命名文件。 最近在程序员晚枫的读者群里&#xff0c;发现很多朋友对这个功能很感兴趣&#xff0c;尤其是对下一步的优化&#xff1a;批量重命名文件夹。 这周我利用下班时…

Java 解析Excel单元格的富文本

1. 总体介绍 该方法是解析 xlsx 单元格中的富文本&#xff0c;注意不是 xls&#xff0c;xls 的 api 不一样&#xff0c;试了很久没成功。只实现了解析 斜体字、上下标&#xff0c;其它的实现方式应该类似。 2. 具体实现 2.1 代码 package util;import java.io.FileInputStr…