超人阿光 永久会员 2024年7月25日 下午5:12

    本打卡对应问题:【作业4】下标法:剑指 Offer 03. 数组中重复的数字
    具体打卡内容:

    class Solution {
    public int findRepeatDocument(int[] documents) {
    if(documents null || documents.length 0) return -1;

        // 数组计数法或者数组下标法
        /*
        范围为:0 ~ 99999;
        类型为int
         */
    
        int[] count = new int[100001];
    
        // 遍历目标数组
        for(int i = 0; i < documents.length; i++){
            count[documents[i]]++;
        }
    
        // 返回统计数组中任一 >= 2 的项
        for(int i = 0; i < count.length ; i++){
            if(count[i] >= 2) return i;
        }
    
        // 没有则返回-1;
        return -1;
    }
    

    }

    短某人。 永久会员 2024年7月21日 上午2:00

    本打卡对应问题:二叉树的最近公共祖先 中等
    具体打卡内容:

    帅地哥 这个python的答案会超出时间限制 过不了 下面这个答案也是递归 原理一样
    class Solution:
    def lowestCommonAncestor(self, root: ‘TreeNode’, p: ‘TreeNode’, q: ‘TreeNode’) -> ‘TreeNode’:
    # 基准情况
    if root is None or root p or root q:
    return root

        # 递归查找左子树和右子树
        left = self.lowestCommonAncestor(root.left, p, q)
        right = self.lowestCommonAncestor(root.right, p, q)
    
        # 如果左右子树都有结果,说明当前节点是最近公共祖先
        if left and right:
            return root
    
        # 否则返回非空的那个结果
        return left if left else right
    

    # def find(self, root, p):
    # if root is None:
    # return False
    # if root p:
    # return True
    # return self.find(root.left, p) or self.find(root.right, p)

    星河揽我入梦 永久会员 2024年7月18日 下午3:37

    本打卡对应问题:【任务11】数据统计与拦截:统计网站在线人数
    具体打卡内容:

    我采用session监听器来统计网站在线人数,每次创建session时就会自动加一,销毁session时就会自动减一;
    先初始化一个类实现HttpSessionlistener,然后定义count,创建session,count+1,销毁session,count-1;然后在类上加注解webListener,启动类上再加@ServletComponentScan(“com.example.demo.listener”)扫描包才有用。
    优点是:
    统计在线人数结果相对准确;
    缺点是:
    当用户关闭浏览器时并不会触发session监听,当下一次登录时仍然会让count加一
    或者在session过期时,session监听并不能做一个实时的响应去将在线数减一
    当用户再次登陆,由于cookie中含有的session_id不同而导致session监听器记录下session创建,而使count加一。
    对服务器性能影响较大,用户每次访问网站时,服务端都会创建一个session,并将该session与用户关联起来,这样会增加服务器的负担,特别是在高并发的时候,导致服务器压力过大
    https://github.com/CurryisCoat/community/tree/dev

    翰林猿 永久会员 2024年7月12日 下午4:05

    本打卡对应问题:LeetCode25. K 个一组翻转链表🌟🌟🌟困难
    具体打卡内容:

    class Solution {
    public ListNode reverseKGroup(ListNode head, int k) {
    int n = 0;
    for (ListNode cur = head; cur != null; cur = cur.next)
    ++n; // 统计节点个数

        ListNode dummy = new ListNode(0, head), p0 = dummy;
        ListNode pre = null, cur = head;
        for (; n >= k; n -= k) {
            for (int i = 0; i < k; ++i) { // 同 92 题
                ListNode nxt = cur.next;
                cur.next = pre; // 每次循环只修改一个 next,方便大家理解
                pre = cur;
                cur = nxt;
            }
    
            // 见视频
            ListNode nxt = p0.next;
            p0.next.next = cur;
            p0.next = pre;
            p0 = nxt;
        }
        return dummy.next;
    }
    

    }

    mpweixin用户 普通 2024年7月9日 下午6:24

    本打卡对应问题:算法刷题路线
    具体打卡内容:

    怎么突然要会员了,跟了一半还没做完QAQ

    星河揽我入梦 永久会员 2024年7月8日 上午10:57

    本打卡对应问题:【总结2】注册与登录:用户密码加密的设计
    具体打卡内容:

    已完成阅读

    星河揽我入梦 永久会员 2024年7月8日 上午10:21

    本打卡对应问题:【任务10】注册与登录:不允许多个设备同时在线
    具体打卡内容:

    我的实现逻辑是用redis存储随机数,key为用户id,只保留最后一个登录的用户生成的token,在用户登录时进行判断,如果redis里面存了该用户的token,我们就将其删除,然后设置一个新的token值,将其挤下线;
    https://github.com/CurryisCoat/community/tree/dev

    mpweixin用户 普通 2024年7月8日 上午12:37

    本打卡对应问题:《剑指offer最优解》相关说明
    具体打卡内容:

    为什么网页端要会员而手机端不需要

    星河揽我入梦 永久会员 2024年7月4日 下午2:27

    本打卡对应问题:【任务9】注册与登录:拥有登录功能(初级)
    具体打卡内容:

    使用session保持用户登录态
    https://github.com/CurryisCoat/community/tree/dev
    public String login(HttpServletRequest request,HttpServletResponse response) throws IOException {
    String username = request.getParameter(“username”);
    User user = userService.login(username);
    response.setContentType(“text/html;charset=utf-8”);
    PrintWriter writer = response.getWriter();

        if(user != null){
            if(md5s.md5(request.getParameter("password")+user.getSalt()).equals(user.getPassword())){
                HttpSession session = request.getSession();
                String sessionAttribute = md5s.GenerateUUID();
                session.setAttribute("LoginStatus",sessionAttribute);
                session.setMaxInactiveInterval(24 * 60 * 60);
                return "index";
            }else{
              return "login";
            }
        }else{
           return "register";
        }
    
    星河揽我入梦 永久会员 2024年7月2日 下午2:32

    本打卡对应问题:【阅读】关于短信验证与邮箱验证码的设计
    具体打卡内容:

    已阅读完成

    星河揽我入梦 永久会员 2024年7月2日 下午1:46

    本打卡对应问题:【任务8】注册与登录:设计一个加密算法
    具体打卡内容:

    加密方式:MD5,随机加盐
    public class Md5Memory {

    public static String GenerateUUID(){
        return UUID.randomUUID().toString().replace("-","").substring(0,5);
    }
    
    public static String md5(String context){
        if(StringUtils.isBlank(context)){
            return null;
        }
        return DigestUtils.md5DigestAsHex(context.getBytes()).substring(0,10);
    }
    

    }

    星河揽我入梦 永久会员 2024年7月2日 上午10:02

    本打卡对应问题:【总结+面试考点1】用户名防重名设计
    具体打卡内容:

    已完成阅读

    mpweixin用户 会员 2024年6月30日 下午3:45

    本打卡对应问题:01背包问题🌟🌟🌟🌟🌟
    具体打卡内容:

    讲解里的公式v[i](体积)和w[i](价值)写反了,如果拿的时候公式应该是:dp[i][v] = dp[i-1][v-v[i]] + w[i]

    我来吃饭啦 永久会员 2024年6月20日 上午9:53

    本打卡对应问题:LeetCode92. 反转链表 II🌟🌟🌟中等
    具体打卡内容:

    打卡

    class Solution:
        def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
            p0 = dummy = ListNode(next=head)
            for _ in range(left - 1):
                p0 = p0.next
    
            pre = None
            cur = p0.next
            for _ in range(right - left + 1):
                nxt = cur.next
                cur.next = pre  # 每次循环只修改一个 next,方便大家理解
                pre = cur
                cur = nxt
    
            # 见视频
            p0.next.next = cur
            p0.next = pre
            return dummy.next
    

    先化为前right项,再让left逐渐为1,采用递归的思想

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        last = None
        def reverseBetween(self, head: Optional[ListNode], left: int, right: int) -> Optional[ListNode]:
            if left == 1:
                return self.reversethN(head,right)
    
            head.next = self.reverseBetween(head.next,left-1,right-1)
            return head
    
        def reversethN(self,head,n):
            if n == 1:
                self.last = head.next
                return head
    
            newhead = self.reversethN(head.next,n-1)
            head.next.next = head
            head.next = self.last
            return newhead
    
    我来吃饭啦 永久会员 2024年6月18日 下午9:03

    本打卡对应问题:LeetCode206. 反转链表🌟🌟🌟🌟🌟简单
    具体打卡内容:

    打卡

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    #  递归1
    class Solution:
        def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
            def recur(cur, per):
                if not cur: return per
                res = recur(cur.next, cur)
                cur.next = per
                return res
            return recur(head, None)
    

    # 递归2
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def reverseList(self, head: Optional[ListNode]) -> Optional[ListNode]:
            if not head or not head.next:
                return head
            newhead = self.reverseList(head.next)
            head.next.next = head
            head.next = None
            return newhead
    
    我来吃饭啦 永久会员 2024年6月18日 下午8:32

    本打卡对应问题:LeetCode160. 相交链表🌟🌟🌟🌟🌟简单
    具体打卡内容:

    打卡

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, x):
    #         self.val = x
    #         self.next = None
    
    class Solution:
        def getIntersectionNode(self, headA: ListNode, headB: ListNode) -> Optional[ListNode]:
            A, B = headA, headB
            while A != B:
                A = A.next if A else headB
                B = B.next if B else headA
            return A
    
    我来吃饭啦 永久会员 2024年6月18日 下午7:43

    本打卡对应问题:剑指 Offer 06. 从尾到头打印链表🌟🌟🌟🌟🌟简单
    具体打卡内容:
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution: # 递归
        def reverseBookList(self, head: Optional[ListNode]) -> List[int]:
            return self.reverseBookList(head.next) + [head.val] if head else []
    

    class Solution:
        def reverseBookList(self, head: ListNode) -> List[int]:
            stack = []
            while head:
                stack.append(head.val)
                head = head.next
            return stack[::-1]
    
    我来吃饭啦 永久会员 2024年6月17日 下午11:35

    本打卡对应问题:LeetCode19. 删除链表的倒数第 N 个结点🌟🌟🌟🌟🌟中等
    具体打卡内容:
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    # 快慢指针
    class Solution:
        def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
            dummy = ListNode(0, head)
            slow, fast = dummy, dummy
            for _ in range(n):
                fast = fast.next
    
            while fast.next:
                fast = fast.next
                slow = slow.next
    
            slow.next = slow.next.next #不可以写 slow.next = fast (删除头节点会出问题)
            return dummy.next
    

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    # 循环迭代
    class Solution:
        def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
            dummy = ListNode(0, head)
            cur, length = head, 0
            while cur:
                length += 1
                cur = cur.next
            cur = dummy
            for _ in range(length - n):
                cur = cur.next
            cur.next = cur.next.next
            return dummy.next
    

    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    #  迭代法
    class Solution:
        def removeNthFromEnd(self, head: Optional[ListNode], n: int) -> Optional[ListNode]:
            if not head:
                self.count = 0
                return head
            head.next = self.removeNthFromEnd(head.next, n)
            self.count += 1
            return head.next if self.count == n else head
    
    我来吃饭啦 永久会员 2024年6月17日 下午4:48

    本打卡对应问题:剑指 Offer 22. 链表中倒数第k个节点🌟🌟🌟🌟🌟中等
    具体打卡内容:
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    #  former比latter多走了cnt步
    class Solution:
        def trainingPlan(self, head: Optional[ListNode], cnt: int) -> Optional[ListNode]:
            latter = former = head
            for _ in range(cnt):
                if not former: return 
                former = former.next
            while former:
                latter = latter.next
                former = former.next
            return latter
    
    我来吃饭啦 永久会员 2024年6月17日 下午4:10

    本打卡对应问题:LeetCode876. 链表的中间结点🌟🌟🌟🌟🌟简单
    具体打卡内容:
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    # 双指针
    class Solution:
        def middleNode(self, head: Optional[ListNode]) -> Optional[ListNode]:
            slow = fast = head
            while fast and fast.next:
                slow = slow.next
                fast = fast.next.next
            return slow
    
    我来吃饭啦 永久会员 2024年6月17日 下午2:49

    本打卡对应问题:LeetCode203.移除链表元素🌟🌟🌟🌟🌟简单
    具体打卡内容:
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution: #  有虚拟头节点
        def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
            dummyHead = ListNode(-1, head)
            cur = dummyHead
            while cur.next:
                if cur.next.val == val:
                    cur.next = cur.next.next
                else:
                    cur = cur.next
            return dummyHead.next
    #递归法
    # Definition for singly-linked list.
    # class ListNode:
    #     def __init__(self, val=0, next=None):
    #         self.val = val
    #         self.next = next
    class Solution:
        def removeElements(self, head: Optional[ListNode], val: int) -> Optional[ListNode]:
            if not head: 
                return 
            head.next = self.removeElements(head.next, val)
            return head.next if head.val == val else head
    
    我来吃饭啦 永久会员 2024年6月17日 下午2:02

    本打卡对应问题:第四章:理解链表🌟🌟🌟🌟🌟
    具体打卡内容:

    打卡

    我来吃饭啦 永久会员 2024年6月16日 上午11:04

    本打卡对应问题:递归入门与优化 + 例题🌟🌟🌟🌟🌟
    具体打卡内容:

    拿掉栈顶元素,反转:1,2,3,4,5 => 4,3,2,1
    拿掉栈顶元素,top放到栈底,将tmp放到栈顶:4,3,2,1 => 5,4,3,2 => 5,4,3,2,1

     # stack = 1, 2, 3, 4, 5 => stack = 5, 4, 3, 2,1
    class Solution:
        def reverse(self, stack):
            if not stack or len(stack) == 1:
                return stack
            top = stack.pop()  # 1,2,3,4
            stack = self.reverse(stack)  # 4,3,2,1
            stack = self.push_first(stack, top)  # 5,4,3,2,1
            return stack
    
        def push_first(self, stack, top):
            if not stack:
                stack.append(top)
                return stack
            temp = stack.pop()  # 4,3,2
            stack = self.push_first(stack, top)  # 5,4,3,2
            stack.append(temp)  # 5,4,3,2,1
            return stack
    
    solution = Solution()
    stack = [3, 4, 5, 6]
    reversed_stack = solution.reverse(stack.copy())
    print(reversed_stack)
    

    class Solution:
        def reverse1(self,stack):
            if not stack or len(stack) == 1:
                return stack
    
            last = self.get_last(stack)  # 1,2,3,4,5 =>2,3,4,5 last = 1
            stack = self.reverse1(stack)  # 5,4,3,2
            stack.append(last)  # 5,4,3,2,1
            return stack
    
        def get_last(self,stack):
            if len(stack) == 1:
                return stack.pop()
    
            temp = stack.pop()  # 1,2,3,4
            last = self.get_last(stack)  # 2,3,4
            stack.append(temp)  # 2,3,4,5
            return last
    
    solution = Solution()
    stack = [3, 4, 5, 6]
    reversed_stack = solution.reverse1(stack.copy())
    print(reversed_stack)
    
    我来吃饭啦 永久会员 2024年6月16日 上午10:20

    本打卡对应问题:巧用数组下标法🌟🌟🌟🌟🌟
    具体打卡内容:
    ```class Solution:#原地交换
        def findRepeatDocument(self, documents: List[int]) -> int:
            i = 0
            while i < len(documents):
                if documents[i] == i:
                    i += 1
                    continue
                if documents[documents[i]] == documents[i]: return documents[i]
                documents[documents[i]], documents[i] = documents[i], documents[documents[i]]
            return -1
    class Solution:# 哈希表
        def findRepeatDocument(self, documents: List[int]) -> int:
            hmap = set()
            for doc in documents:
                if doc in hmap:
                    return doc
                hmap.add(doc)
            return -1
    
    我来吃饭啦 永久会员 2024年6月15日 下午10:38

    本打卡对应问题:LeetCode209. 长度最小的子数组🌟🌟🌟🌟中等
    具体打卡内容:
    class Solution:#滑动窗口
        def minSubArrayLen(self, target: int, nums: List[int]) -> int:
            l, r, s = 0, 0, 0
            n = len(nums)
            ans = float('inf')
            while r < n:
                s += nums[r]
    
                while s >= target:
                    ans = min(ans, r - l + 1)
                    s -= nums[l]
                    l += 1
    
                r += 1
            return ans if ans <= n else 0
    
    
    我来吃饭啦 永久会员 2024年6月15日 上午11:13

    本打卡对应问题:LeetCode11.盛最多水的容器🌟🌟🌟中等
    具体打卡内容:

    ”’
    class Solution:
    def maxArea(self, height: List[int]) -> int:
    l = 0
    r = len(height) – 1
    s =0
    while l <= r:
    tmp = min(height[l], height[r]) #记录容器的高
    s = max(s, tmp*(r-l))
    if height[l] < height[r]:
    l += 1
    else:
    r -= 1
    return s
    ”’

    我来吃饭啦 永久会员 2024年6月15日 上午10:41

    本打卡对应问题:LeetCode27.移除元素🌟🌟🌟🌟🌟简单
    具体打卡内容:

    +双指针法

    class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
    l = 0
    r = len(nums) – 1
    if not nums:
    return 0
    while l <= r:
    if nums[l] val:
    nums[l], nums[r] = nums[r], nums[l]
    r -= 1
    else:
    l += 1
    return l
    

    +单指针

    class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
    l = 0
    for i in range(len(nums)):
    if nums[i] val:
    nums[i] = ‘_’
    else:
    tmp = nums[l]
    nums[l] = nums[i]
    nums[i] = tmp
    l += 1
    return l
    
    我来吃饭啦 永久会员 2024年6月15日 上午10:38

    本打卡对应问题:LeetCode27.移除元素🌟🌟🌟🌟🌟简单
    具体打卡内容:

    *双指针法
    ”’
    class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
    l = 0
    r = len(nums) – 1
    if not nums:
    return 0
    while l <= r:
    if nums[l] val:
    nums[l], nums[r] = nums[r], nums[l]
    r -= 1
    else:
    l += 1
    return l
    ”’
    *单指针
    ”’
    class Solution:
    def removeElement(self, nums: List[int], val: int) -> int:
    l = 0
    for i in range(len(nums)):
    if nums[i]
    val:
    nums[i] = ‘_’
    else:
    tmp = nums[l]
    nums[l] = nums[i]
    nums[i] = tmp
    l += 1
    return l
    ”’

    我来吃饭啦 永久会员 2024年6月15日 上午9:01

    本打卡对应问题:LeetCode69.x的平方根.🌟🌟🌟🌟🌟简单
    具体打卡内容:
    • 使得保证hh永远大于x
      class Solution:
      def mySqrt(self, x: int) -> int:
      l = 0
      h = x
      while l <= h:
      if h – l <= 1:
      return l
      mid = l + (h – l)//2
      if mid
      mid > x:
      h = mid
      elif mid*mid < x:
      l = mid
      else:
      return mid
      return -1
    星河揽我入梦 永久会员 2024年6月14日 下午4:33

    本打卡对应问题:【任务7】注册与登录:进阶:动态维护敏感词库
    具体打卡内容:

    github仓库:https://github.com/CurryisCoat/community/tree/dev

    @Component
    public class SensitiveFilter {
    
        private static final Logger logger = LoggerFactory.getLogger(SensitiveFilter.class);
    
        private static final String REPLACEMENT = "***";
    
        // 根节点
        private TrieNode rootNode = new TrieNode();
    
        @Autowired
        private DisallowService disallowService;
    
        @PostConstruct
        public void init()
        {
    //        InputStream is = this.getClass().getClassLoader().getResourceAsStream("sensitive-filter.txt");
    //        BufferedReader read = new BufferedReader(new InputStreamReader(is));
    
    //        try {
    //            String keyWord;
    //            while((keyWord=read.readLine())!=null)
    //            {
    //                this.addKeyword(keyWord);
    //            }
    //        } catch (IOException e) {
    //            logger.error("加载敏感词文件失败: " + e.getMessage());
    //        }
    
            List<DisallowWord> list = disallowService.wordList();
            for(DisallowWord t:list){
                String temp = t.getValue();
                this.addKeyword(temp);
            }
        }
    
        //将一个敏感词添加到前缀树中
        private void addKeyword(String keyWord)
        {
    
            TrieNode tempNode = rootNode;
            for(int i = 0;i < keyWord.length();i ++)
            {
                char c = keyWord.charAt(i);
                TrieNode subNode = tempNode.getSubNode(c);
    
                if(subNode==null){
                    subNode = new TrieNode();
                    tempNode.addSubNode(c,subNode);
                }
    
                tempNode=subNode;
                if(i == keyWord.length()-1){
                    tempNode.setKeywordEnd(true);
                }
            }
        }
        //过滤文本
        public String filter(String text)
        {
            if(StringUtils.isBlank(text)){
                return null;
            }
    
            TrieNode p1 = rootNode;
            int p2 = 0;
            int p3 = 0;
            StringBuilder sb = new StringBuilder();
            while(p3 < text.length())
            {
                char c = text.charAt(p3);
                if(isSymbol(c)){
    
                    if(p1 == rootNode){
                        sb.append(c);
                        p2++;
                    }
                    p3++;
                    continue;
                }
    
                p1 = p1.getSubNode(c);
                if(p1==null){
                    sb.append(text.charAt(p2));
                    p3 = ++p2;
                    p1 = rootNode;
                }else if(p1.isKeywordEnd()==true){
                    sb.append(REPLACEMENT);
                    p2 = ++p3;
                    p1 = rootNode;
                }else{
                    p3++;
                }
            }
            sb.append(text.substring(p2));
            return sb.toString();
        }
    
    
        // 判断是否为符号
        private boolean isSymbol(Character c) {
            // 0x2E80~0x9FFF 是东亚文字范围
            return !CharUtils.isAsciiAlphanumeric(c) && (c < 0x2E80 || c > 0x9FFF);
        }
        //树结构
        private class TrieNode{
    
            private boolean iskeywordEnd = false;
    
            private HashMap<Character,TrieNode> subNodes = new HashMap<>();
    
            public boolean isKeywordEnd() {
                return iskeywordEnd;
            }
    
            public void setKeywordEnd(boolean keywordEnd) {
                iskeywordEnd = keywordEnd;
            }
    
            public void addSubNode(Character c,TrieNode node){
                subNodes.put(c,node);
            }
    
            public TrieNode getSubNode(Character c){
                return subNodes.get(c);
            }
        }
    }
    
    

    2.建表语句
    CREATE TABLE disallow_word (
    id int NOT NULL AUTO_INCREMENT,
    value varchar(255) NOT NULL,
    type int NOT NULL DEFAULT ‘0’,
    PRIMARY KEY (id)
    ) ENGINE=InnoDB

    星河揽我入梦 永久会员 2024年6月12日 下午8:48

    本打卡对应问题:【任务6】注册与登录:初步完善注册功能
    具体打卡内容:

    github仓库:https://github.com/CurryisCoat/community/tree/dev
    1.在数据库设计表时给用户名字段添加唯一索引;
    2:前缀树

    public class SensitiveFilter {
    
    <pre><code>private static final Logger logger = LoggerFactory.getLogger(SensitiveFilter.class);
    
    private static final String REPLACEMENT = "***";
    
    // 根节点
    private TrieNode rootNode = new TrieNode();
    
    @PostConstruct
    public void init()
    {
        InputStream is = this.getClass().getClassLoader().getResourceAsStream("sensitive-filter.txt");
        BufferedReader read = new BufferedReader(new InputStreamReader(is));
    
        try {
            String keyWord;
            while((keyWord=read.readLine())!=null)
            {
                this.addKeyword(keyWord);
            }
        } catch (IOException e) {
            logger.error("加载敏感词文件失败: " + e.getMessage());
        }
    }
    
    //将一个敏感词添加到前缀树中
    private void addKeyword(String keyWord)
    {
    
        TrieNode tempNode = rootNode;
        for(int i = 0;i < keyWord.length();i ++)
        {
            char c = keyWord.charAt(i);
            TrieNode subNode = tempNode.getSubNode(c);
    
            if(subNode==null){
                subNode = new TrieNode();
                tempNode.addSubNode(c,subNode);
            }
    
            tempNode=subNode;
            if(i == keyWord.length()-1){
                tempNode.setKeywordEnd(true);
            }
        }
    }
    //过滤文本
    public String filter(String text)
    {
        if(StringUtils.isBlank(text)){
            return null;
        }
    
        TrieNode p1 = rootNode;
        int p2 = 0;
        int p3 = 0;
        StringBuilder sb = new StringBuilder();
        while(p3 < text.length())
        {
            char c = text.charAt(p3);
            if(isSymbol(c)){
    
                if(p1 == rootNode){
                    sb.append(c);
                    p2++;
                }
                p3++;
                continue;
            }
    
            p1 = p1.getSubNode(c);
            if(p1==null){
                sb.append(text.charAt(p2));
                p3 = ++p2;
                p1 = rootNode;
            }else if(p1.isKeywordEnd()==true){
                sb.append(REPLACEMENT);
                p2 = ++p3;
                p1 = rootNode;
            }else{
                p3++;
            }
        }
        sb.append(text.substring(p2));
        return sb.toString();
    }
    
    
    // 判断是否为符号
    private boolean isSymbol(Character c) {
        // 0x2E80~0x9FFF 是东亚文字范围
        return !CharUtils.isAsciiAlphanumeric(c) && (c < 0x2E80 || c > 0x9FFF);
    }
    //树结构
    private class TrieNode{
    
        private boolean iskeywordEnd = false;
    
        private HashMap<Character,TrieNode> subNodes = new HashMap<>();
    
        public boolean isKeywordEnd() {
            return iskeywordEnd;
        }
    
        public void setKeywordEnd(boolean keywordEnd) {
            iskeywordEnd = keywordEnd;
        }
    
        public void addSubNode(Character c,TrieNode node){
            subNodes.put(c,node);
        }
    
        public TrieNode getSubNode(Character c){
            return subNodes.get(c);
        }
    }
    
    }
    
    星河揽我入梦 永久会员 2024年6月10日 下午11:14

    本打卡对应问题:【任务5】注册与登录:初步完成注册相关功能
    具体打卡内容:

    CREATE TABLE user (
    id int NOT NULL AUTO_INCREMENT,
    username varchar(20) NOT NULL,
    password int NOT NULL,
    salt varchar(5) NOT NULL,
    PRIMARY KEY (id)
    ) ENGINE=InnoDB
    提交地址:https://github.com/CurryisCoat/community/tree/dev

    星河揽我入梦 永久会员 2024年6月6日 下午8:59

    本打卡对应问题:【任务4】网站首次打开网页在前端判断好还是在服务端好呢?
    具体打卡内容:

    对于网站首次打开网页时的性能优化,通常建议将一些关键逻辑放在前端进行判断,以加快页面加载速度。这样可以让用户更快地看到页面内容,并提升用户体验。同时,在服务端进行一些必要的校验和安全性检查也是很重要的,以确保用户输入的数据安全可靠。综合来看,前端和服务端各有其优势,合理分配逻辑判断和处理任务可以提高网站性能和用户体验。

    星河揽我入梦 永久会员 2024年6月5日 下午12:54

    本打卡对应问题:【任务3】让网站拥有短暂的记忆
    具体打卡内容:

    1.key = “first” value= “encodedValue”
    2.C:\Users\zouliang\AppData\Local\Microsoft\Edge\User Data\Default\Network
    3.https://github.com/CurryisCoat/community/tree/dev

    星河揽我入梦 永久会员 2024年6月3日 下午11:31

    本打卡对应问题:【任务2】创建一个web服务
    具体打卡内容:

    使用SpringBoot创建
    GitHUb地址:https://github.com/CurryisCoat/community/tree/dev

    盖瑞 永久会员 2024年5月31日 下午11:14

    本打卡对应问题:【链表专题】字节真题:单链表相加
    具体打卡内容:

    反转链表 + 字符串相加

            public ListNode plus(ListNode head1, ListNode head2) {
                if (head1 == null) return head2;
                if (head2 == null) return head1;
                ListNode num1 = reverse(head1);
                ListNode num2 = reverse(head2);
                boolean jinwei = false;
                ListNode pre = new ListNode(-1);
                ListNode ans = pre;
                while (num1 != null || num2 != null || jinwei) {
                    int num = jinwei ? 1 : 0;
                    if (num1 != null) num += num1.val;
                    if (num2 != null) num += num2.val;
                    if (num >= 10) jinwei = true;
                    else jinwei = false;
                    pre.next = new ListNode(num % 10);
                    if (num1 != null) num1 = num1.next;
                    if (num2 != null) num2 = num2.next;
                    pre = pre.next;
                }
                return reverse(ans.next);
            }
    
    星河揽我入梦 永久会员 2024年5月30日 下午11:31
    fungible 永久会员 2024年5月30日 下午11:29

    本打卡对应问题:剑指 Offer 22. 链表中倒数第k个节点🌟🌟🌟🌟🌟中等
    具体打卡内容:

    求倒数第cnt个结点,用双指针,先让前一个指针跑cnt步,随后再一起跑,前一个指针跑到终点时,后一个指针就正好到了倒数第cnt个结点
    时间复杂度:O(n)
    空间复杂度: O(1)
    class Solution {
    public ListNode trainingPlan(ListNode head, int cnt) {
    ListNode p=head,q=head;
    while(q!=null){
    while(cnt>0){//先跑cnt步
    q=q.next;
    cnt–;
    }
    while(cnt0&&q!=null){
    p=p.next;
    q=q.next;
    }
    
    }
    return p;
    }
    }

    笨笨小子 永久会员 2024年5月30日 下午5:36

    本打卡对应问题:LeetCode704.二分查找🌟🌟🌟🌟🌟简单
    具体打卡内容:

    打卡,简单复习

    开心果🍅 永久会员 2024年5月30日 上午11:29

    本打卡对应问题:回溯概念科普🌟🌟🌟🌟🌟
    具体打卡内容:

    打卡

    笨笨小子 永久会员 2024年5月29日 下午3:48

    本打卡对应问题:第二章:时间复杂度分析
    具体打卡内容:

    打卡

    笨笨小子 永久会员 2024年5月23日 上午9:50

    本打卡对应问题:第一章:如何准备一场算法面试?
    具体打卡内容:

    打卡

    mpweixin用户 普通 2024年5月18日 上午12:21

    本打卡对应问题:什么是二叉堆?
    具体打卡内容:

    阅读打卡

    mpweixin用户 普通 2024年5月16日 下午11:55

    本打卡对应问题:什么是AVL树?
    具体打卡内容:

    阅读打卡

    mpweixin用户 普通 2024年5月14日 上午11:56

    本打卡对应问题:【链表专题】剑指 Offer 35. 复杂链表的复制
    具体打卡内容:

    使用hashmap打卡成功

    mpweixin用户 普通 2024年5月14日 上午11:56

    本打卡对应问题:【链表专题】剑指 Offer 24. 反转链表
    具体打卡内容:

    两种方法都打卡成功

    mpweixin用户 普通 2024年5月14日 上午11:56

    本打卡对应问题:【链表专题】剑指 Offer 06. 从尾到头打印链表
    具体打卡内容:

    打卡成功!

    mpweixin用户 普通 2024年5月14日 上午11:55

    本打卡对应问题:【链表专题】剑指 Offer 52. 两个链表的第一个公共点
    具体打卡内容:

    d打卡成功!

    mpweixin用户 普通 2024年5月14日 上午11:55

    本打卡对应问题:【链表专题】剑指 Offer 25. 合并两个排序的链表
    具体打卡内容:

    打卡成功!!