重新拣起算法-第一阶段:找回手感(数组与字符串)

编程  ·  2026-09-10   全文 1915 字,阅读约 7 分钟

之前尝试刷力扣灵神的算法题单,但是我没有算法基础(没上过课),还是个文科生,所以刷起来太费劲了,才第一章节的滑动窗口,勉强刷完中级题,到后面2-3个小时还理解不了题目,断签了一天之后没动力了,就一直没再刷。现在有空了,决定重新捡起来。但毕竟很久不写代码了,现在脚本也都让DS老师生成语法都忘得差不多了,所以让DS老师帮忙制定了一个学习方案。

学习方案

第一阶段:找回手感(数组与字符串)
目标:熟悉平台,找回代码感觉。

Two Sum (1) - 哈希表的经典入门
Palindrome Number (9) - 熟悉数字与字符串操作
Valid Parentheses (20) - 栈结构的基础应用
Merge Two Sorted Lists (21) - 链表基础操作
Best Time to Buy and Sell Stock (121) - 简单的数组遍历
Valid Palindrome (125) - 双指针入门

第二阶段:夯实基础(哈希表与链表)
目标:掌握核心数据结构,理解“空间换时间”。

Contains Duplicate (217) - 哈希集合应用
Valid Anagram (242) - 哈希表计数字典
Reverse Linked List (206) - 链表反转,重中之重
Linked List Cycle (141) - 快慢指针
Remove Duplicates from Sorted Array (26) - 双指针/快慢指针
Single Number (136) - 位运算入门

第三阶段:接触核心算法(递归、树与二分查找)
目标:理解递归思想,接触更抽象的数据结构。

Maximum Depth of Binary Tree (104) - 递归入门
Climbing Stairs (70) - 简单动态规划
Binary Tree Inorder Traversal (94) - 中序遍历
Invert Binary Tree (226) - 递归练习
Binary Search (704) - 二分查找模板

新的开始
因为发现中文的一些翻译太晦涩难懂了,所以决定重新用英文版的leetcode开始刷(顺便也练习下英语),一开始提交第一题的时候发现和我之前第一次提交一样,都是用暴力算法,之前偷懒了,因为觉得能通过就行,不一定要按题目知识点来,才会踏进同一条河流。现在有空,就一道道吃透吧。

Two Sum (1) - 哈希表的经典入门
第一次解题只想着相邻的数,但刚好用例都绿了就提交了,提交后报错才突然发现理解错了。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        number = 0
        answer = []
        for number in range(len(nums)):
            if nums[number]+nums[number+1] == target:
                answer.append(number)
                answer.append(number+1)
                return  answer
            else:
                number += 1

第二次解题用了暴力算法,速度很慢但占用内存小,然后突然想起来第一次刷力扣的时候似乎也是用的这种解法,速度很慢但占用内存。决定要吃透题目和做笔记。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        for num1 in range(len(nums)):
            for num2 in range(len(nums)):
                if target - nums[num1] == nums[num2] and num1 != num2 :
                    return [num1,num2]
            

image.png
第三次解题,原来不知道啥是哈希表,听了DS老师解题才明白过来。解法的for没有进行计算,只是逐个记录。相当于每个人都登记之后,找到第一个登记后和以前登记的人配对成功等于target的俩人的位置。

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        done ={}
        for num in range(len(nums)):
            now = nums[num]
            need = target - now
            if need in done:
                return [done[need],num]
            done[now] = num

image.png
Palindrome Number (9) - 熟悉数字与字符串操作
第一次解法,一开始想着是个位数的情况要单独处理还想到用位数计算法,然后突然看到有字符串的提示,那应该是用字符串的解法。想到反转,错用了列表的reverse,问了DS老师的字符串反转方法,原来是切片,[::-1]反转。所以很好解。加一个负数判断的话速度和内存都更优。

class Solution:
    def isPalindrome(self, x: int) -> bool:
        if x < 0 :
            return False
        else:
            if str(x) == str(x)[::-1]:
                return True
            else:
                return False

image.png

Valid Parentheses (20) - 栈结构的基础应用
第一次解题,倒是知道计算方法,但是写成语法不知道怎么写了。pop()里面应该用的索引,内容和索引经常搞混。

