10月份
01题TWO SUM(10.6)
- python暴力法
报错运行时间超时,时间复杂度O(n^2),空间复杂度O(1)
l = len(nums)
for i in range(l):
if nums[i] > target :
continue
if i == l-1 :
return 'error'
for j in range(i+1,l):
if nums[i]+nums[j] == target :
return [i,j]
- python一遍哈希表,时间O(n),空间O(n)
def twoSum(nums, target):
d = {}
for i, n in enumerate(nums):
if n in d:
return [d[n], i]
else:
d[target-n]=i
return (0,0)
因为没有查找value的方法,所以创建一个value-key 的dict,其中的d[target-num[i]] = i,在创建哈希表的同时就可以查找,找到键对应值的就为第一个数的位置
- Java 一遍哈希表
Map接口
boolean containsKey(Object k)
如果此映射包含指定键的映射关系,则返回 true
Object get(Object k)
返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
class Solution {
public int[] twoSum(int[] nums, int target) {
Map<Integer,Integer> map = new HashMap<>();
for(int i = 0;i<nums.length;i++){
int b = target - nums[i];
if(map.containsKey(b)){
return new int[] {map.get(b),i};
}
map.put(nums[i],i);
}
throw new IllegalArgumentException("No two sum solution");
}
}
Python 中self 用法
主要是用于类中定义函数方便调用
02题Add Two Numbers(10.9)
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.Example:
Input: (2 -> 4 -> 3) + (5 -> 6 -> 4) Output: 7 -> 0 -> 8 Explanation:
342 + 465 = 807.
这道题学习到了链表的操作,Java和python中利用引用,定义类来实现链表等数据结构的操作
- python麻烦的
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
#进位
cur = 0
item = z = ListNode(0)
a = l1.val + l2.val
cur = a//10
item.next = ListNode(a%10)
item =item.next
#巧妙的对z进行操作实现链表,下一个对应一个链
while l1.next and l2.next:
l1 = l1.next
l2 = l2.next
a = l1.val + l2.val
b = a%10 + cur
item.next = ListNode(b%10)
cur = a//10+b//10
item = item.next
if l1.next == None and l2.next == None :
if cur>0:
item.next = ListNode(cur)
return z.next
elif l1.next == None:
while l2.next:
l2 = l2.next
a = l2.val
b = a + cur
item.next = ListNode(b%10)
cur = b//10
item = item.next
if cur>0:
item.next = ListNode(cur)
return z.next
elif l2.next == None:
while l1.next:
l1 = l1.next
a = l1.val
b = a + cur
item.next = ListNode(b%10)
cur = b//10
item = item.next
if cur>0:
item.next = ListNode(cur)
return z.next
- python别人的
class Solution:
def addTwoNumbers(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
temp = z = ListNode(0)
cur = 0
while l1 or l2 or cur:
if l1:
cur +=l1.val
l1 = l1.next
if l2:
cur +=l2.val
l2 = l2.next
temp.next = ListNode(cur%10)
temp = temp.next
cur //=10
return z.next
- Java的
public ListNode addTwoNumbers(ListNode l1, ListNode l2) {
ListNode z = new ListNode(0);
ListNode p = l1,q = l2,temp = z;
int cur = 0;
while(p!=null || q!=null) {
int x = (p!=null)? p.val:0;
int y = (q!=null)? q.val:0;
int sum = x+y+cur;
cur = sum/10;
temp.next = new ListNode(sum%10);
temp = temp.next;
if(p!=null) {
p = p.next;
}
if(q!=null) {
q = q.next;
}
}
if(cur>0) {
temp.next = new ListNode(cur);
}
return z.next;
}
- Python定义类的几种方法总结:
1__init__(),用于初始化一个类
03题(10.10)Longest Substring Without Repeating Characters
- python暴力(超时)
对于每一个函数的任务要明确,算法思想要少漏洞
def lengthOfLongestSubstring(s):
"""
:type s: str
:rtype: int
"""
max = 0
for i in range(len(s)):
for j in range(i+1,len(s)+1):
if isSubstring(s,i,j):
length = j-i
if(length>max):
max = length
return max
def isSubstring(s,i,j):
for m in range(i,j):
if s[m] in s[m+1:j]:
return False
return True
- python滑动窗口
def lengthOfLongestSubstring(self, s):
"""
:type s: str
:rtype: int
"""
a = ''
j =0
max = 0
n = len(s)
while(j<n):
if(s[j] not in a):
a = a+s[j]
j = j+1
if(max<len(a)):
max = len(a)
else:
a = a[1::]
return max
- python优化的滑动窗口
a = {}
j = 0
ans = 0
for i in range(len(s)):
if(s[i] in a):
j = max(a[s[i]],j)
a[s[i]] = i+1
ans = max(ans,i-j+1)
return ans
04题Median of Two Sorted Arrays(10.13)
m个 num1 i处分开
n个 num2 j处分开
1、i + j =m-i +n - j(或:m-i+n-j+1) n>m j = (m+n+1)/2
2、A[i-1]<=b[j] b[j-1]<=A[i]
二叉树搜索:
imin=0,imax= m,i = (imin+imax)/2
def findMedianSortedArrays(self, A, B):
"""
:type nums1: List[int]
:type nums2: List[int]
:rtype: float
"""
m = len(A)
n = len(B)
if m>n:
A,B,m,n = B,A,n,m
if n == 0:
return error
imin = 0
imax = m
x = (m+n+1)//2
while(imin<=imax):
i = (imin+imax)//2
j = x-i
if i<m and B[j-1]>A[i] :
imin = i+1
elif i>0 and A[i-1]>B[j]:
imax = i-1
else:
if i == 0: maxleft = B[j-1]
elif j == 0: maxleft =A[i-1]
else : maxleft = max(A[i-1],B[j-1])
if(m+n)%2 == 1:
return maxleft
if i == m: minright = B[j]
elif j == n: minright = A[i]
else: minright = min(A[i],B[j])
return (maxleft+minright)/2.0
05题Longest Palindromic Substring
- 中心扩展算法:从回文的中心开始找,对所有字符遍历,中心有两种可能:单个字符,以及挨着的相等字符 时间O(n2)
def longestPalindrome(self, s):
"""
:type s: str
:rtype: str
"""
n = len(s)
start,end = 0,0
for i in range(n):
len1 = self.palindromic(s,i,i)
len2 = self.palindromic(s,i,i+1)
L = max(len1,len2)
if(L>end-start):
start = i - (L-1)//2
end = i + L//2
return s[start:end+1]
def palindromic(self,s,i,j):
L,R = i,j
while(L>=0 and R<len(s) and s[L] == s[R]):
L -= 1
R += 1
return R-L-1
- Manacher 算法
时间复杂度O(N)的专门解决回文的算法
- 算法分析
由于回文分为奇偶回文,处理比较麻烦,在每个字符前后都加上一个符号,从而变成奇数
s =‘abcd’ 变为 s = '#a#b#c#d'
回文具有对称性质,pal(i)以i为中心的最大回文半径
图中为以id为中心的回文,mx是回文的边界,我们想要得到以i为中心的最大回文半径,可以通过对j(i关于id的对称点)求解得到 ------j = 2*id - i
if(i<mx)
p[i] = min(p[2*id-i],mx-i)
若 p[2*id-i] == mx-i
i还可以再往两边增加
以上通过P[j],可以快速得到对称的回文数,减少时间复杂度
- 马拉车代码
class Solution:
def longestPalindrome(self,s):
ss = '' #装入加了#号的新字符串
for i in s:
ss = ss+'#'
ss = ss+i
ss = ss+'#'
p = [0]*2001 #表示以i为中心的最长回文字符串半径
start,end,maxlen,mx = 0,0,0,0 #mx是以id为中心的回文最右边,start end最长的开始和结束
for i in range(len(ss)):
if(i<mx):
p[i] = min(p[2*id-i],mx-i) #如果在id回文的边界之内,则可以借鉴对称位置的值
else:
p[i] = 1
while((i - p[i])>=0 and i+p[i]<len(ss) and ss[i-p[i]] == ss[i+p[i]]): #在已知基础上看还有没有其他值
p[i] += 1
if(mx<i+p[i]): #更新id和mx
id = i
mx = i+p[i]
if(maxlen<(p[i]-1)): #如果最大长度替换原来的
maxlen = p[i]-1
start = i+1-p[i]
end = i+p[i]-1
return ss[start:end+1].replace('#','')
10、Container With Most Water(10.19)
暴力法python o(n2)超时
m = 0
long = len(height)
for i in range(long-1):
for j in range(i+1,long):
high = min(height[i],height[j])
s = (j-i)*high
if(m<s): m = s
return m
由两边向中心
def maxArea(self, height):
end = len(height)-1
start = 0
max = 0
while(start<end):
s = (end-start)*min(height[start],height[end])
if(max<s): max = s
if(height[start]<height[end]):
start += 1
else:
end -=1
return max
15.3SUM(10.20)
思路:简单的暴力法肯定会超时
换思路,先排序(通过排序解决重复问题),选出一个数后取反-c,如果遇到相等的直接跳过,然后从右边剩下的里面找a,b,从两边向中间找,a如果相等直接跳过,直到
a+b = -c
def threeSum(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
l,ans = len(nums),[]
nums.sort()
for i in range(l-2):
if i > 0 and nums[i] == nums[i-1]:
continue
c = nums[i]*-1
a = i+1
b = l-1
while a<b :
if nums[a]+nums[b] == c:
ans.append([nums[i],nums[a],nums[b]])
a += 1
while a<b and nums[a] == nums[a-1]:
a += 1
elif nums[a] + nums[b] < c :
a += 1
else:
b -= 1
return ans
17.Letter Combinations of a Phone Number(10.21-11.8)
思路:通过输入的数字,得到要输出的key值——num,循环遍历num,将对应的value相加
两个数组相加最简单,多个数组很难操作
通过新建一个空数组的方式,循环进行两数组相加
- python
n = len(digits)
phone = {2:'abc',3:'def',4:'ghi',5:'jkl',6:'mno',7:'pqrs',8:'tuv',9:'wxyz'}
res = ['']
if n == 0:
return []
for i in digits:
num = phone[int(i)]
newres = []
for a in num:
for b in res:
newres.append(b+a)
res = newres
return res
- java一样思路的解法
(其中java直接赋值是将地址给了)
public List<String> letterCombinations(String digits) {
List<String> ans = new ArrayList<String>();
List<String> newans = new ArrayList<String>();
String[] mapping = new String[] {"0", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
if(digits.isEmpty()) return ans ;
ans.add("");
for(int i=0;i<digits.length();i++) {
int x = Character.getNumericValue(digits.charAt(i));
newans.clear();
for(char s : mapping[x].toCharArray())
{
for(String t: ans) {
newans.add(t+s);
}
}
ans.clear();
ans.addAll(newans);
}
return ans;
}
- java另一个思路
remove(),直接去掉第一个元素并取出,一直循环直到所有的元素都加上了新的
public static List<String> letterCombinations(String digits) {
LinkedList<String> ans = new LinkedList<String>();
String[] mapping = new String[] {"0", "1", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
if(digits.isEmpty()) return ans ;
ans.add("");
for(int i=0;i<digits.length();i++) {
int x = Character.getNumericValue(digits.charAt(i));
while(ans.peek().length()==i){
String t = ans.remove();
for(char s : mapping[x].toCharArray())
ans.add(t+s);
}
}
return ans;
}