Python学习(Leetcode 算法题解【1~20】)

掌握了python的基础概念,并不意味着就可以使用python来进行项目开发了。学习一门编程语言时,对于概念的掌握只是基础。用该语言去解决实际问题,并在解决问题的过程中学习才是学一门语言时费时较长的部分。
Leetcode上的算法题目都比较经典,各个难度层次的题目都有,因此可以让各个水平参差的程序员与算法爱好者找到适合自己的题目。一般有参加ACM或者topcoder意向的程序员都会选择在Leetcode上练手。而且Leetcode上的很多题目来源于企业的笔试题,刷Leetcode上的算法题,对于以后求职也有一定的帮助。
基于以上几点,我开始在Leetcode上用python去解决基础的算法题目。根据Acceptance从高到低的顺序,一道一道往下刷。所有刷过的题目,都会在此附上题目、解题思路和代码。文章较长,可通过Ctrl+F进行查找。这篇博文也会随着解决的题目的增加而继续更新。

Leetcode的python框架

题目中会给定输入和输出的格式,需要在实现相应的算法功能后,将结果返回。
一般Leetcode的编辑器会给出你所需要编写的代码的框架,如:

class Solution(object):           #类的继承
    def reverseString(self, s):   #类方法
        """
        :type s: str              #输入数据类型
        :rtype: str               #输出数据类型
        """
                                  #代码填充区域

334. Reverse String

题目:
Write a function that takes a string as input and returns the string reversed.

Example:
Given s = “hello”, return “olleh”.
解题思路:
这道题目其实非常简单,如果用C语言的思路去解决,需要先读取字符串长度,然后从后往前读取字符串的每个字符,并将它们拼成一个新字符串后输出。
代码(1):

class Solution(object):           
    def reverseString(self, s):   
        """
        :type s: str             
        :rtype: str              
        """
        s1=''
        l=len(s)
        for x in range(l)
            s1+=s[l-1-x]
        return s1                             

实际上,在python的字符串类中,已经存在类似于matlab的对于字符串的读取方式。可以通过设置起始值、终止值、步长的方式来访问字符串中特定位置的字符。
代码(2):

class Solution(object):           
    def reverseString(self, s):   
        """
        :type s: str             
        :rtype: str              
        """
        return s[::-1]

一行代码就可以完成。
由此可见,正确地使用编程语言中自带的表示方式有时候和算法思想一样重要。

338. Counting Bits

题目:
Given a non negative integer number num. For every numbers i in the range 0 ≤ i ≤ num calculate the number of 1’s in their binary representation and return them as an array.

Example:
For num = 5 you should return [0,1,1,2,1,2].

Follow up:

It is very easy to come up with a solution with run time O(n*sizeof(integer)). But can you do it in linear time O(n) /possibly in a single pass?
Space complexity should be O(n).
Can you do it like a boss? Do it without using any builtin function like __builtin_popcount in c++ or in any other language.
思路:
由于需要返回0-num的所有的数字的二进制中1的个数,因此最好前面几个数的结果可以为后面的数所用。
代码:

class Solution(object):
    def countBits(self, num):
        """
        :type num: int
        :rtype: List[int]
        """
        ans=[0]
        for x in range(1,num+1):
            ans+=[ans[x&x-1]+1]
        return ans

292. Nim Game

题目:
You are playing the following Nim Game with your friend: There is a heap of stones on the table, each time one of you take turns to remove 1 to 3 stones. The one who removes the last stone will be the winner. You will take the first turn to remove the stones.

Both of you are very clever and have optimal strategies for the game. Write a function to determine whether you can win the game given the number of stones in the heap.

For example, if there are 4 stones in the heap, then you will never win the game: no matter 1, 2, or 3 stones you remove, the last stone will always be removed by your friend.
思路:
这道题目其实很简单。如果开始的石子个数是4的倍数,后拿的人必胜。后拿的人,只需要保证每次拿的个数和对方拿的个数的和为4,就能确保胜利。而如果开始的石子个数不是4的倍数,先拿的人必胜。因为他可以先拿走1-3个,让剩下的石子的个数为4的倍数,接下来的情况与开始石子个数为4的倍数类似,他只需要保证之后每次他拿的石子个数与对方的和为4即可。

class Solution(object):
    def canWinNim(self, n):
        """
        :type n: int
        :rtype: bool
        """
        return (n%4)!=0

一行代码就解决了。

371. Sum of Two Integers