class Solution:
    def isValid(self, s: str) -> bool:
        left = ['(', '{', '[' ]
        right = [ ')', '}', ']']
        dic={')':'(' , '}':'{', ']':'[' }
        current = []
        new = ''
        for i in range(len(s)):
            if s[i] in right :
                if current == []:
                    return False 
                elif dic[s[i]] == current[-1]:
                    current.pop(-1)
                else :
                    return False
            else :
                current.append(s[i])
        if current == []:
            return True
        else : 
            return False

image.png
第二次解题,问了DS老师为什么我的代码速度和内存这么落后,发现俩问题一个是和上一题一样考虑如果是奇数就不成对了,直接返回错误就行。另一个是左右列表其实没用,重复了,就用一个字典就好了。

class Solution:
    def isValid(self, s: str) -> bool:
        dic={')':'(' , '}':'{', ']':'[' }
        current = []
        if len(s)%2 == 0:
            for i in range(len(s)):
                if s[i] in dic :
                    if current == []:
                        return False 
                    elif dic[s[i]] == current[-1]:
                        current.pop(-1)
                    else :
                        return False
                else :
                    current.append(s[i])
            if current == []:
                return True
            else : 
                return False
        else:
            return False

image.png
Merge Two Sorted Lists (21) - 链表基础操作
第一次解题,这个真的是怎么想到理解不了链表的设计。listN直接指代节点,val是值,next是下一位。一整个链表没有位置索引有点不习惯。和DS老师对话多轮才理解下来。

# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def mergeTwoLists(self, list1: Optional[ListNode], list2: Optional[ListNode]) -> Optional[ListNode]:
        list3 = ListNode(0)
        tail = list3
        while list1 and list2:
            if list1.val >= list2.val:
                tail.next = list2
                list2 =list2.next
            else :
                tail.next = list1
                list1 =list1.next
            tail = tail.next
        tail.next = list1 or list2
        return list3.next

image.png

Best Time to Buy and Sell Stock (121) - 简单的数组遍历
第一次解题,用了暴力遍历的方法,数据大的时候超时了。

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        current = 0
        for i in range(len(prices)):
            for j in range(i,len(prices)):
                if current < prices[j]-prices[i]:
                    current = prices[j]-prices[i]
        return current

image.png
第二次解题,维护两个变量一个是最小价格,每次按当天减掉最小价格,维护一个最高利润。

class Solution:
    def maxProfit(self, prices: List[int]) -> int:
        min_price = prices[0]
        max_profit = profit = 0
        for day in range(len(prices)):
            if prices[day] < min_price :
                min_price = prices[day]
            profit = prices[day] - min_price
            if profit > max_profit :
                max_profit = profit 
        return max_profit 

image.png
Valid Palindrome (125) - 双指针入门
第一次解法,有一个错误的地方是忘记了给处理后的数值赋值,导致用例origin没改变。

class Solution:
    def isPalindrome(self, s: str) -> bool:
        origin = '' 
        for w in range(len(s)):
            if s[w].isalnum():
                origin += s[w]
        origin = origin.lower()
        return origin[::-1] == origin

image.png
第二次解题,发现题目要求的双指针,但是我这个解法没用到指针呢。重新想。这里犯过三次错误,第一次是同时计算左右两边的对比,但是两边的符号数可能不一样所以无法同步比较。第二次是不理解为什么在外部while不能使用left不等于right判断,原因是如果长度是偶数,可能导致加减后双方擦肩而过比如0,32,1,就会越界,所以只能用大小判断。最后一次错误是为什么外部已经判断了左边小于右边的情况下还需要在内部继续判断左右大小,因为最后在内部的while结束后还有一轮无条件的左右加减,如果左右也是偶数的情况,有可能也会擦肩而过越界。

class Solution:
    def isPalindrome(self, s: str) -> bool:
        left = 0
        right = len(s)-1
        while left < right : 
            while not s[left].isalnum() and left < right:
                left +=1
            while not s[right].isalnum() and left < right:
                right -=1
            if s[left].lower() != s[right].lower():
                return False
            left +=1
            right -=1
        return True

image.png

下一篇:没有了
评论
yk1537. All Rights Reserved. Theme Jasmine by Kent Liao.