LeetCode初级算法

一、数组

136. 只出现一次的数字 - 力扣(LeetCode)

from functools import reduce

def singleNumber(nums):
    return reduce(lambda x, y: x ^ y, nums)

if __name__ == '__main__':
    array = list(map(int, input().split()))
    print(array)
    s_n = singleNumber(array)
    print(s_n)

知识点:位运算

&、|、^、~、>>、<<

在计算机中都是以二进制来进行运算,在代码中直接使用(+、-、*、/)运算符,合理的运用位运算更能显著提高代码在机器上的执行效率。

位运算(&、|、^、~、>>、 | 菜鸟教程 (runoob.com)

189. 轮转数组 - 力扣(LeetCode)

要用nums[:]原地更改,同时考虑到k大于len(nums)的情况,所以要取余

nums和nums[:]的区别在于它们指向的对象不同,nums是列表对象的引用,nums[:]是对列表nums的元素的引用

方法一:

时间复杂度:O(n)

空间复杂度:O(n)

def rotate(nums, k):
    # 取余很必要
    k = k % len(nums)
    nums[:] = nums[-k:] + nums[:-k]
    return nums

if __name__ == '__main__':
    nums = list(map(int, input().split(',')))
    k = int(input())
    array = rotate(nums, k)
    print(array)

方法二:

时间复杂度:O(n*k)

空间复杂度:O(1)

# 12.75%
def rotate_list(nums, k):
    for i in range(k):
        nums.insert(0, nums.pop())
    return nums

方法三:

时间复杂度:

空间复杂度:O(1)

# 58.65%
def rotate(nums, k):
    k = k % len(nums)
    reverse(nums, 0, len(nums) - 1)
    print(nums)
    reverse(nums, 0, k - 1)
    print(nums)
    reverse(nums, k, len(nums) - 1)
    print(nums)

def reverse(nums, start, end):
    while start < end:
        nums[start], nums[end] = nums[end], nums[start]
        start += 1
        end -= 1

列表的操作

pythonic、生成器表达式(generator expression)

python list 之时间复杂度分析 - 简书

https://zhuanlan.zhihu.com/p/54011712

https://zhuanlan.zhihu.com/p/503164110

Python 列表(List) | 菜鸟教程

内置操作的时间复杂度

350. 两个数组的交集 II - 力扣(LeetCode)

方法一:

时间复杂度:O(m+n)

空间复杂度:O(min⁡(m,n))

import collections

# 52.04%
def intersect(nums1, nums2):
    """
    :type nums1: List[int]
    :type nums2: List[int]
    :rtype: List[int]
    """
    if len(nums1) > len(nums2):
        return intersect(nums2, nums1)

    h = collections.Counter()
    for n1 in nums1:
        h[n1] += 1

    result = []
    for n2 in nums2:
        if h.get(n2, 0) > 0:
            result.append(n2)
            h[n2] -= 1
            if h[n2] == 0:
                del h[n2]
    return result

if __name__ == '__main__':
    num1 = list(map(int, input().split(',')))
    num2 = list(map(int, input().split(',')))
    result = intersect(num1, num2)
    print(result)

方法二:

时间复杂度:O(mlogm + nlogn)

空间复杂度:O(min⁡(m,n))

# 74.21%
def intersect_sort(num1, num2):
    num1.sort()
    num2.sort()
    i, j = 0, 0
    result = []
    while i < len(num1) and j < len(num2):
        if num1[i] < num2[j]:
            i += 1
        elif num1[i] > num2[j]:
            j += 1
        elif num1[i] == num2[j]:
            result.append(num1[i])
            i += 1
            j += 1
    return result

哈希表/散列表:根据键(Key)直接访问在内存储存位置的数据结构

作用:实现数据到存储位置的一对一映射

collections.Counter:用于计数 hashable对象的字典子类

详解Python计数的Counter类 https://zhuanlan.zhihu.com/p/355601478

1. 两数之和 - 力扣(LeetCode)

方法一:暴力解法

时间复杂度:O(n^2)

空间复杂度:O(1)

def twoSum(nums, target):
    length = len(nums)
    for i in range(length):
        for j in range(length):
            if (i != j) and (nums[i] + nums[j] == target):
                return [i, j]

if __name__ == '__main__':
    nums = list(map(int, input().split(',')))
    target = int(input())
    result = twoSum(nums, target)
    print(result)

方法二:

时间复杂度:O(n)

空间复杂度:O(n)

# 98.80%
def twoSum_Hash(nums, target):
    hashtable = dict()
    for i, num in enumerate(nums):
        if target - num in hashtable:
            return [hashtable[target - num], i]
        hashtable[nums[i]] = i
    return []

哈希表

26. 删除有序数组中的重复项 题解 - 力扣(LeetCode)

def removeDuplicates(nums):
    """
    :type nums: List[int]
    :rtype: int
    """
    i, j = 0, 0
    length = len(nums)
    result = []
    while i < length:
        if j < length and nums[i] == nums[j]:
            j += 1
        else:
            result.append(nums[i])
            i = j
    nums[:] = result
    return len(result)

if __name__ == '__main__':
    nums = list(map(int, input().split(',')))
    len = removeDuplicates(nums)
    print(len)
    # 91.92%
    def removeDuplicates(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        i, j = 0, 1
        length = len(nums)
        while j  < length:
            if nums[i] == nums[j]:
                j += 1
            else:
                nums[i + 1] = nums[j]
                i += 1
        return i + 1

二、字符串

344. 反转字符串 - 力扣(LeetCode)

def reverseString(s):
    """
    :type s: List[str]
    :rtype: None Do not return anything, modify s in-place instead.
    """
    for i in range(len(s) >> 1):
        s[i], s[- i - 1] = s[- i - 1], s[i]

if __name__ == '__main__':
    s = input().split(',')
    reverseString(s)
    print(s)

python列表的两种索引方式、>>运算符、直接a,b=b,a交换更快

387. 字符串中的第一个唯一字符 - 力扣(LeetCode)

方法一:

时间复杂度:O(n)

空间复杂度:O(∣Σ∣),∣Σ∣≤26

def firstUniqChar(s):
    """
    :type s: str
    :rtype: int
    """
    h = collections.Counter(s)
    for i, ch in enumerate(s):
        if h.get(ch, 0) == 1:
            return i
    return -1

if __name__ == '__main__':
    s = input()
    reuslt = firstUniqChar(s)
    print(reuslt)

8. 字符串转换整数 (atoi) - 力扣(LeetCode)

def myAtoi(s):
    """
    :type s: str
    :rtype: int
    """
    res = 0
    flag = 1
    i = 0
    for i in range(len(s)):
        if s[i] == ' ':
            i = i + 1
        elif s[i] == '+':
            flag = 1
            i = i + 1
            break
        elif s[i] == '-':
            flag = -1
            i = i + 1
            break
        else:
            break

    for j in range(i, len(s)):
        if '0' <= s[j] <= '9':
            res = res * 10 + int(s[j])
        elif 'a' <= s[j] <= 'z' or 'A' <= s[j] <= 'Z' or s[j] == '.' or s[j] == '+' or s[j] == '-' or s[j] == ' ':
            break
    res = flag * res
    if res < -1 * pow(2, 31):
        res = -1 * pow(2, 31)
    elif res > pow(2, 31) - 1:
        res = pow(2, 31) - 1
    return res
if __name__ == '__main__':
    s = input()
    res = myAtoi(s)
    print(res)

方法二:自动机

INT_MAX = 2 ** 31 - 1
INT_MIN = -2 ** 31

class Automaton:
    def __init__(self):
        self.state = 'start'
        self.sign = 1
        self.ans = 0
        self.table = {
            'start': ['start', 'signed', 'in_number', 'end'],
            'signed': ['end', 'end', 'in_number', 'end'],
            'in_number': ['end', 'end', 'in_number', 'end'],
            'end': ['end', 'end', 'end', 'end'],
        }

    def get_col(self, c):
        if c.isspace():
            return 0
        if c == '+' or c == '-':
            return 1
        if c.isdigit():
            return 2
        return 3

    def get(self, c):
        self.state = self.table[self.state][self.get_col(c)]
        if self.state == 'in_number':
            self.ans = self.ans * 10 + int(c)
            self.ans = min(self.ans, INT_MAX) if self.sign == 1 else min(self.ans, -INT_MIN)
        elif self.state == 'signed':
            self.sign = 1 if c == '+' else -1

class Solution(object):
    def myAtoi(self, s):
        """
        :type s: str
        :rtype: int
        """
        automaton = Automaton()
        for c in s:
            automaton.get(c)
        return automaton.sign * automaton.ans

方法三:正则表达式

def myAtoi(self, s):
    """
    :type s: str
    :rtype: int
    """
    return max(min(int(*re.findall('^[\+\-]?\d+', s.lstrip())), 2 ** 31 - 1), -2 ** 31)
  • 使用正则表达式 ^:匹配字符串开头,[\+\-]:代表一个+字符或-字符,?:前面一个字符可有可无,\d:一个数字,+:前面一个字符的一个或多个,\D:一个非数字字符
  • max(min(数字, 2**31 - 1), -2**31) 用来防止结果越界

*代表的传递参数,传递无名参数,你可以搜一下python *的用法

*实际上是对re.findall的结果进行操作。findall函数返回所有找到的结果,用一个list表示,*是解包,因为我们的答案只有一个也就是说list中只会有一个元素,所以直接解包就可以了。解包:[1,2,3]→1,2,3

28. 找出字符串中第一个匹配项的下标 - 力扣(LeetCode)

方法一:暴力求解

# 78.23%
def strStr(haystack, needle):
    """
    :type haystack: str
    :type needle: str
    :rtype: int
    """
    i, j = 0, 0
    if len(haystack) < len(needle):
        return -1
    for i in range(len(haystack)):
        for j in range(len(needle)):
            if i + j > len(haystack) - 1:
                return -1
            elif haystack[i + j] != needle[j]:
                break
            elif j >= len(needle) - 1:
                return i
    return -1

最浅显易懂的 KMP 算法讲解_哔哩哔哩_bilibili

方法二:KMP算法

# 49.74%

def strStr(haystack, needle):
    next = getnext(needle)
    i, j = 0, 0
    while i < len(haystack):
        if haystack[i] == needle[j]:
            i = i + 1
            j = j + 1
        elif j > 0:
            j = next[j - 1]
        else:
            i = i + 1

        if j >= len(needle):
            return i - j
    return -1

def getnext(needle):
    '''
    param needle:
    return:
    example:
        aabaaf
        [0, 1, 0, 1, 2, 0]
    '''
    next = ['' for i in range(len(needle))]
    next[0] = k = 0
    for i in range(1, len(needle)):
        while k > 0 and needle[k] != needle[i]:
            k = next[k - 1]
        if needle[k] == needle[i]:
            k += 1
        next[i] = k
    return next

if __name__ == '__main__':
    haystack = input()
    needle = input()
    res = strStr(haystack, needle)
    print(res)

求解next数组的代码:根据已经掌握的信息规避重复的运算。

三、链表

206. 反转链表 - 力扣(LeetCode)

方法一:三个指针,其实可以优化为两个指针

# 77.63%
def reverseList(head):
    """
    :type head: ListNode
    :rtype: ListNode
    """
    if head == None:
        return None

    front = head.next
    rear = head
    rear.next = None

    while front != None:
        head = front
        front = front.next
        head.next = rear
        rear = head
    return head

方法二:两个指针

 # 98.83%
 def reverseList(head):
    """
    :type head: ListNode
    :rtype: ListNode
    """
    # 申请两个节点,pre和 cur,pre指向None
    pre = None
    cur = head
    # 遍历链表,while循环里面的内容其实可以写成一行
    while cur:
        # 记录当前节点的下一个节点
        tmp = cur.next
        # 然后将当前节点指向pre
        cur.next = pre
        # pre和cur节点都前进一位
        pre = cur
        cur = tmp
    return pre	

上面两种感觉差不多

方法三:递归

	def reverseList(self, head):
		"""
		:type head: ListNode
		:rtype: LitNode
		"""
		# 递归终止条件是当前为空,或者下一个节点为空
		if(head==None or head.next==None):
			return head
		# 这里的cur就是最后一个节点
		cur = self.reverseList(head.next)
		# 这里请配合动画演示理解
		# 如果链表是 1->2->3->4->5,那么此时的cur就是5
		# 而head是4,head的下一个是5,下下一个是空
		# 所以head.next.next 就是5->4
		head.next.next = head
		# 防止链表循环,需要将head.next设置为空
		head.next = None
		# 每层递归函数都返回cur,也就是最后一个节点
		return cur
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值