题目:
Calculate the sum of two integers a and b, but you are not allowed to use the operator + and -.

Example:
Given a = 1 and b = 2, return 3.
思路:没什么好说的,太简单了。
代码:

class Solution(object):
    def getSum(self, a, b):
        """
        :type a: int
        :type b: int
        :rtype: int
        """
        return a+b

136. Single Number

题目:
Given an array of integers, every element appears twice except for one. Find that single one.

Note:
Your algorithm should have a linear runtime complexity. Could you implement it without using extra memory?
思路:不使用过多内存,时间复杂度为线性。使用list变量中的count函数来实现。
代码(1):

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        for  x in nums:
            if nums.count(x)==1
                return x

结果时间复杂度超了。当nums比较复杂时,运行时间超限。
代码(2):

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        B={}
        for i in nums:
            if i not in B:
                B[i]=1
            else:
                B[i]=2
        for i in B:
            if B[i]==1:
                ret=i
                break
        return ret

采用这种两次循环的方式来实现,却通过了。个人理解为python中使用list.count()函数,其中的源代码也是通过循环来实现,其代码的时间复杂度未知,使用时可能会出现运算时间长的情况。

258. Add Digits

题目:
Given a non-negative integer num, repeatedly add all its digits until the result has only one digit.

For example:

Given num = 38, the process is like: 3 + 8 = 11, 1 + 1 = 2. Since 2 has only one digit, return it.

Follow up:
Could you do it without any loop/recursion in O(1) runtime?
思路:首先可以通过循环来实现。但是其时间复杂度明显大于O(1)。
代码(1):

class Solution(object):
    def addDigits(self, num):
        """
        :type num: int
        :rtype: int
        """
        while num>9:
            num=sum(int(i) for i in str(num))
        return num

思考其中的规律,由于最终返回的数字的范围为0-9且addDigits(n)=addDigits(n+9),n>0。因此可以写出以下代码:
代码(2):

class Solution(object):
    def addDigits(self, num):
        """
        :type num: int
        :rtype: int
        """
        if num==0:
            return 0
        else:
            return 1+(num-1)%9

104. Maximum Depth of Binary Tree

题目:
Given a binary tree, find its maximum depth.

The maximum depth is the number of nodes along the longest path from the root node down to the farthest leaf node.
思路:
通过递归的方式来实现。
代码:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def maxDepth(self, root):
        """
        :type root: TreeNode
        :rtype: int
        """
        if root is None:
            return 0
        else:
            return 1+max(self.maxDepth(root.left),self.maxDepth(root.right))

226. Invert Binary Tree

题目:
Invert a binary tree.
4
/ \
2 7
/ \ / \
1 3 6 9

to
4
/ \
7 2
/ \ / \
9 6 3 1
思路:仍旧是递归的思想。
代码:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def invertTree(self, root):
        """
        :type root: TreeNode
        :rtype: TreeNode
        """
        if root is None:
            return None
        else:
            temp=root.left;
            root.left=self.invertTree(root.right);
            root.right=self.invertTree(temp);
        return root

260. Single Number III

题目:
Given an array of numbers nums, in which exactly two elements appear only once and all the other elements appear exactly twice. Find the two elements that appear only once.

For example:

Given nums = [1, 2, 1, 3, 2, 5], return [3, 5].

Note:
The order of the result is not important. So in the above example, [5, 3] is also correct.
Your algorithm should run in linear runtime complexity. Could you implement it using only constant space complexity?
思路:同之前的Single Number.

