今天正是开始刷LeetCoded的题目了。计划先开始用python刷Easy的题,一下会记录题目和相关解析。
---2018/03/08------
女神节快乐!一大早起来刷题,就是满足感爆棚!
53 - Maximum Subarray
Find the contiguous subarray within an array (containing at least one number) which has the largest sum.
For example, given the array [-2,1,-3,4,-1,2,1,-5,4], the contiguous subarray [4,-1,2,1] has the largest sum = 6.
解法一:
解题思路:“动态规划”,比较经典的动态规划的题目。主要有以下几个概念,依次计算以第k个数作为子数组末尾的最优子数组(和最大)的和dp[],然后求dp中的最大值。那递推关系是怎样的呢,当把下一个数字num[k+1]最为末尾数字时,要看它之前与它相连的子数组的和是否是正的,如果是正的,应该加上,否则舍弃。下面的代码把求dp和求dp中的最大值一起计算了,所以没有额外的数组dp。in short: 一旦前面总和<0,说明前面的加进去也是没用的,所以全部抛弃.
class Solution(object):
def maxSubArray(self, nums):
"""
:type nums: List[int]
:rtype: int
"""
nums = [-2, 1, -3, 4, -1, 2, 1, -5, 4]
length = len(nums)
current = nums[0]
m = current
for i in range(1, length):
if current < 0:
current = 0
current += nums[i]
m = max(current,m)
return m
if __name__ == "__main__":
result = Solution().maxSubArray([-2, 1, -3, 4, -1, 2, 1, -5, 4])
print (result)
解法二:分治法
class Solution(object):
def maxSubArrayHelper(self,nums, l, r):
if l > r:
return -2147483647
m = (l+r) / 2
leftMax = sumNum = 0
for i in range(m - 1, l - 1, -1): # 从中间向左遍历
sumNum += nums[i]
leftMax = max(leftMax, sumNum)
rightMax = sumNum = 0
for i in range(m + 1, r + 1): # 从中间向右遍历
sumNum += nums[i]
rightMax = max(rightMax, sumNum)
leftAns = self.maxSubArrayHelper(nums, l, m - 1)
rightAns = self.maxSubArrayHelper(nums, m + 1, r)
return max(leftMax + nums[m] + rightMax, max(leftAns, rightAns))
def maxSubArray(self, nums):
return self.maxSubArrayHelper(nums, 0, len(nums) - 1)
-----2018/03/07----
怎么一眨眼就2天没刷题了。。。现在真的是深刻体会到了“刷题可以让人安心”这句话的含义了。。。
想买包的时候,刷两题;
想偷懒的时候,刷两题;
想看剧的时候,刷两题;
想出去玩的时候,刷两题;
想。。。。
前天跳跃着上了下CS61B讲算法runtime的部分,本想找个简单的O答案的,结果还是没找到,Josh Hug明说了,没有捷径,就是要递归慢慢算.....
昨晚实在太累,9点多就和娃娃一起倒下,再也没有起来.....
今天白天也没上课,就光折腾我的GitHub和Blog了。过程很艰辛,各种卸载重装,各种tutorial,总算用GitHub Page搞出了个Blog的框架。下一步要研究出来如何在GitHub Page上显示Jupyter Notebook。
嗯,好了,继续刷题。。。
38. Count and Say
1. 1
2. 11
3. 21
4. 1211
5. 111221
Given an integer n, generate the nth term of the count-and-say sequence. Note: Each term of the sequence of integers will be represented as a string.
思路:Idea here is keep track of the first letter in the sequence and count
consecutive occurances. Once you encounter a new letter you add the previous
count and letter to the chain. Repeat n-1 times (since we seeded the initial ‘1’ case).
We always update temp after the inner loop since we will never have already added the last sequence.
这道题 关键是要把‘1211’里的每一位看作是string,而不是integer.
代码:
def countAndSay(self, n):
s= '1'
for i in range(n-1):
letter, temp,count = s[0], '', 0
for k in s:
if letter == k:
count += 1
else:
temp = str(count) + letter
letter = k
count = 1
temp += str(count) + letter
s = temp
return s
35. Search Insert Position
Given a sorted array and a target value, return the index if the target is found. If not, return the index where it would be if it were inserted in order. You may assume no duplicates in the array.
Example1:Input: [1,3,5,6], 5, Output: 2
思路:用Binary Tree的方法两边向中间寻找求解。
代码:
class Solution:
def searchInsert(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: int
"""
if len(nums) == 0:
return 0
left, right = 0, len(nums) - 1
while left <= right:
mid = (left + right) // 2
if nums[mid] > target:
right = mid - 1
elif nums[mid] < target:
left = mid + 1
else:
return mid
return left
28. Implement strStr()
Return the index of the first occurrence of needle in haystack, or -1 if needle is not part of haystack.
Example: Input: haystack = "hello", needle = "ll", Output: 2
Example: Input: haystack = "aaaaa", needle = "bba", Output: -1
思路一: 扫描haystack,当遇到与needle首字符相同的位置时,检查haystack从该位置开始的与needle长度相同的块,与needle是否相同
class Solution(object):
def strStr(self, haystack, needle):
"""
:type haystack: str
:type needle: str
:rtype: int
"""
for i in range(len(haystack) - len(needle)+1):
if haystack[i:i+len(needle)] == needle:
return i
return -1
思路二:按照题目提示,用双指针实现。
def strStr(haystack, needle):
size1 = len(haystack)
size2 = len(needle)
if size2 == 0:
return 0
i = 0
while i < size1:
if size1 - i < size2:
return -1
if haystack[i] == needle[0]:
j = 1
while j < size2:
if haystack[i+1] != needle[j]:
break
j += 1
if j == size2:
return i
i += 1
return -1
-----2018/3/4-----
这周末在家宴请了LD的几个同事,一起为其中一个怀孕的女生办了个babyshower,然后过了个元宵节。这年也算是过完了。周末就在家准备饭,带娃,打扫卫生了。好容易今晚有点时间,躺下了还要起来刷一题,这样才可以安心去睡。
27. Remove Element
Given an array and a value, remove all instances of that value
Do not allocate extra space for another array, you must do this by modifying the input array
The order of elements can be changed. It doesn't matter what you leave beyond the new length.
Example:
Given nums = [3,2,2,3], val = 3,
Your function should return length = 2, with the first two elements of nums being 2.
思路:有i,j两个下标变量,如果nums[j] != val,那么nums[i] = nums[j],i,j各+ 1。
代码:
class Solution(object):
def removeElement(self, nums, val):
j = 0
i = 0
while i < len(nums):
if nums[i] != val:
nums[j] = nums[i]
j += 1
i += 1
else:
i += 1
return j
26. Remove Duplicates from Sorted Array
Given a sorted array, remove the duplicates in place such that each element appear only once and return the new length.
Do not allocate extra space for another array, you must do this in place with constant memory.
For example,
Given input array A = [1,1,2],
Your function should return length = 2, and A is now [1,2].
解题思路:使用一个指针j,当i向后遍历数组时,如果遇到与A[j]不同的,将A[i]和A[j+1]交换,同时j=j+1,即j向后移动一个位置,然后i继续向后遍历。
代码:
def removeduplicates(nums):
if len(nums) == 0:
return 0
newlst = []
j = 0
newlst.append(nums[j])
for i in range(len(nums)):
if nums[i] != nums[j]:
nums[j+1] = nums[i]
j = j + 1
newlst.append(nums[j])
return j+1,newlst
print (removeduplicates([1,1,2,3,4,5,5,6,6]))
参考了别人的解题思路,自己加了几行代码来返回新的list。
-----2018/3/2----
21. Merger two sorted lists (**)
Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists.
Example:
Input: 1->2->4, 1->3->4
Output: 1->1->2->3->4->4
这个其实算是一个归并排序:
归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
代码:
# Definition for singly-linked list.
class ListNode(object):
def __init__(self, x):
self.val = x
class Solution(object):
def mergeTwoLists(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
if l1 == None:
return l2
if l2 == None:
return l1
ret = ListNode(0)
head = ret
while l1 != None and l2 != None:
if l1.val > l2.val:
else:
if l1 == None:
if l2 == None:
--------2018/3/1----------
214. Valid Parentheses
Given a string containing just the characters '(', ')', '{', '}', '[' and ']', determine if the input string is valid.
The brackets must close in the correct order, "()" and "()[]{}" are all valid but "(]" and "([)]" are not.Valid Parenthesesleetcode.com
思路:用栈来操作,将所有的字符依次入栈,当栈顶的括号和正要入栈的括号匹配时将栈顶的括号弹出且不入栈,否则入栈新的括号。最后,只有当栈里没有括号时,才表明输入是有效的。
代码:
class Solution(object):
def isValid(self, s):
"""
:type s: str
:rtype: bool
"""
pars = [None] #size of pars is 1 here
parmap = {')':'(','}':'{',']':'['}
for x in s:
# if x in parmap checks if x in the dictionary's key
if x in parmap and parmap[x] == pars[len(pars)-1]:
pars.pop() # by default pop the last item of the list
else:
pars.append(x)
return len(pars) == 1 #check if there is anything left
14. Longest Common Prefix
Write a function to find the longest common prefix string among an array of strings.
思路:、
Longest Common Prefix从任意一个字符串开始,扫描该字符串,依次检查其他字符串的同一位置是否是一样的字符,当遇到不一样时则返回当前得到的前缀。
class Solution(object):
def longestCommonPrefix(self, strs):
if len(strs) == 0:
return ""
result = ""
for i in range(len(strs[0])):
for j in range(1,len(strs)):
if i >= len(strs[j]) or strs[0][i] != strs[j][i]:
return result
result += strs[0][i]
return result
-----2018/02/28-------
13. Roman to Integer [easy]
Given a roman numeral, convert it to an integer.
Input is guaranteed to be within the range from 1 to 3999.Roman to Integerleetcode.com
罗马数字采用七个罗马字母作数字:
I(1)、X(10)、C(100)、M(1000)、V(5)、L(50)、D(500)。
记数的方法:
1. 相同的数字连写,所表示的数等于这些数字相加得到的数,如 III=3;
2. 小的数字在大的数字的右边,所表示的数等于这些数字相加得到的数,如 VIII=8、XIII=12;
3. 小的数字(限于 I、X 和 C)在大的数字的左边,所表示的数等于大数减小数得到的数,如 IV=4、IX=9;
4. 在一个数的上面画一条横线,表示这个数增值 1,000 倍。
基本规则就是:在一个罗马数字中,大数一般是在高位,小数在低位,只有当小数为1,10,100并与后面的数字作减法的时候,才可以小数在大数前面。如:
MCMLIV = 1000 + (1000-100) + 50 + (5-1)
所以一种思路是:在字符串中检测右边比自己小的位置,将该位置的数加上负号,最后直接求和。(由于根据规则左减最多只有一位,所以只比较相邻两位即可)。另一种思路为,从高到低依次取数,如果下一个比现在大,就减去现在的数,否则就加上,最后一个肯定是加。这里我用后一种思路写代码。
代码:
class Solution:
def romanToInt(self, s):
romandict = {'I':1, 'V':5, 'X':10, 'L':50, 'C':100, 'D':500, 'M':1000}
introman = 0
#since we are search for s[i+1] will over flow, so we only end to len(s)-1 below. so we need to add romandict[s[len(s)-1]]
for i in range(len(s)-1):
if (romandict[s[i]] < romandict[s[i+1]]):
introman -= romandict[s[i]]
else:
introman += romandict[s[i]]
return introman + romandict[s[len(s)-1]]
9. Palindrome Number [easy]
Determine whether an integer is a palindrome. Do this without extra space.
Some hints:Could negative integers be palindromes? (ie, -1)
If you are thinking of converting the integer to string, note the restriction of using extra space.
You could also try reversing an integer. However, if you have solved the problem "Reverse Integer", you know that the reversed integer might overflow. How would you handle such case?
There is a more generic way of solving this problem.
思路:负数不是对称的,所以负数都不是Palindrom。 假如是正数,先找到一个div来判断数的位数,
代码:
class Solution:
def isPalindrome(self, x):
if x < 0:
return False
div = 1
## finding the number of digits for x
while x/div >= 10:
div = div * 10
## compare the left digit with the right digit
while x > 0:
left = int(x / div) ## get the very left digit
right = x % 10 ##get the very right digit
if left != right:
return False
x = int(( x % div ) / 10) ##cut off the left digit and right digit
div = div / 100 ## adjust the div.
return True
7. Reverse Integer [easy]
Reverse digits of an integer.
Example1: x = 123, return 321
Example2: x = -123, return -321
思路: 利用Python的字符串反转操作来实现对整数的反转,反转后的字符串要重新转换为整数。同上面一样,要注意正负和溢出情况。
class Solution:
def reverse(self,x):
if x > 0:
y = int(str(x)[::-1])
else:
y = (-1) * int(str(abs(x))[::-1])
if y > 2147483647 or y < - 2147483648:
y = 0
return y
--- 2018/02/27------------------------
1. Two Sum
Given an array of integers, return indices of the two numbers such that they add up to a specific target.
You may assume that each input would have exactly one solution, and you may not use the same element twice.
Example:
Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].
思路1:直接两重循环,暴力求解。效率很低。
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
for i in xrange(len(nums) - 1):
for j in xrange(i + 1, len(nums)):
if nums[i] + nums[j] == target:
return [i,j]
思路2:由于题目说了有且只有唯一解,可以考虑两遍扫描求解:第一遍扫描原数组,将所有的数重新存放到一个dict中,该dict以原数组中的值为键,原数组中的下标为值;第二遍扫描原数组,对于每个数nums[i]查看target-nums[i]是否在dict中,若在则可得到结果。
当然,上面两遍扫描是不必要的,一遍即可,详见代码。
class Solution(object):
def twoSum(self, nums, target):
"""
:type nums: List[int]
:type target: int
:rtype: List[int]
"""
dict = {}
for i in range(len(nums)):
if target - nums[i] in dict:
return [dict[target-nums[i]],i]
if nums[i] not in dict:
dict[nums[i]] = i
"""
test [3,2,4], target = 6
"""
167. Two Sum II - Input array is sorted [easy]
思路解析:
定义两个指针,一个从数组头开始遍历,一个从数组尾开始遍历,两者之和与target比较,如果和小于target,那么头指针加1,如果和大于target,那么尾指针减1.
class Solution(object):
def twoSum(self, numbers, target):
"""
:type numbers: List[int]
:type target: int
:rtype: List[int]
"""
# newlist = numbers.sort()
""""""
start = 0
end = len(numbers) - 1
while start != end:
sum = numbers[start] + numbers[end]
if sum > target:
end -= 1
elif sum < target:
start += 1
else:
return (start + 1, end + 1)