目录
1、找出数组中重复的数字
给定一个长度为 n 的整数数组 nums
,数组中所有的数字都在 0∼n−10∼n−1 的范围内。
数组中某些数字是重复的,但不知道有几个数字重复了,也不知道每个数字重复了几次。
请找出数组中任意一个重复的数字。
注意:如果某些数字不在 0∼n−10∼n−1 的范围内,或数组中不包含重复数字,则返回 -1;
样例
给定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。
返回 2 或 3。
class Solution(object):
def duplicateInArray(self, nums):
"""
:type nums: List[int]
:rtype int
"""
hash={}
for num in nums:
if num<0 or num>len(nums)-1:
return -1
for num in nums:
if num in hash:
return num
else:
hash[num]=1
return -1
直接哈希存储,因为并不知道其中有几个数字重复,并且重复了几次,所以选择这样的方式行统计,当数已经在字典中时,直接返回即可。
还有另一种排序基于物理排序,但是python里会超时,感觉C++是可以AC的
while(nums[i]!=nums[nums[i]]) swap(nums[i],nums[nums[i]]),
最后判断 if nums[i]!=i return nums[i],基本思路就是用萝卜去占坑、
2、不修改数组找出重复的数字
给定一个长度为 n+1n+1 的数组nums
,数组中所有的数均在 1∼n1∼n 的范围内,其中 n≥1n≥1。
请找出数组中任意一个重复的数,但不能修改输入的数组。
样例
给定 nums = [2, 3, 5, 4, 3, 2, 6, 7]。
返回 2 或 3。
思考题:如果只能使用 O(1)的额外空间,该怎么做呢
class Solution(object):
def duplicateInArray(self, nums):
"""
:type nums: List[int]
:rtype int
"""
l=1;r=len(nums)-1
#数的范围在1---n,长度为n-1,所以要len-1
while(l<r):
mid=(l+r)//2
s=0
for num in nums:
if num>=l and num<=mid:
s+=1
#遍历所有数中,在【l,mid】范围内的数有多少进行累加,判断个数和区间长度即可更新区间
if s> mid-l+1:
r=mid
else:
l=mid+1
return r
'''
要注意这里的区间是在题意中的1-n的范围内寻找,和下标并没有卵关系
'''
看到题目用二分,但是怎么分要深刻理解题意,因为有n+1个坑,数都在1-n中,所以一分为二,看看所有数中在【1,n/2】的个数,如果大于区间个数,就更新区间,踩过的坑其中是大于等于左右端点值,是在这个区间,判断的时候是严格大于区间长度
反应的是抽屉原理,n+1个苹果放进n个坑中,去找坑的问题,时间复杂度0(nlogn)
3、二维数组中的查找
在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。
请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
样例
输入数组:
[
[1,2,8,9],
[2,4,9,12],
[4,7,10,13],
[6,8,11,15]
]
如果输入查找数值为7,则返回true,
如果输入查找数值为5,则返回false。
class Solution(object):
def searchArray(self, array, target):
"""
:type array: List[List[int]]
:type target: int
:rtype: bool
"""
if len(array)==0:
return False
row=len(array)-1
col=len(array[0])-1
j=col
i=0
while i<=row and j>=0:
if array[i][j]>target:
j-=1
elif array[i][j]<target:
i+=1
else :
return True
return False
基本思路就是从右上角从右往左找,从上往下找,和target进行比较,要么j-1往左走,要么i+1往下走,注意题解中可能row和col变量名标反了哦、
4、替换空格
请实现一个函数,把字符串中的每个空格替换成"%20"
。
你可以假定输入字符串的长度最大是1000。
注意输出字符串的长度可能大于1000。
样例
输入:"We are happy."
输出:"We%20are%20happy."
class Solution(object):
def replaceSpaces(self, s):
"""
:type s: str
:rtype: str
"""
res=''
for i in s:
if i==' ':
res+='%20'
else:
res+=i
return res
这个应该比较简单,不用思考,首先利用res存储结果,遍历s数组,如果其中是空格,则加%20,否则将对应元素加进数组中去
5、 从尾到头打印链表
输入一个链表的头结点,按照 从尾到头 的顺序返回节点的值。
返回的结果用数组存储。
样例
输入:[2, 3, 5]
返回:[5, 3, 2]
class Solution(object):
def printListReversingly(self, head):
"""
:type head: ListNode
:rtype: List[int]
"""
if not head:
return []
res=[]
stk=[]
p=head
while p:
stk.append(p.val)
p=p.next #要注意让指针移动起来
#for i in range(len(stk)-1,-1,-1):
# res.append(stk[i])
while len(stk)>0:
res.append(stk.pop())
return res
#从尾到头打印,则利用栈的想法,利用list实现,从前往后遍历链表,将值压入堆栈,最后pop()出来即可
6、在O(1)时间删除链表结点
给定单向链表的一个节点指针,定义一个函数在O(1)时间删除该结点。
假设链表一定存在,并且该节点一定不是尾节点。
样例
输入:链表 1->4->6->8
删掉节点:第2个节点即6(头节点为第0个节点)
输出:新链表 1->4->8
class Solution(object):
def deleteNode(self, node):
"""
:type node: ListNode
:rtype: void
"""
p = node.next
node.val = p.val
node.next = p.next
#o(1)时间内,直接将后一个节点的值复制过来即可,然后指向下一个节点
7、 删除链表中重复的节点
在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留。
样例1
输入:1->2->3->3->4->4->5
输出:1->2->5
class Solution(object):
def deleteDuplication(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
dummy = ListNode(-1)
dummy.next = head
p=dummy
while(p.next):
q=p.next
while q and p.next.val == q.val:
q=q.next
if p.next.next == q:
p=p.next
else:
p.next = q
return dummy.next
'''
删除链表中重复节点,这个可以多说说,就是首先建立虚拟节点,将head保存起来,
而后比较时候,每一次令q指向p的下一个节点,当p.next.val == q.val时,q往
后移,其实是将p.next也就是初始时刻的q作为比较对象,一直往后移动,而后p.next
的更新就要看q位置了
因此核心就是两步,以p.next为基准,让q一直移动,第二步更新p,game over
'''
8、链表中倒数第k个节点
输入一个链表,输出该链表中倒数第k个结点。
注意:
k >= 0
;- 如果k大于链表长度,则返回 NULL;
样例
输入:链表:1->2->3->4->5 ,k=2
输出:4
class Solution(object):
def findKthToTail(self, head, k):
"""
:type pListHead: ListNode
:type k: int
:rtype: ListNode
"""
p=head;n=1
if not head:
return None
while p.next:
p=p.next
n+=1
if k>n:
return None
p=head
for i in range(n-k):
p=p.next
return p
9、链表中环的入口结点
给定一个链表,若其中包含环,则输出环的入口节点。
若其中不包含环,则输出null
。
样例
给定如上所示的链表:
[1, 2, 3, 4, 5, 6]
2
注意,这里的2表示编号是2的节点,节点编号从0开始。所以编号是2的节点就是val等于3的节点。
则输出环的入口节点3.
class Solution(object):
def entryNodeOfLoop(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
fast=head;slow=head
while fast :
slow=slow.next
fast=fast.next
if fast.next:
fast=fast.next
else:
return None
if fast == slow:
break
slow=head
while fast!=slow:
fast=fast.next
slow=slow.next
return slow
10、反转链表
定义一个函数,输入一个链表的头结点,反转该链表并输出反转后链表的头结点。
思考题:
- 请同时实现迭代版本和递归版本。
样例
输入:1->2->3->4->5->NULL
输出:5->4->3->2->1->NULL
class Solution:
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
pre=None
cur = head
while cur:
s=cur.next
cur.next = pre
pre=cur
cur=s
return pre
递归实现:
class Solution:
def reverseList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if not head:
return []
if not head.next:
return head
last = self.reverseList(head.next)
head.next.next=head
head.next = None
return last
'''
#翻转链表的递归版本
1、 递归函数要有 base case, 也就是这句:
if (head.next == null) return head;
意思是如果链表只有⼀个节点的时候反转也是它⾃⼰, 直接返回即可。
2、 当链表递归反转之后, 新的头结点是 last , ⽽之前的 head 变成了最
后⼀个节点, 别忘了链表的末尾要指向 null:
head.next = null;
'''
(一)
(二)
(三)
(四)
(五)
扩展:
反转从位置 m 到 n 的链表。请使用一趟扫描完成反转。
说明:
1 ≤ m ≤ n ≤ 链表长度。
示例:
输入: 1->2->3->4->5->NULL, m = 2, n = 4
输出: 1->4->3->2->5->NULL
class Solution:
def reverseBetween(self, head: ListNode, m: int, n: int) -> ListNode:
def reverseN(head,n):
if n == 1:return head
last = reverseN(head.next,n-1)
successor = head.next.next
head.next.next = head
head.next = successor
return last
if m == 1:return reverseN(head,n)
head.next = self.reverseBetween(head.next,m-1,n-1)
return head
11、合并两个排序的链表
输入两个递增排序的链表,合并这两个链表并使新链表中的结点仍然是按照递增排序的。
样例
输入:1->3->5 , 2->4->5
输出:1->2->3->4->5->5
class Solution(object):
def merge(self, l1, l2):
"""
:type l1: ListNode
:type l2: ListNode
:rtype: ListNode
"""
dummy = ListNode(-1)
cur = dummy
while l1 and l2:
if l1.val<=l2.val:
cur.next=l1
l1=l1.next
else:
cur.next =l2
l2=l2.next
cur=cur.next
cur.next=l1 if l1 is not None else l2
return dummy.next
10、复杂链表的复刻
请实现一个函数可以复制一个复杂链表。
在复杂链表中,每个结点除了有一个指针指向下一个结点外,还有一个额外的指针指向链表中的任意结点或者null。
注意:
- 函数结束后原链表要与输入时保持一致
class Solution(object):
def copyRandomList(self, head):
"""
:type head: ListNode
:rtype: ListNode
"""
if head ==None:
return None
p=head
while p :
np = ListNode(p.val)
s=p.next
p.next=np
np.next=s
p=s
p=head
while p :
if p.random:
p.random.next=p.next.random
p=p.next.next
dummy=ListNode(-1)
cur=dummy
p=head
while p :
pre=p
cur.next=p.next
cur=cur.next
p=p.next.next
pre.next=p
return dummy.next