给一个链表,若其中包含环,请找出该链表的环的入口结点,否则,输出null。
解法
参考:https://blog.csdn.net/wszll_Alex/article/details/86741909
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def EntryNodeOfLoop(self, pHead):
# write code here
if not pHead:
return None
fast = slow = pHead
while fast and fast.next:
slow = slow.next
fast = fast.next.next
if fast == slow:
fast = pHead
while fast != slow:
fast = fast.next
slow = slow.next
return fast
return None
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
注意:保证测试中不会当栈为空的时候,对栈调用pop()或者min()或者top()方法。
解法
其实就是提前存下一个min值,随时更新它就可以。
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.stack = []
self.mi = 100000
def push(self, node):
# write code here
self.stack.append(node)
if node < self.mi:
self.mi = node
def pop(self):
# write code here
t = self.stack[-1]
self.stack = self.stack[:-1]
if t == self.mi:
self.mi = 100000
for x in self.stack:
if x < self.mi:
self.mi = x
return t
def top(self):
# write code here
t = self.stack[-1]
return t
def min(self):
# write code here
return self.mi
请实现一个函数用来找出字符流中第一个只出现一次的字符。例如,当从字符流中只读出前两个字符"go"时,第一个只出现一次的字符是"g"。当从该字符流中读出前六个字符“google"时,第一个只出现一次的字符是"l"。
输出描述:
如果当前字符流没有存在出现一次的字符,返回#字符。
解法
想到了哈希,用一个列表存储所有进来的字符,随时判断每个字符是否重复,并且随时更新当前指向第一个不重复字符的指针。
但是后来看了解析,发现并不需要这么复杂,可以使用队列的思想,不需要保存下所有字符,只需要保存那些不重复的字符。
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.s = []
self.dic = {}
self.idx = -1
# 返回对应char
def FirstAppearingOnce(self):
# write code here
if self.idx == -1:
return "#"
return self.s[self.idx]
def Insert(self, char):
# write code here
self.s.append(char)
if char not in self.dic:
self.dic[char] = 1
if self.idx == -1:
self.idx = len(self.s) - 1
else:
self.dic[char] += 1
if self.idx != -1 and self.dic[self.s[self.idx]] > 1:
flag = 0
for i in range(self.idx + 1, len(self.s)):
if self.dic[self.s[i]] == 1:
self.idx = i
flag = 1
break
if flag == 0:
self.idx = -1
从上到下按层打印二叉树,同一层结点从左至右输出。每一层输出一行。
解法
二叉树的层次遍历用的就是BFS,为了确定当前是哪一行,所以需要在队列中再保存一个当前的层数。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回二维列表[[1,2],[4,5]]
def Print(self, pRoot):
# write code here
if not pRoot:
return []
res = [[]]
q = []
q.append((pRoot, 0))
while q:
cur, n = q.pop(0)
if n >= len(res):
res.append([])
res[n].append(cur.val)
if cur.left:
q.append((cur.left, n + 1))
if cur.right:
q.append((cur.right, n + 1))
return res
统计一个数字在排序数组中出现的次数。
解法
# -*- coding:utf-8 -*-
class Solution:
def GetNumberOfK(self, data, k):
# write code here
if not data:
return 0
l, r = 0, len(data) - 1
idx = -1
while l <= r:
mid = (l + r) // 2
if data[mid] == k:
idx = mid
break
elif data[mid] < k:
l = mid + 1
elif data[mid] > k :
r = mid - 1
if idx == -1:
return 0
res = 0
for i in range(idx, len(data)):
if data[i] == k:
res += 1
elif data[i] > k:
break
for i in range(idx - 1, -1, -1):
if data[i] == k:
res += 1
elif data[i] < k:
break
return res
# -*- coding:utf-8 -*-
class Solution:
def GetNumberOfK(self, data, k):
# write code here
if not data:
return 0
l, r = 0, len(data)
while l < r:
mid = (l + r) // 2
if data[mid] < k:
l = mid + 1
else:
r = mid
lower = l
l, r = 0, len(data)
while l < r:
mid = (l + r) // 2
if data[mid] <= k:
l = mid + 1
else:
r = mid
upper = l
return upper - lower
每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0…m-1报数…这样下去…直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!_)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1)
如果没有小朋友,请返回-1
解法
参考:https://www.nowcoder.com/questionTerminal/f78a359491e64a50bce2d89cff857eb6?answerType=1&f=discussion
模拟法
递归法:假设f(n, m) 表示最终留下元素的序号。
首先,长度为 n 的序列会先删除第 m % n 个元素,然后剩下一个长度为 n - 1 的序列。那么,我们可以递归地求解 f(n - 1, m),就可以知道对于剩下的 n - 1 个元素,最终会留下第几个元素,我们设答案为 x = f(n - 1, m)。
由于我们删除了第 m % n 个元素,将序列的长度变为 n - 1。当我们知道了 f(n - 1, m) 对应的答案 x 之后,我们也就可以知道,长度为 n 的序列最后一个删除的元素,应当是从 m % n 开始数的第 x 个元素。因此有 f(n, m) = (m % n + x) % n = (m + x) % n。
当n等于1时,f(1,m) = 0
迭代法:从递归法延伸过来的,因为递归会超时
# -*- coding:utf-8 -*-
class Solution:
def LastRemaining_Solution(self, n, m):
# write code here
if n < 1:
return -1
res = 0
for i in range(2, n + 1):
res = (res + m) % i
return res
一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。
解法
如何找到位置i?可用i = ret ^ (-ret)
因为计算机用补码存取二进制数,而负数的补码为反码+1,举个例子
假如ret = 1110 , -ret = 0010 , 所以 i = 0010
所以,再异或一遍即可得到答案。
# -*- coding:utf-8 -*-
class Solution:
# 返回[a,b] 其中ab是出现一次的两个数字
def FindNumsAppearOnce(self, array):
# write code here
tmp = 0
for x in array:
tmp ^= x
res = tmp & (-tmp)
num1, num2 = 0, 0
for x in array:
if x & res:
num1 ^= x
else:
num2 ^= x
return [num1, num2]
给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
解法
参考:https://www.nowcoder.com/questionTerminal/9023a0c988684a53960365b889ceaf5e?answerType=1&f=discussion
# -*- coding:utf-8 -*-
# class TreeLinkNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
# self.next = None
class Solution:
def GetNext(self, pNode):
# write code here
if not pNode:
return None
cur = pNode
if cur.right:
cur = cur.right
while cur.left:
cur = cur.left
return cur
while cur.next:
tmp = cur.next
if tmp.left == cur:
return tmp
cur = cur.next
return None
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
解法
链接:https://www.nowcoder.com/questionTerminal/d77d11405cc7470d82554cb392585106?answerType=1&f=discussion
来源:牛客网
直接模拟即可。因为弹出之前的值都会先入栈,所以这里用个栈来辅助。
# -*- coding:utf-8 -*-
class Solution:
def IsPopOrder(self, pushV, popV):
# write code here
l, r = 0, 0
stack = []
while pushV:
tmp = pushV.pop(0)
if tmp != popV[0]:
stack.append(tmp)
else:
popV.pop(0)
if not popV:
return True
while stack[-1] == popV[0]:
stack.pop(-1)
popV.pop(0)
if not popV:
return True
return False
输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。
输出描述:
对应每个测试案例,输出两个数,小的先输出。
解法
开始自己一直陷在递增排序所以用二分法的解法中,然后又不希望遍历,就想找规律,什么样的两个数乘积最小,后来发现无解,于是看了题解。
# -*- coding:utf-8 -*-
class Solution:
def FindNumbersWithSum(self, array, tsum):
# write code here
l, r = 0, len(array) - 1
mul = 100000
res = []
while l < r:
if array[l] + array[r] == tsum:
if array[l] * array[r] < mul:
res = [array[l], array[r]]
mul = array[l] * array[r]
l += 1
r -= 1
elif array[l] + array[r] > tsum:
r -= 1
else:
l += 1
return res
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任意一个重复的数字。 例如,如果输入长度为7的数组{2,3,1,0,2,5,3},那么对应的输出是第一个重复的数字2。
解法
# -*- coding:utf-8 -*-
class Solution:
# 这里要特别注意~找到任意重复的一个值并赋值到duplication[0]
# 函数返回True/False
def duplicate(self, numbers, duplication):
# write code here
for i in range(len(numbers)):
while i != numbers[i]:
if numbers[i] == numbers[numbers[i]]:
duplication[0] = numbers[i]
return True
else:
tmp = numbers[i]
numbers[i] = numbers[numbers[i]]
numbers[tmp] = tmp
#numbers[i], numbers[numbers[i]] = numbers[numbers[i]], numbers[i]
return False
输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。
解法
参考:https://www.nowcoder.com/questionTerminal/947f6eb80d944a84850b0538bf0ec3a5?answerType=1&f=discussion
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def __init__(self):
self.pre = None
def Convert(self, pRootOfTree):
# write code here
if pRootOfTree == None:
return None
self.Convert(pRootOfTree.right)
if self.pre != None:
pRootOfTree.right = self.pre
self.pre.left = pRootOfTree
self.pre = pRootOfTree
self.Convert(pRootOfTree.left)
return self.pre
在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)
解法
本来以为会有优雅点的解法,但发现就是直接哈希。第一遍哈希得到字符次数,第二遍找到第一个位置
# -*- coding:utf-8 -*-
class Solution:
def FirstNotRepeatingChar(self, s):
# write code here
dic = {}
for x in s:
if x not in dic:
dic[x] = 0
dic[x] += 1
for i in range(len(s)):
if dic[s[i]] == 1:
return i
return -1
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
解法
注意:记得最后要判断一下最后得到的数字是否真的是众数。这几种方法的时间复杂度都是O(n)。
# -*- coding:utf-8 -*-
class Solution:
def MoreThanHalfNum_Solution(self, numbers):
# write code here
cnt, tmp = 1, numbers[0]
for x in numbers[1:]:
if x == tmp:
cnt += 1
else:
cnt -= 1
if cnt == 0:
cnt = 1
tmp = x
cnt = 0
for x in numbers:
if x == tmp:
cnt += 1
if cnt > len(numbers)/2:
return tmp
return 0
输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。
解法
def PrintMinNumber(self, numbers):
# write code here
n = len(numbers)
for i in range(n):
for j in range(i+1, n):
if int(str(numbers[i]) + str(numbers[j]) > str(numbers[j]) + str(numbers[i])):
numbers[j], numbers[i] = numbers[i], numbers[j]
return ''.join([str(i) for i in numbers])
# -*- coding:utf-8 -*-
class Solution:
def PrintMinNumber(self, numbers):
# write code here
lmb = lambda a, b: int(str(a) + str(b)) - int(str(b) + str(a))
numbers = sorted(numbers, cmp=lmb)
res = "".join(str(x) for x in numbers)
return res
小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!
输出描述:
输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序
解法
参考:https://www.nowcoder.com/questionTerminal/c451a3fd84b64cb19485dad758a55ebe?answerType=1&f=discussion
# -*- coding:utf-8 -*-
class Solution:
def FindContinuousSequence(self, tsum):
# write code here
l, r = 1, 1
tmp = 0
res = []
while l <= tsum/2:
if tmp < tsum:
tmp += r
r += 1
elif tmp > tsum:
tmp -= l
l += 1
else:
ans = [x for x in range(l, r)]
res.append(ans)
tmp -= l
l += 1
return res
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
解法
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回合并后列表
def Merge(self, pHead1, pHead2):
# write code here
head = ListNode(-1)
cur = head
while pHead1 and pHead2:
if pHead1.val < pHead2.val:
cur.next = pHead1
pHead1 = pHead1.next
else:
cur.next = pHead2
pHead2 = pHead2.next
cur = cur.next
if pHead1:
cur.next = pHead1
if pHead2:
cur.next = pHead2
return head.next
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回合并后列表
def Merge(self, pHead1, pHead2):
# write code here
if not pHead1:
return pHead2
if not pHead2:
return pHead1
if pHead1.val <= pHead2.val:
pHead1.next = self.Merge(pHead1.next, pHead2)
return pHead1
else:
pHead2.next = self.Merge(pHead1, pHead2.next)
return pHead2
从上往下打印出二叉树的每个节点,同层节点从左至右打印。
解法
不需要记录深度的层次遍历
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回从上到下每个节点值列表,例:[1,2,3]
def PrintFromTopToBottom(self, root):
# write code here
if not root:
return []
q = [root]
res = []
while q:
cur = q.pop(0)
res.append(cur.val)
if cur.left:
q.append(cur.left)
if cur.right:
q.append(cur.right)
return res
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
解法
参考https://www.nowcoder.com/questionTerminal/beb5aa231adc45b2a5dcc5b62c93f593?answerType=1&f=discussion
# -*- coding:utf-8 -*-
class Solution:
def reOrderArray(self, array):
# write code here
i = 0
for j in range(len(array)):
if array[j] % 2 == 1:
tmp = array[j]
for k in range(j - 1, i - 1, -1):
array[k + 1] = array[k]
array[i] = tmp
i += 1
return array
输入一颗二叉树的根节点和一个整数,按字典序打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。
解法
显然是使用递归的方法。注意要判断叶子节点。关键是在递归上面加上两个全局变量存储结果。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回二维列表,内部每个列表表示找到的路径
def __init__(self):
self.path = []
self.res = []
def dfs(self, root, expectNumber):
self.path.append(root.val)
if root.val == expectNumber and not root.left and not root.right:
self.res.append(self.path)
if root.left:
self.dfs(root.left, expectNumber - root.val)
if root.right:
self.dfs(root.right, expectNumber - root.val)
self.path = self.path[:-1]
def FindPath(self, root, expectNumber):
# write code here
if not root:
return self.path
self.dfs(root, expectNumber)
return self.res
LL今天心情特别好,因为他去买了一副扑克牌,发现里面居然有2个大王,2个小王(一副牌原本是54张_)…他随机从中抽出了5张牌,想测测自己的手气,看看能不能抽到顺子,如果抽到的话,他决定去买体育彩票,嘿嘿!!“红心A,黑桃3,小王,大王,方片5”,“Oh My God!”不是顺子…LL不高兴了,他想了想,决定大\小 王可以看成任何数字,并且A看作1,J为11,Q为12,K为13。上面的5张牌就可以变成“1,2,3,4,5”(大小王分别看作2和4),“So Lucky!”。LL决定去买体育彩票啦。 现在,要求你使用这幅牌模拟上面的过程,然后告诉我们LL的运气如何, 如果牌能组成顺子就输出true,否则就输出false。为了方便起见,你可以认为大小王是0。
题解
参考: https://www.nowcoder.com/questionTerminal/762836f4d43d43ca9deb273b3de8e1f4?answerType=1&f=discussion
这个题也不难,本来想的是用一堆判断来做,但是发现有更简单的思路。
分两种情况考虑,
所以根据如上两个条件,算法过程如下:
# -*- coding:utf-8 -*-
class Solution:
def IsContinuous(self, numbers):
# write code here
if not numbers:
return False
mi, ma = 14, 0
res = set()
for x in numbers:
if x in res:
return False
if x != 0 and x not in res:
res.add(x)
if x < mi:
mi = x
if x > ma:
ma = x
if ma - mi < 5:
return True
return False
给定一个数组和滑动窗口的大小,找出所有滑动窗口里数值的最大值。例如,如果输入数组{2,3,4,2,6,2,5,1}及滑动窗口的大小3,那么一共存在6个滑动窗口,他们的最大值分别为{4,4,6,6,6,5}; 针对数组{2,3,4,2,6,2,5,1}的滑动窗口有以下6个: {[2,3,4],2,6,2,5,1}, {2,[3,4,2],6,2,5,1}, {2,3,[4,2,6],2,5,1}, {2,3,4,[2,6,2],5,1}, {2,3,4,2,[6,2,5],1}, {2,3,4,2,6,[2,5,1]}。
解法
之前做过这个题
# -*- coding:utf-8 -*-
class Solution:
def maxInWindows(self, num, size):
# write code here
if not num or size < 1 or len(num) < size:
return []
res = []
q = []
for i, x in enumerate(num):
while q and num[q[-1]] < x:
q.pop()
q.append(i)
if q[0] <= i - size:
q.pop(0)
if i >= size - 1:
res.append(num[q[0]])
return res
给定一棵二叉搜索树,请找出其中的第k小的结点。例如, (5,3,7,2,4,6,8) 中,按结点数值大小顺序第三小结点的值为4。
解法
思路比较简单,因为二叉搜索树的性质,中序遍历就可以得到从小到大的顺序,只需要在到达第k个值的时候停下就可以。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回对应节点TreeNode
def __init__(self):
self.cnt = 0
self.res = None
def dfs(self, pRoot, k):
if not pRoot:
return
self.KthNode(pRoot.left, k)
self.cnt += 1
if self.cnt == k:
self.res = pRoot
return
if self.cnt > k:
return
self.KthNode(pRoot.right, k)
def KthNode(self, pRoot, k):
# write code here
self.dfs(pRoot, k)
return self.res