class Solution(object):
    def singleNumber(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        B={}
        for i in nums:
            if i not in B:
                B[i]=1
            else:
                B[i]=2
        ret=[]
        for i in nums:
            if B[i]==1:
                ret+=[i]
        return ret

283. Move Zeroes

题目:
Given an array nums, write a function to move all 0’s to the end of it while maintaining the relative order of the non-zero elements.

For example, given nums = [0, 1, 0, 3, 12], after calling your function, nums should be [1, 3, 12, 0, 0].

Note:
You must do this in-place without making a copy of the array.
Minimize the total number of operations.
思路:
我首先想到的是通过交换位置的方式,通过while循环来逐渐将0往后移。

class Solution(object):
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        i=0
        while(sum(abs(nums[j]) for j in range(i,len(nums)))!=0):
            if nums[i]==0:
                for j in range(i,len(nums)-1):
                    nums[j]=nums[j+1]
                nums[-1]=0
            else:
                i+=1
        return

这种方式能够实现简单的移动零的操作,但是数据量大时,运行时间过长。
想起list类型的数据中有list.count()、list.remove()、list.append()函数,于是用这几个函数来实现。

class Solution(object):
    def moveZeroes(self, nums):
        """
        :type nums: List[int]
        :rtype: void Do not return anything, modify nums in-place instead.
        """
        zn=nums.count(0);
        for i in range(zn):
            nums.remove(0);
            nums.append(0);
        return

349. Intersection of Two Arrays

题目:
Given two arrays, write a function to compute their intersection.

Example:
Given nums1 = [1, 2, 2, 1], nums2 = [2, 2], return [2].

Note:
Each element in the result must be unique.
The result can be in any order.
思路:
依次判断List1中的元素是否在List2中出现,如果出现则将其加入到返回列表中。最后通过集合类型的数据的特性,将返回列表中重复元素去掉。
代码:

class Solution(object):
    def intersection(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        ret=[]
        for i in nums1:
            if i in nums2:
                ret+=[i]
        ret=list(set(ret))
        return ret

237. Delete Node in a Linked List

题目:

Write a function to delete a node (except the tail) in a singly linked list, given only access to that node.

Supposed the linked list is 1 -> 2 -> 3 -> 4 and you are given the third node with value 3, the linked list should become 1 -> 2 -> 4 after calling your function.
思路:题目表述不是特别清楚,不太明白node.next的数据类型,通过尝试不同的方式解出。
代码:

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.next = None

class Solution(object):
    def deleteNode(self, node):
        """
        :type node: ListNode
        :rtype: void Do not return anything, modify node in-place instead.
        """
        node.val=node.next.val
        node.next=node.next.next
        return

238. Product of Array Except Self

题目:
Given an array of n integers where n > 1, nums, return an array output such that output[i] is equal to the product of all the elements of nums except nums[i].

Solve it without division and in O(n).

For example, given [1,2,3,4], return [24,12,8,6].

Follow up:
Could you solve it with constant space complexity? (Note: The output array does not count as extra space for the purpose of space complexity analysis.)
思路:
此题有一定难度,需要一定的算法基础才能解决这道题。
可以考虑的是,用两个数组left和right分别存储对应元素左、右边元素依次相乘的值。通过一个遍历即可实现。
然后在第二个循环中,将对应的left和right数组中的值相乘。
代码:
首先,我自己写了一遍代码:
代码(1):

class Solution(object):
    def productExceptSelf(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        l=len(nums)
        left=list[l]
        right=list[l]
        left[0]=1;
        right[0]=1;
        for i in range(1,l):
            left[i]=left[i-1]*nums[i-1]
            right[i]=right[i-1]*nums[l-i]
        right=right[::-1]

        ret=[]
        for i in range(len(nums)):
            ret+=[left[i]*right[i]]
        return ret

结果时间超出。
然后找了同种思路的网上的一份代码:
代码(2):

class Solution(object):
    def productExceptSelf(self, nums):
        """
        :type nums: List[int]
        :rtype: List[int]
        """
        result = [1]

        for i in range(1,len(nums)):
            result.append(result[i-1] * nums[i-1])

        product = 1
        for i in range(len(nums)-1,-1,-1):
            result[i] = product * result[i]
            product *= nums[i]

        return result

第二份代码中与第一份代码的计算量的差别主要在于对right数组的反向操作上。空间使用率主要在于第二份代码中,不必用数组存储left和right,而是对空间进行重复使用,并在第二层循环中,即时地计算right的值,并即时存入最终返回的数组中。

由此可见,即使是相同的算法思路,通过不同的代码组织方式,得到结果效率差别可能会很大。

100. Same Tree

题目:
Given two binary trees, write a function to check if they are equal or not.

Two binary trees are considered equal if they are structurally identical and the nodes have the same value.
思路:迭代。
代码:

# Definition for a binary tree node.
# class TreeNode(object):
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None

class Solution(object):
    def isSameTree(self, p, q):
        """
        :type p: TreeNode
        :type q: TreeNode
        :rtype: bool
        """
        if p is None and q is None:
            return True
        else:
            if p is None or q is None:
                return False
            else:
                flag1=(p.val==q.val)
                flag2=self.isSameTree(p.left,q.left)
                flag3=self.isSameTree(p.right,q.right)
                return flag1 and flag2 and flag3

122. Best Time to Buy and Sell Stock II

题目:
Say you have an array for which the i-th element is the price of a given stock on day i.

Design an algorithm to find the maximum profit. You may complete as many transactions as you like (ie, buy one and sell one share of the stock multiple times). However, you may not engage in multiple transactions at the same time (ie, you must sell the stock before you buy again).
思路:找出所有的后一时刻价格大于前一时刻价格的时间,并将其差值加到返回值上。
代码:

class Solution(object):
    def maxProfit(self, prices):
        """
        :type prices: List[int]
        :rtype: int
        """
        ret=0
        for time in range(len(prices)-1):
            profit=prices[time+1]-prices[time]
            ret+=(profit>0)*profit
        return ret

347. Top K Frequent Elements

题目:
Given a non-empty array of integers, return the k most frequent elements.

For example,
Given [1,1,1,2,2,3] and k = 2, return [1,2].

Note:
You may assume k is always valid, 1 ≤ k ≤ number of unique elements.
Your algorithm’s time complexity must be better than O(n log n), where n is the array’s size.
思路:硬解,直接计算每种元素的个数,并进行排序即可。
代码:

class Solution(object):
    def topKFrequent(self, nums, k):
        """
        :type nums: List[int]
        :type k: int
        :rtype: List[int]
        """
        uniquenums=list(set(nums))
        count=[]
        l=len(uniquenums)
        for i in range(0,l):
            count+=[nums.count(uniquenums[i])]

        for i in range(0,l-1):
            for j in range(i+1,l):
                if count[i]return uniquenums[0:k]

171. Excel Sheet Column Number

题目:
Related to question Excel Sheet Column Title

Given a column title as appear in an Excel sheet, return its corresponding column number.

For example:

A -> 1
B -> 2
C -> 3
...
Z -> 26
AA -> 27
AB -> 28 

思路:建立字典,然后依次计算即可。
代码:

class Solution(object):
    def titleToNumber(self, s):
        """
        :type s: str
        :rtype: int
        """
        C2N={'A':1,'B':2,'C':3,'D':4,'E':5,'F':6,'G':7,'H':8,'I':9,'J':10,'K':11,'L':12,'M':13,'N':14,'O':15,'P':16,'Q':17,'R':18,'S':19,'T':20,'U':21,'V':22,'W':23,'X':24,'Y':25,'Z':26}
        ret=0
        for i in s:
            ret=26*ret+C2N[i]
        return ret

242. Valid Anagram

题目:
Given two strings s and t, write a function to determine if t is an anagram of s.

For example,
s = “anagram”, t = “nagaram”, return true.
s = “rat”, t = “car”, return false.

Note:
You may assume the string contains only lowercase alphabets.

Follow up:
What if the inputs contain unicode characters? How would you adapt your solution to such case?
思路:对比两个字符串中字符的个数是否相等即可。
代码:

class Solution(object):
    def isAnagram(self, s, t):
        """
        :type s: str
        :type t: str
        :rtype: bool
        """
        if len(s)!=len(t):
            return False
        s1=list(set(s))
        for ss in s1:
            if s.count(ss)!=t.count(ss):
                return False
        return True

357. Count Numbers with Unique Digits

题目:
Given a non-negative integer n, count all numbers with unique digits, x, where 0 ≤ x < 10n.

Example:
Given n = 2, return 91. (The answer should be the total numbers in the range of 0 ≤ x < 100, excluding [11,22,33,44,55,66,77,88,99])
思路:首先,在一定范围内,可以通过递归实现。但是发现递归次数过多。后来想到其实返回值只有10个,直接查表会十分简单。先写了个简单程序求出所有值,然后建表后查表即可。
代码:

class Solution(object):
    def countNumbersWithUniqueDigits(self, n):
        """
        :type n: int
        :rtype: int
        """
        dict=[1,10,91,739,5275,32491,168571,712891,2345851,5611771]
        if n>9:
            return 5611711
        else:
            return dict[n]

169. Majority Element

题目:
Given an array of size n, find the majority element. The majority element is the element that appears more than ⌊ n/2 ⌋ times.

You may assume that the array is non-empty and the majority element always exist in the array.

Credits:
Special thanks to @ts for adding this problem and creating all test cases.
思路:硬解即可。
代码:

class Solution(object):
    def majorityElement(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        l=len(nums)/2
        uniquenums=list(set(nums))
        for x in uniquenums:
           if nums.count(x)>l:
               return x

至此,leetcode中最简单的20道题已经完成,为了避免一篇博文过长,后面的题目将新开一篇博文。

你可能感兴趣的:(Python-学习,算法学习)