益智小游戏 Python 一

注:本文中的题目参考自leetcode

两数之和

给定一个整数数组 nums 和一个整数目标值 target,请你在该数组中找出 和为目标值 的那 两个 整数,并返回它们的数组下标。
你可以假设每种输入只会对应一个答案。但是,数组中同一个元素不能使用两遍。
你可以按任意顺序返回答案。

解法1

class Solution:
    def twoSum(self, nums: List[int], target: int) -> List[int]:
        for i in range(len(nums)):
            for j in range(i+1,len(nums)):
                if nums[i]+nums[j] == target:
                    return i,j

解法2

class Solution:
    def twoSum(self, nums, target):
        class Iter:
            value = -1
            def __init__(self, nums):
                self.nums = nums

            def __next__(self):
                if self.value >=  len(self.nums): raise StopIteration
                self.value += 1
                return self.value

            def __iter__(self):
                return self

        c = Iter(nums)
        num = list(c)
        for i in num:
            for j in num[i+1:-1]:
                if nums[i] + nums[j] == target:
                    return i,j

两数相加

给你两个 非空 的链表,表示两个非负的整数。它们每位数字都是按照 逆序 的方式存储的,并且每个节点只能存储 一位 数字。
请你将两个数相加,并以相同形式返回一个表示和的链表。
你可以假设除了数字 0 之外,这两个数都不会以 0 开头。

疑问:不明白链表、结点怎么使用类进行抽象表述

数组实现:

class Solution:
    def palnum(self,num1,num2):
        if len(num1) > len(num2):
            for i in range(len(num1) - len(num2)):
                num2.append(0)
        else:
            for i in range(len(num2 - len(num1))):
                num1.append(0)
        return num1,num2

    def TwoSum(self,num1,num2):
        num = []
        carry = [0]
        num1, num2 = self.palnum(num1, num2)
        for i in range(len(num1)+1):
            if i != len(num1):
                sumi = num1[i] + num2[i] + carry[-1]
                num.append(sumi % 10)
                carry.append(sumi // 10)
            else:
                sumi = carry[-1]
                if sumi != 0:num.append(sumi % 10)
        return(num)

无重复字符的最长子串

给定一个字符串,请你找出其中不含有重复字符的 最长子串 的长度。

自己的思路

思路,定义一个空列表num,遍历字符串,如果num中不存在某个字符,则追加至列表中,最后获取num的长度

解题的时候发现自己理解错了,这里寻找的子串应该是连续的字符

而且没有注意到空字符串和开头为空的字符串情况

自己的逻辑:
先找出字符串中字符种类的个数,即字符串最大子串的长度m

遍历字符串,寻找有无m长度不重复子串,否则寻找m-1长度不重复子串

class Solution:
    def fnum(self,str1):
        num = []
        for i in str1:
            if i not in num:
                num.append(i)
        return num
    
    def det(self,str1):
        if len(str1) == len(self.fnum(str1)) : return True
        else: return False

    def lengthOfLongestSubstring(self, s: str) -> int:
        
        for m in reversed(range(1,len(self.fnum(s))+1)):
            for n in range(len(s) - m + 1):
                if self.det(s[n:n+m]) : 
                    return(len(s[n:n+m]))
        if s == "": return 0

链表实现

class Node:
    def __init__(self, initdata):
        self.data = initdata
        self.next = None

    def getData(self):
        return self.data

    def getNext(self):
        return self.next
    
    def setData(self, newdata):
        self.data = newdata
    
    def setNext(self, newnext):
        self.next = newnext

class UnorderList:
    def __init__(self):
        self.head = None

    def isEmpty(self):
        return self.head == None

    def add(self, item):
        temp = Node(item)
        temp.setNext(self.head)
        self.head = temp

    def pop(self):
        current = self.head
        if current != None:
            previous = current
            self.head = current.getNext()
            return previous.getData()

    def length(self):
        current = self.head
        count = 0
        while current != None:
            count = count + 1
            current = current.getNext()
        return count

    def search(self, item):
        current = self.head
        found = False
        while current != None and not found:
            if current.getData() == item:
                found = True
            else:
                current = current.getNext()
        return found

    def remove(self, item):
        current = self.head
        previous = None
        found = False
        while not found:
            if current.getData() == item:
                found = True
            else:
                previous = current
                current = current.getNext()

        if previous == None:
            self.head = current.getNext()
        else:
            previous.setNext(current.getNext())
            
class Solution:
    def palnum(self,num1,num2):
        if len(num1) > len(num2):
            for i in range(len(num1) - len(num2)):
                num2.append(0)
        else:
            for i in range(len(num2) - len(num1)):
                num1.append(0)
        return num1,num2

    def addTwoNumbers(self, list1:UnorderList, list2:UnorderList):
        num1 = []
        while(list1.isEmpty()):
            num1.append(list1.pop())
        num2 = []
        while(list2.isEmpty()):
            num2.append(list2.pop())

        num = []
        carry = [0]
        num1, num2 = self.palnum(num1, num2)
        for i in range(len(num1)+1):
            if i != len(num1):
                sumi = num1[i] + num2[i] + carry[-1]
                num.append(sumi % 10)
                carry.append(sumi // 10)
            else:
                sumi = carry[-1]
                if sumi != 0:num.append(sumi % 10)
        out = UnorderList()
        while(len(num) != 0):
            out.add(num.pop())
        return(out)

惭愧! 纸上得来终觉浅,绝知此事要躬行!

复杂度分析

与解答相比,自己的代码中不重复子串的判断是定义了一个类似于set的列表来完成的。

使用set改进自己的代码

class Solution:
    def fnum(self,str1):
        return len(set(str1))

    def det(self,str1):
        if len(str1) == self.fnum(str1): return True
        else: return False

    def lengthOfLongestSubstring(self, s: str) -> int:    
        for m in reversed(range(1,self.fnum(s)+1)):
            for n in range(len(s) - m + 1):
                if self.det(s[n:n+m]) : 
                    return(len(s[n:n+m]))
        if s == "": return 0

官方解答用到了哈希集合

class Solution:
    def lengthOfLongestSubstring(self, s: str) -> int:
        # 哈希集合,记录每个字符是否出现过
        occ = set()
        n = len(s)
        # 右指针,初始值为 -1,相当于我们在字符串的左边界的左侧,还没有开始移动
        rk, ans = -1, 0
        for i in range(n):
            if i != 0:
                # 左指针向右移动一格,移除一个字符
                occ.remove(s[i - 1])
            while rk + 1 < n and s[rk + 1] not in occ:
                # 不断地移动右指针
                occ.add(s[rk + 1])
                rk += 1
            # 第 i 到 rk 个字符是一个极长的无重复字符子串
            ans = max(ans, rk - i + 1)
        return ans

我们使用两个指针表示字符串中的某个子串(的左右边界)。其中左指针代表着上文中「枚举子串的起始位置

在每一步的操作中,我们会将左指针向右移动一格,表示 我们开始枚举下一个字符作为起始位置,然后我们可以不断地向右移动右指针,但需要保证这两个指针对应的子串中没有重复的字符。在移动结束后,这个子串就对应着 以左指针开始的,不包含重复字符的最长子串。我们记录下这个子串的长度;

在枚举结束后,我们找到的最长的子串的长度即为答案。

python 内置函数set的用法:

x = set("pwwkew")
print(x)
print(list(x))
{'e', 'w', 'k', 'p'}
['e', 'w', 'k', 'p']

复杂度分析

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/Winds_Up/article/details/112500742