配合Online Judge刷题,体验更佳!剑指offer_编程题_牛客网
1. 二维数组中的查找
题目描述
在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数
# -*- coding:utf-8 -*-
class Solution:
# array 二维列表
def Find(self, target, array):
# write code here
i = len(array) - 1
j = 0
while i >= 0 and j < len(array[0]):
if target == array[i][j]:
return True
elif target > array[i][j]:
j += 1
else:
i -= 1
return False
思路
将这个矩阵理解为一块切斜的平面,左低右高,上低下高。巧妙的将查找起点设置在左下角(或者右上角),这样保证查找方向唯一。
2. 替换空格
题目描述
请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are
Happy.则经过替换之后的字符串为We%20Are%20Happy。
# -*- coding:utf-8 -*-
class Solution:
# s 源字符串
def replaceSpace(self, s):
# write code here
new_s = ''
for i in s:
if i != ' ':
new_s += i
else:
new_s += '%20'
return new_s
思路
使用python 字符串连接的语法,实现得简单了。也可以先计算新字符串的长度,然后通过下标索引填充字符。
3. 从尾到头打印链表
题目描述
输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回从尾部到头部的列表值序列,例如[1,2,3]
def printListFromTailToHead(self, listNode):
# write code here
stack = []
while listNode:
stack.append(listNode.val)
listNode = listNode.next
resultArray = []
while stack:
resultArray.append(stack.pop())
return resultArray
思路
使用了两个列表,第一个列表顺序装入链表节点,第二个列表翻转第一个列表。
4. 重建二叉树
题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回构造的TreeNode根节点
def reConstructBinaryTree(self, pre, tin):
if not pre:
return None
for index in range(len(tin)):
if tin[index] == pre[0]:
break
left_tin = tin[:index]
right_tin = tin[index+1:]
left_pre = pre[1:index + 1]
right_pre = pre[index + 1:]
rootNode = TreeNode(pre[0])
rootNode.left = self.reConstructBinaryTree(left_pre, left_tin)
rootNode.right = self.reConstructBinaryTree(right_pre, right_tin)
return rootNode
思路
利用如下规则,递归地切分左右子树的前序和中序遍历列表。
1、前序遍历的第一个数字是根节点;
2、中序遍历,根节点左边的数字属于左子树,,右边的数字属于右子树。
3、前序和中序遍历,左子树的数字在右子树的前面。
5. 用两个栈实现队列
题目描述
用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.stack1 = []
self.stack2 = []
def push(self, node):
# write code here
self.stack1.append(node)
def pop(self):
# return xx
if not self.stack2:
while self.stack1:
self.stack2.append(self.stack1.pop(-1))
return self.stack2.pop(-1)
思路
只在stack2为空时,才把stack1的元素一次性倒入stack2。
6. 旋转数组的最小数字
题目描述
把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。 输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。
例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
# -*- coding:utf-8 -*-
class Solution:
def minNumberInRotateArray(self, rotateArray):
# write code here
tmp = 0
for i in rotateArray:
if i < tmp:
return i
else:
tmp = i
return 0
思路
比较相邻元素,查找。
7. 斐波那契数列
题目描述
大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0)。 n<=39
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.fibonacci_dict = {}
def Fibonacci(self, n):
# write code here
if self.fibonacci_dict.has_key(n):
return self.fibonacci_dict[n]
if n == 0:
return 0
elif n == 1:
return 1
else:
value = self.Fibonacci(n-1) + self.Fibonacci(n-2)
self.fibonacci_dict[n] = value
return value
思路
递归。因为运行超时,这里加了个键值对缓存。
8. 跳台阶
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。
# -*- coding:utf-8 -*-
class Solution:
def jumpFloor(self, number):
# write code here
j1 = 1
j2 = 2
if number == 1:
return j1
elif number == 2:
return j2
for _ in range(number-2):
j2, j1 = j1+j2, j2
return j2
思路
跟斐波那契数列一样。
9. 变态跳台阶
题目描述
一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。
# -*- coding:utf-8 -*-
class Solution:
def jumpFloorII(self, number):
# write code here
if number == 1:
return 1
elif number ==2:
return 2
n_list = [1,2]
for _ in range(number-2):
n_list.append(sum(n_list)+1)
return n_list[-1]
思路
规律是n 级台阶的跳法是1、2、…、n-1 级台阶跳法的和,再加上1.
10. 矩形覆盖
题目描述
我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
# -*- coding:utf-8 -*-
class Solution:
def rectCover(self, number):
# write code here
f1 = 1
f2 = 2
if number == 1:
return f1
elif number == 2:
return f2
elif number ==0:
return 0
for _ in range(number-2):
f2, f1 = f1+f2, f2
return f2
思路
跟跳台阶一样,本质上都是斐波那契数列。
11. 二进制中1的个数
题目描述
输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
# -*- coding:utf-8 -*-
class Solution:
def NumberOf1(self, n):
# write code here
count = 0
if n < 0:
n = 2**31+n
count +=1
while n != 0:
count += (n%2)
n = n//2
return count
思路
负数的补码,其实是2**31 减去负数绝对值之后的正数的二进制码,最高位是1以标记为负数。
12. 数值的整数次方
题目描述
给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。
保证base和exponent不同时为0
# -*- coding:utf-8 -*-
class Solution:
def Power(self, base, exponent):
# write code here
if exponent < 0:
tmp_exp = -exponent
else:
tmp_exp = exponent
result = 1
if tmp_exp == 1:
result = base
tmp_base = base
while tmp_exp > 1:
if tmp_exp%2 == 1:
result *= tmp_base
result *= tmp_base**2
tmp_exp = tmp_exp //2
tmp_base = base**2
if exponent < 0:
result = 1.0/result
return result
思路
找到循环的模式,例如
n
11
=
n
2
∗
5
∗
n
=
(
n
2
)
2
∗
2
∗
n
2
∗
n
.
n^{11}= n^{2*5}*n={(n^{2})}^{2*2}*n^{2}*n.
n11=n2∗5∗n=(n2)2∗2∗n2∗n.
13. 调整数组顺序使奇数位于偶数前面
题目描述
输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
# -*- coding:utf-8 -*-
class Solution:
def reOrderArray(self, array):
# write code here
result_array = array[:]
length = len(array)
for i in range(length):
for j in range(length-1-i):
if result_array[j]%2 ==0 and result_array[j+1]%2 ==1:
tmp = result_array[j]
result_array[j] = result_array[j+1]
result_array[j+1] = tmp
return result_array
思路
借用了冒泡排序,只不过是元素交换条件换成了:相邻两个元素,左边偶数右边奇数。冒泡排序是稳定性排序,相等的元素相对位置不变(这里的相等的含义是两个奇数是相等的,或者两个偶数是相等的)。
14. 链表中倒数第k个结点
题目描述
输入一个链表,输出该链表中倒数第k个结点。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
def FindKthToTail(self, head, k):
# write code here
if not head:
return None
node = head
node_list = []
while node:
node_list.append(node)
node = node.next
if k > len(node_list) or k < 1:
return None
else:
return node_list[-k]
思路
遍历链表,然后把节点按顺序放在列表里,返回倒数第k个元素。
15. 反转链表
题目描述
输入一个链表,反转链表后,输出新链表的表头。
# -*- coding:utf-8 -*-
# class ListNode:
# def __init__(self, x):
# self.val = x
# self.next = None
class Solution:
# 返回ListNode
def ReverseList(self, pHead):
# write code here
if not pHead:
return None
p1 = pHead
p = pHead.next
p1.next = None
while p:
p2 = p.next
p.next = p1
p1 = p
p = p2
return p1
思路
设置3个相邻元素的指针,遍历链表,挨个的改变节点的next。
16. 合并两个排序的链表
题目描述
输入两个单调递增的链表,输出两个链表合成后的链表,当然我们需要合成后的链表满足单调不减规则。
# -*- 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
pHead = p = ListNode(0)
while pHead1 or pHead2:
if not pHead1:
p.next = pHead2
break
if not pHead2:
p.next = pHead1
break
if pHead2.val > pHead1.val:
p.next = pHead1
pHead1 = pHead1.next
else:
p.next = pHead2
pHead2 = pHead2.next
p = p.next
return pHead.next
思路
创建一个新链表,遍历两个链表,按大小放入新链表。
17. 树的子结构
题目描述
输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
def isSame(self, pRoot1, pRoot2):
if pRoot1 is None and pRoot2 is not None:
return False
if pRoot2 is None:
return True
if pRoot1.val != pRoot2.val:
return False
return self.isSame(pRoot1.left, pRoot2.left) and self.isSame(pRoot1.right, pRoot2.right)
def HasSubtree(self, pRoot1, pRoot2):
# write code here
if pRoot1 is None or pRoot2 is None:
return False
if self.isSame(pRoot1, pRoot2):
return True
return self.HasSubtree(pRoot1.left, pRoot2) or self.HasSubtree(pRoot1.right, pRoot2)
思路
两个递归函数。一个用来比较树结构是否 一样;一个用来查找子结构的根节点在树中的位置。
18. 二叉树的镜像
题目描述
操作给定的二叉树,将其变换为源二叉树的镜像。
# -*- coding:utf-8 -*-
# class TreeNode:
# def __init__(self, x):
# self.val = x
# self.left = None
# self.right = None
class Solution:
# 返回镜像树的根节点
def swap(self, root):
if root is not None:
tmpNode = root.left
root.left = root.right
root.right = tmpNode
self.swap(root.left)
self.swap(root.right)
def Mirror(self, root):
# write code here
self.swap(root)
return root
思路
递归的交换左右子节点。
19. 顺时针打印矩阵
题目描述
输入一个矩阵,按照从外向里以顺时针的顺序依次打印出每一个数字,例如,如果输入如下4 X 4矩阵: 1 2 3 4 5 6 7 8 9 10
11 12 13 14 15 16 则依次打印出数字1,2,3,4,8,12,16,15,14,13,9,5,6,7,11,10.
# -*- coding:utf-8 -*-
class Solution:
# matrix类型为二维列表,需要返回列表
def printMatrix(self, matrix):
# write code here
# 0 - right
# 1 - down
# 2 - left
# 3 - up
rows = len(matrix)
cols = len(matrix[0])
direct = 0
i = j = 0
result = []
for _ in range(rows*cols):
result.append(matrix[i][j])
matrix[i][j] = None
if direct == 0:
if j+1 == cols or matrix[i][j+1] is None:
direct = 1
i+=1
else:
j+=1
elif direct == 1:
if i+1 == rows or matrix[i+1][j] is None:
direct = 2
j-=1
else:
i+=1
elif direct == 2:
if j == 0 or matrix[i][j-1] is None:
direct = 3
i-=1
else:
j-=1
elif direct == 3:
if i == 0 or matrix[i-1][j] is None:
direct = 0
j+=1
else:
i-=1
return result
思路
试探边界并改变方向;遍历过的元素标记为None。
20. 包含min函数的栈
题目描述
定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1))。
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.stack = []
self.min_stack = []
def push(self, node):
# write code here
self.stack.append(node)
if not self.min_stack or node < self.min_stack[-1]:
self.min_stack.append(node)
else:
min_item = self.min_stack[-1]
self.min_stack.append(min_item)
def pop(self):
# write code here
self.min_stack.pop(-1)
return self.stack.pop(-1)
def top(self):
# write code here
return self.stack[-1]
def min(self):
# write code here
return self.min_stack[-1]
思路
设置一个栈,记录每次压入之后的最小值。
21. 栈的压入、弹出序列
题目描述
输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序,序列4,5,3,2,1是该压栈序列对应的一个弹出序列,但4,3,5,1,2就不可能是该压栈序列的弹出序列。(注意:这两个序列的长度是相等的)
# -*- coding:utf-8 -*-
class Solution:
def IsPopOrder(self, pushV, popV):
# write code here
stack = []
j = 0
for i in pushV:
stack.append(i)
while stack[-1] == popV[j]:
stack.pop(-1)
j+=1
if stack == []:
break
if stack == []:
return True
else:
return False
思路
模拟压入弹出过程,如果栈最终为空,则有效。
这个过程描述为,设置一个栈,遍历压入列表压入,如果栈顶是出栈结点,弹出值。
22. 数组中出现次数超过一半的数字
题目描述
数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。
# -*- coding:utf-8 -*-
class Solution:
def __init__(self):
self.num_count = {}
def MoreThanHalfNum_Solution(self, numbers):
# write code here
for i in numbers:
if i in self.num_count:
self.num_count[i] += 1
else:
self.num_count[i] = 1
if self.num_count[i] > len(numbers) // 2:
return i
return 0
思路
最直接的算法,创建一个字典,存放数字出现的次数
23. 数组中重复的数字
题目描述
在一个长度为n的数组里的所有数字都在0到n-1的范围内。 数组中某些数字是重复的,但不知道有几个数字是重复的。也不知道每个数字重复几次。请找出数组中任一一个重复的数字。 例如,如果输入长度为7的数组[2,3,1,0,2,5,3],那么对应的输出是2或者3。存在不合法的输入的话输出-1
#
# 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
#
#
# @param numbers int整型一维数组
# @return int整型
#
class Solution:
def duplicate(self , numbers ):
# write code here
counts = [0] * len(numbers)
for i in numbers:
counts[i] +=1
if counts[i] > 1:
return i
return -1
思路
创建一个新数组,存放下标数值本身在数组中出现的次数。