說明:自己思考以及和別人對比,參考對比程序來源
包含 2 - 11 題
002、單向鏈表兩數相加
You are given two non-empty linked lists representing two non-negative integers. The digits are stored in reverse order and each of their nodes contain a single digit. Add the two numbers and return it as a linked list.
You may assume the two numbers do not contain any leading zero, except the number 0 itself.
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4)
Output: 7 -> 0 -> 8
# Definition for singly-linked list.
# class ListNode(object):
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution(object):
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
current = ListNode(0)
p = current
value = 0
while l1 or l2:
if l1:
value = value + l1.val
l1 = l1.next
if l2:
value = value + l2.val
l2 = l2.next
# current.var = value % 10
var = value % 10
value = value / 10
current.next = ListNode(var)
current = current.next
if value:
# current.var = value
current.next = ListNode(value)
return p.next
if __name__ == '__main__':
a, a.next, a.next.next = ListNode(2), ListNode(4), ListNode(3)
b, b.next, b.next.next = ListNode(5), ListNode(6), ListNode(4)
result = Solution().addTwoNumbers(a, b)
print "%d -> %d -> %d " %(result.val , result.next.val , result.next.next.val)
這個題主要注意以下問題:要考慮兩個鏈表不同長度的相加;第一個頭結點不保留數據,返回p.next;
003、最大不重復的子串
Given "abcabcbb", the answer is "abc", which the length is 3.
Given "bbbbb", the answer is "b", with the length of 1.
Given "pwwkew", the answer is "wke", with the length of 3. Note that the answer must be a substring, "pwke" is a subsequence and not a substring.
以下是自己的答案,用了兩個for循環,還是復雜了點,最后一個測試超時
class Solution(object):
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
length_max = 0
for i in range(0,len(s)):
mystr , length = self.search(s[i:])
if length > length_max:
length_max = length
return length_max
def search(self,s):
i = 0
while s[i] not in s[0:i]:
i += 1
if i == len(s):
break
length = i
mystr = s[0:i]
#print mystr
return mystr,length
if __name__ == '__main__' :
s = Solution()
length_max1 = s.lengthOfLongestSubstring('abcdefgabc')
print length_max1
別人的答案 48.5%
class Solution:
# @return an integer
def lengthOfLongestSubstring(self, s):
longest, start, visited = 0, 0, [False for _ in xrange(256)]
for i, char in enumerate(s):
if visited[ord(char)]:
while char != s[start]:
visited[ord(s[start])] = False
start += 1
start += 1
else:
visited[ord(char)] = True
longest = max(longest, i - start + 1)
return longest
if __name__ == "__main__":
print Solution().lengthOfLongestSubstring("abcabcbb")
004、Median of Two Sorted Arrays
There are two sorted arrays nums1 and nums2 of size m and n respectively.
Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n))
class Solution(object):
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
result = []
i = 0
j = 0
median, flag = (len(nums1) + len(nums2))//2, (len(nums1) + len(nums2))%2
while i < len(nums1) and j < len(nums2):
if nums1[i] < nums2[j]:
result.append(nums1[i])
i += 1
else:
result.append(nums2[j])
j += 1
result += nums1[i:]
result += nums2[j:]
if flag == 1:
return (result[median] + result[median]) * 0.5
if flag == 0:
return (result[median - 1] + result[median]) * 0.5
if __name__ == '__main__':
print Solution().findMedianSortedArrays([1, 3, 5, 7], [2, 4, 6])
print Solution().findMedianSortedArrays([1, 2], [3,4])
這個題目反應出基礎功,由于快速過了一遍數據結構和算法,將兩個排好序的序列重新組合這么簡單的問題居然會無從下手,而又覺得特別熟悉,其實在歸并排序中就有出現,而這邊也是完全借用歸并排序的思想。其實上述有個明顯的缺點就是將整個數組排序了,實際上只需要排序到指定位置即可。
運行時間 108ms 超過了60%
class Solution(object):
def findMedianSortedArrays(self, nums1, nums2):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
len1, len2 = len(nums1), len(nums2)
if (len1 + len2) % 2 == 1:
return self.getKth(nums1, nums2, (len1 + len2)/2 + 1)
else:
return (self.getKth(nums1, nums2, (len1 + len2)/2) + \
self.getKth(nums1, nums2, (len1 + len2)/2 + 1)) * 0.5
def getKth(self, A, B, k):
m, n = len(A), len(B)
if m > n:
return self.getKth(B, A, k)
left, right = 0, m
while left < right:
mid = left + (right - left) / 2
if 0 <= k - 1 - mid < n and A[mid] >= B[k - 1 - mid]:
right = mid
else:
left = mid + 1
Ai_minus_1 = A[left - 1] if left - 1 >= 0 else float("-inf")
Bj = B[k - 1 - left] if k - 1 - left >= 0 else float("-inf")
return max(Ai_minus_1, Bj)
上述為別人的思路,運行時間95ms。
005 Longest Palindromic Substring 最大回文字符串
Input: "babad"
Output: "bab"
Note: "aba" is also a valid answer.
class Solution(object):
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
length = len(s)
maxlen, maxL, maxR = 0, 0, 0
for i in range(length):
start = i #考慮為偶數情況
end = i + 1
while start >= 0 and end <= length - 1:
if s[start] == s[end]:
if end - start + 1 > maxlen:
maxlen = end - start + 1
maxL = start
maxR = end
start -= 1
end += 1
else:
break
start = i - 1 #考慮為奇數情況
end = i + 1
while start >= 0 and end <= length - 1:
if s[start] == s[end]:
if end - start + 1 > maxlen:
maxlen = end - start + 1
maxL = start
maxR = end
start -= 1
end += 1
else:
break
return s[maxL:maxR+1]
if __name__ == '__main__':
solution = Solution()
print solution.longestPalindrome('abbacd')
上面的程序運行效率不是很高,只優于41%的提交。
是否能把所有的情況全部轉換為奇數處理?Manacher算法,且這個算法求最長回文子串的時間復雜度是線性O(N)的。參考
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
def preProcess(s):
if not s:
return ['^', '$']
T = ['^']
for c in s:
T += ['#', c]
T += ['#', '$']
return T
T = preProcess(s)
P = [0] * len(T)
center, right = 0, 0
for i in xrange(1, len(T) - 1):
i_mirror = 2 * center - i
if right > i:
P[i] = min(right - i, P[i_mirror])
else:
P[i] = 0
while T[i + 1 + P[i]] == T[i - 1 - P[i]]:
P[i] += 1
if i + P[i] > right:
center, right = i, i + P[i]
max_i = 0
for i in xrange(1, len(T) - 1):
if P[i] > P[max_i]:
max_i = i
start = (max_i - 1 - P[max_i]) / 2
return s[start : start + P[max_i]]
6、 ZigZag Conversion
class Solution(object):
def convert(self, s, numRows):
"""
:type s: str
:type numRows: int
:rtype: str
"""
if numRows == 1:
return s
str1 = ''
j, flag = 0, 0
T = ['' for i in range(numRows)]
for i in range(len(s)):
if flag == 0:
T[j] += s[i]
j += 1
if j == numRows:
flag = 1
j -= 2
else:
#p[i] = j
T[j] += s[i]
j -= 1
if j == -1:
flag = 0
j += 2
for i in range(numRows):
str1 += T[i]
return str1
if __name__ == '__main__':
solution = Solution()
print solution.convert('abc',2)
上述算法 思路主要是:0123432101234321。
運行結果出來一瞬間真是崩了,216ms,只勝于10%,可能原因一是算法確實沒別人好,二是字符串操作可能會帶來開銷。
class Solution(object):
def convert(self, s, numRows):
"""
:type s: str
:type numRows: int
:rtype: str
"""
if numRows == 1:
return s
step, zigzag = 2 * numRows - 2, ""
for i in xrange(numRows):
for j in xrange(i, len(s), step):
zigzag += s[j]
if 0 < i < numRows - 1 and j + step - 2 * i < len(s):
zigzag += s[j + step - 2 * i]
return zigzag
if __name__ == "__main__":
print Solution().convert("PAYPALISHIRING", 3)
該算法優于40%,還是不夠好
7、Reverse digits of an integer
Example1: x = 123, return 321
Example2: x = -123, return -321
這個問題需要注意的有兩個問題,一是可能是負數,二是考慮是否越界,假設為有符號32bit。
反轉一般有兩種常用解決方式,一是以整數方式,除10取余,二是利用字符串自帶的反轉功能,str1[::-1]。
class Solution(object):
def reverse(self, x): #該方法更優
"""
:type x: int
:rtype: int
"""
if x < 0:
return -self.reverse(-x)
result = 0
while x:
result = result * 10 + x % 10
x /= 10
return result if result <= 0x7fffffff else 0 # Handle overflow.
def reverse2(self, x):
"""
:type x: int
:rtype: int
"""
if x < 0:
x = int(str(x)[::-1][-1] + str(x)[::-1][:-1])
else:
x = int(str(x)[::-1])
x = 0 if abs(x) > 0x7FFFFFFF else x
return x
def reverse3(self, x):
"""
:type x: int
:rtype: int
"""
s = cmp(x, 0)
r = int(`s * x`[::-1])
return s * r * (r < 2 ** 31)
字符串反轉有以下兩種常用方法:
使用[::-1]:
s = 'python'
print s[::-1]使用reverse()方法:
l = list(s)
l.reverse() #不返回,但是原列表已經反轉
print ''.join(l)
8、String to Integer (atoi)
這個題確實有很多細節需要考慮,一開始做的時候只考慮了字符串中間有字母,以及首位可能為'-',發現還有可能首位為‘+’和一個或多個空格。該題還有一個特殊就是'12a'也能出結果12,就是是逐個判斷
class Solution(object):
def myAtoi(self, str):
"""
:type str: str
:rtype: int
"""
result, flag = 0, 1
if len(str) == 0:
return 0
if len(str) == 1 and str not in '0123456789':
return 0
if str[0] == ' ':
return self.myAtoi(str[1:])
for i in range(0,len(str)):
if i == 0 and str[i] not in '-+0123456789':
return 0
if i>0 and str[i] not in '0123456789':
return 0
for c in str:
if c == '-':
flag = -1
continue
if c == '+':
continue
num = ord(c) - ord('0')
result = result*10 + num
return result*flag
以上是初步代碼,還有很多需要改善,邏輯關系沒有劃分很清楚,沒有考慮到越界,遞歸調用看似簡便但開銷大,使用兩個循環,略顯臃腫。
class Solution(object):
def myAtoi(self, str):
"""
:type str: str
:rtype: int
"""
result, i, flag = 0, 0, 1
if len(str) == 0:
return 0
while str[i] == ' ':
i += 1
if str[i] == '-':
flag = -1
i += 1
elif str[i] == '+':
i += 1
while i<len(str) and str[i] >= '0' and str[i] <= '9':
result = result*10 + ord(str[i]) - ord('0')
i += 1
if result > 2147483647:
break
result *= flag
if result >= 2147483647:
return 2147483647
if result <= -2147483648:
return -2147483648
return result
if __name__ == '__main__':
solution = Solution()
print solution.myAtoi('1')
9. Palindrome Number
Determine whether an integer is a palindrome. Do this without extra space.
class Solution(object):
def isPalindrome(self, x):
"""
:type x: int
:rtype: bool
"""
if x < 0:
return False
l = len(str(x)) - 1
while l > 0:
if x % 10 != x // 10**l:
return False
x = x // 10
l -= 1
x = x % 10**l
l -= 1
return True
if __name__ == '__main__':
solution = Solution()
print solution.isPalindrome(12313214)
算比較簡單,第一次提交 81% ,第二次就 69% 第三次 21% 。也是很惶恐,本來開開心心。
趕緊找來別人的看看
class Solution:
# @return a boolean
def isPalindrome(self, x):
if x < 0:
return False
copy, reverse = x, 0
while copy:
reverse *= 10
reverse += copy % 10
copy /= 10
return x == reverse
if __name__ == "__main__":
print Solution().isPalindrome(12321)
print Solution().isPalindrome(12320)
print Solution().isPalindrome(-12321)
這個看起來更優化點,一測試 30%,已經不知道說啥。
10. Regular Expression Matching
Implement regular expression matching with support for '.' and '*'.
'.' Matches any single character.
'*' Matches zero or more of the preceding element.
http://www.cnblogs.com/zuoyuan/p/3781773.html
最后一個‘*’一定不要下意識認為是正則表達式中匹配0或任意個字符,這里是匹配前面出現的字符,可以是不匹配(及匹配0次也可以重復)
class Solution:
# @return a boolean
def isMatch(self, s, p):
if len(p)==0: return len(s)==0
if len(p)==1 or p[1]!='*':
if len(s)==0 or (s[0]!=p[0] and p[0]!='.'):
return False
return self.isMatch(s[1:],p[1:])
else:
i=-1; length=len(s)
while i<length and (i<0 or p[0]=='.' or p[0]==s[i]):
if self.isMatch(s[i+1:],p[2:]): return True
i+=1
return False
算法題理清思路很重要:
isMatch(s, p):
1. 當前p為0時,若s也是0時,則返回true,否則為false
2. 當前p不為0時,
1) p的下一個不是'*'時
if: 當前s與p匹配,
則表明到此都是匹配的,只需要檢查isMatch(s + 1, p + 1)
else:
返回false
2) p的下一個是'*'時,
while: 當前s與p匹配,即表明至此也是匹配的
if: 當前s與下一個p也都匹配,即isMatch(s, p + 2),則返回true
else: s++
此時,當前s與當前p已經不匹配了(之前s都是匹配的),則檢測下一個模板isMatch(s, p + 2)
上面是用遞歸方法,也有人說用動態規劃比較好,待思考。http://www.cnblogs.com/flowerkzj/p/3726667.html
11、Container With Most Water
給定n個數,a1,a2,...,an.在坐標上的位置為(i,ai),求其中兩個點到X軸的線段與x軸圍成的面積最大。
思路:
1、暴力法:用兩個for循環,超時了,看來還是得動腦子。
2、貪心法,從兩邊向中間夾逼,兩個指針指向列表兩端,當左邊高度<右邊時,制約在左邊,右邊往左移肯定找不到更大的,應該左邊往右移,反之也成立。
但注意到,每次都會比較一次,但是當右移或左移的數比原來小時,沒有必要進行計算,因為肯定會比原來結果小,如何優化代碼。
class Solution(object):
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""
length = len(height)
if length < 2:
return -1
left = 0
right = length - 1
max_contain = 0
while left < right:
max_contain = max(max_contain, min(height[left] , height[right]) * (right - left))
if height[left] < height[right]:
left += 1
else:
right -= 1
return max_contain
if __name__ == '__main__':
solution = Solution()
print solution.maxArea([1,3,56,57,8])
優化后,擊敗92%,欣慰。
class Solution(object):
def maxArea(self, height):
"""
:type height: List[int]
:rtype: int
"""
length = len(height)
if length < 2:
return -1
left = 0
right = length - 1
max_contain = 0
while left < right:
max_contain = max(max_contain, min(height[left] , height[right]) * (right - left))
if height[left] < height[right]:
j = left
left += 1
while height[left] <= height[j] and left < right: #若<原來的數,直接下一個,算都不用算
left += 1
else:
j = right
right -= 1
while height[right] <= height[j] and left < right:
right -= 1
return max_contain
if __name__ == '__main__':
solution = Solution()
print solution.maxArea([1,2])