文章目录
1. 数组查找
题目描述: 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。
class Solution:
# array 二维列表
def Find(self, target, array):
# write code here
for i in range(len(array)):
if target in array[i]:
return True
return False
if __name__ == '__main__':
s = Solution()
array = [[2,3,4],[3,4,5]]
print(s.Find(5,array))
2. 替换空格
题目描述: 请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy,则经过替换之后的字符串为We%20Are%20Happy。
实现方法: 先扫描一遍字符串,得出空格的个数,将新字符串的长度限制为原字符串的长度+2*空格个数,从尾到头转移原字符串,并将其中的空格替换为%20
class Solution:
def replaceSpace(self, s):
num_space = 0
new_s = []
for char in s:
if char == ' ':
num_space += 1
new_s.append(char)
new_s = new_s + ['='] * 2 * num_space
s_i = len(s) - 1
new_s_i = len(new_s) - 1
while s_i >= 0 and s_i < new_s_i:
if s[s_i] == ' ':
new_s[new_s_i-2 : new_s_i+1] = ['%', '2', '0']
new_s_i -= 3
else:
new_s[new_s_i] = s[s_i]
new_s_i -=1
s_i -= 1
new_s = ''.join(new_s)
return new_s
if __name__ == '__main__':
s = ' wdad ed '
solt = Solution()
print(solt.replaceSpace(s))
3. 从尾到头打印链表
题目描述: 输入一个链表,按链表从尾到头的顺序返回一个ArrayList。
实现方法: 1、递归实现 2、栈实现
# 从尾至头打印链表
class ListNode:
def __init__(self, v):
self.val = v
self.next = None
def create(self, p, v):
while p.next != None:
p = p.next
p.next = ListNode(v)
# 递归实现
class recurSolution:
def printListFromTailToHead(self, listNode):
res = []
def printListnode(listNode):
if listNode:
printListnode(listNode.next) # 先递归到最后一层
res.append(listNode.val) # 添加值,退出函数,返回到上一层函数中的这行,继续添加值
printListnode(listNode)
return res
# 栈实现
class stackSolution:
def printListFromTailToHead(self, listNode):
chain = []
res = []
p = listNode
while p != None:
chain.append(p.val)
p = p.next
while len(chain) != 0:
res.append(chain.pop())
return res
if __name__ == '__main__':
recur_s = recurSolution()
stack_s = stackSolution()
head = ListNode(1)
head.create(head, 2)
head.create(head, 3)
print(recur_s.printListFromTailToHead(head))
print(stack_s.printListFromTailToHead(head))
4. 根据先序和中序遍历重建二叉树
题目描述: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
实现方法: 先根据先序序列寻找根的位置,再去中序序列中找根的位置,确定完两个序列的根的位置后,将两个序列中的值各自分为3类,左子树下的所有节点、根、右子树下的所有节点,再分别将左子树、右子树内的值按上述方法递归分类。递归结束条件:子树部分只有一个节点,即子树为叶子节点。
# 给定前序和中序遍历,重建二叉树
class treeNode:
def __init__(self, x):
self.val = x
self.left = None
self.right = None
class Solution:
# 返回构造的TreeNode根节点
def reConstructBinaryTree(self, pre, tin):
def ConstructCore(startPre, endPre, startIn, endIn):
rootVal = pre[startPre]
root = treeNode(rootVal)
if startPre == endPre:
if startIn == endIn and pre[startPre] == tin[startIn]:
return root
else:
print('Invalid input.')
# 在中序遍历中找到根节点
rootIn = startIn
while rootIn < endIn and tin[rootIn] != rootVal:
rootIn += 1
if rootIn == endIn and tin[rootIn] != rootVal:
print('Invalid input.')
leftLength = rootIn - startIn
leftPreEnd = startPre + leftLength
if leftLength > 0: # 若左子树不为空,构建左子树
root.left = ConstructCore(startPre+1, leftPreEnd, startIn, rootIn-1)
if leftLength < endIn - startIn: # 若右子树不为空,则构建右子树
root.right = ConstructCore(leftPreEnd+1, endPre, rootIn+1, endIn)
return root
assert len(pre) == len(tin)
if pre == None or tin == None or len(pre) == 0:
return None
else:
return ConstructCore(0, len(pre)-1, 0, len(tin)-1)
if __name__ == '__main__':
s = Solution()
pre = [1,2,3,4,5,6,7]
tin = [3,2,4,1,6,5,7]
print(s.reConstructBinaryTree(pre, tin).val)
5. 二叉树的下一个节点
题目描述: 给定一个二叉树和其中的一个结点,请找出中序遍历顺序的下一个结点并且返回。注意,树中的结点不仅包含左右子结点,同时包含指向父结点的指针。
实现方法: 分为4种情况:1、树只有一个节点或None节点,直接返回None. 2、给定节点有右子树,那么下一个节点为其右子树的最左叶子。3、给定节点无右子树,且为其父节点的左孩子,直接返回其父节点。4、给定节点无右子树,且为其父节点的右孩子,需要一直找其父节点,直到找到某个节点为其父节点的左孩子,或找到了根结点(父节点为None),则返回该父节点。
class TreeLinkNode:
def __init__(self, val):
self.val = val
self.left = None
self.right = None
self.next = None
class Solution():
def GetNext(self, node):
p_next = None
if node.right != None:
p = node.right
while p.left != None:
p = p.left
p_next = p
elif node.next != None:
p_c = node
p_parent = node.next
while p_parent != None and p_c == p_parent.right:
p_c = p_parent
p_parent = p_parent.next
p_next = p_parent
return p_next
6. 用两个栈实现队列
题目描述: 用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。
实现方法: push时,直接将新元素入栈进stack1。pop时,若stack2为空则将stack1的所有元素依次入栈stack2,并出栈stack2的栈顶元素,若转移后stack2仍为空,则说明队列为空,无法出队;若stack2不为空,只需出栈stack2中的栈顶元素即可。
# 利用两个栈实现队列
class Solution:
def __init__(self):
self.stack1 = []
self.stack2 = []
def push(self, node):
self.stack1.append(node)
def pop(self):
if len(self.stack2) == 0:
while len(self.stack1) > 0:
self.stack2.append(self.stack1.pop())
if len(self.stack2) == 0:
print('queue is empty!')
else:
return self.stack2.pop()
if __name__ == '__main__':
s = Solution()
s.push(1)
s.push(2)
s.push(3)
s.pop()
s.pop()
s.pop()
相关题目: 利用两个队列实现入栈出栈函数。
from queue import Queue
class Solution2:
def __init__(self):
self.q1 = Queue(maxsize=0)
self.q2 = Queue(maxsize=0)
def push(self, node):
if not self.q1.empty():
self.q1.put(node)
elif not self.q2.empty():
self.q2.put(node)
else:
self.q1.put(node)
def pop(self):
if not self.q1.empty():
while self.q1.qsize() > 1:
self.q2.put(self.q1.get())
return self.q1.get()
elif not self.q2.empty():
while self.q2.qsize() > 1:
self.q1.put(self.q2.get())
return self.q2.get()
else:
print('stack empty')
7. 斐波那契数列
题目描述: 现在要求输入一个整数n,请你输出斐波那契数列的第n项
实现方法: 循环 or 递归。
# 斐波那契数列
class Solution:
def Fibonacci_1(self, n): # 循环实现
fnm1 = 1
fnm2 = 0
if n == 0:
return fnm2
elif n == 1:
return fnm1
else:
for i in range(2, n+1):
f = fnm1 + fnm2
fnm2 = fnm1
fnm1 = f
return f
def Fibonacci_2(self, N): # 递归实现,超时
def FibonacciRe(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return FibonacciRe(n-1) + FibonacciRe(n-2)
return FibonacciRe(N)
if __name__ == '__main__':
s = Solution()
print(s.Fibonacci_1(39))
8. 青蛙跳台阶
题目描述: 青蛙跳台阶,若一共有n级台阶,一次可以跳1级台阶,或一次可以跳2级台阶。
实现方法:
f
(
n
)
=
f
(
n
−
1
)
+
f
(
n
−
2
)
f(n)=f(n-1)+f(n-2)
f(n)=f(n−1)+f(n−2)
9. 变态跳台阶
题目描述: 若青蛙一次可以跳1级or一次可以跳2级,or……or一次可以跳n级。
实现方法:
f
(
n
)
=
2
n
−
1
f(n)=2^{n-1}
f(n)=2n−1
10. 矩阵覆盖
题目描述: 我们可以用21的小矩形横着或者竖着去覆盖更大的矩形。请问用n个21的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法?
实现方法:
f
(
n
)
=
f
(
n
−
1
)
+
f
(
n
−
2
)
f(n)=f(n-1)+f(n-2)
f(n)=f(n−1)+f(n−2)
8、10均为斐波那契数列思想
11. 旋转数组
题目描述: 把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。
实现方法: 二分法,目标是找到两个递增数组的边界。使用双指针,index1指向首元素,index2指向尾元素,找中间位置的元素值,若大于index1的元素,则目标一定在indexMid之后;若小于index2的元素,则目标一定在indexMid之前,若index1和index2和indexMid位置的值都相等,则只能顺序查找。
public class Main11 {
public int minNumberInRotateArray(int [] array) {
int p1 = 0;
int p2 = array.length-1;
int mid = 0;
while (array[p1] >= array[p2]) {
mid = (p2+p1) / 2;
if (array[p1] == array[mid] && array[mid] == array[p2]) {
return inOrder(array);
}
if (array[p1] <= array[mid]) {
p1 = mid;
}
else if (array[p2] >= array[mid]) {
p2 = mid;
}
if (p2-p1 == 1) {
mid = p2;
break;
}
}
return array[mid];
}
public int inOrder(int[] array) {
int min = array[0];
for (int i = 1; i < array.length ; i++) {
if (array[i] < min){
min = array[i];
}
}
return min;
}
public static void main(String[] args) {
Main11 m = new Main11();
int[] array = {10,1,10,10,10};
System.out.println(m.minNumberInRotateArray(array));
}
}
12. 矩阵中的路径
题目描述: 请设计一个函数,用来判断在一个矩阵中是否存在一条包含某字符串所有字符的路径。路径可以从矩阵中的任意一个格子开始,每一步可以在矩阵中向左,向右,向上,向下移动一个格子。如果一条路径经过了矩阵中的某一个格子,则该路径不能再进入该格子。 例如
[
a
b
c
e
s
f
c
s
a
d
e
e
]
\left[ \begin{matrix} a & b & c & e \\ s & f & c & s \\ a & d & e & e \end{matrix} \right]
⎣⎡asabfdcceese⎦⎤
矩阵中包含一条字符串"bcced"的路径,但是矩阵中不包含"abcb"路径,因为字符串的第一个字符b占据了矩阵中的第一行第二个格子之后,路径不能再次进入该格子。
实现方法: 递归回溯法,需要额外的访问数组visited,重点在20行代码
public class Main12 {
public boolean hasPath(char[] matrix, int rows, int cols, char[] str) {
int[] visited = new int [rows * cols];
int pathLen = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if(hasPathCore(matrix, rows, cols, i, j, visited, pathLen, str)) {
return true;
}
}
}
return false;
}
public boolean hasPathCore(char[] matrix, int rows, int cols, int row, int col, int[] visited, int pathLen, char[] str) {
if (pathLen == str.length) {
return true;
}
boolean hasC = false;
if (row>=0 && row<rows && col>=0 && col<cols && visited[row * cols + col]==0 && matrix[row * cols + col]==str[pathLen]) {
visited[row * cols + col] = 1;
pathLen++;
hasC = hasPathCore(matrix, rows, cols, row-1, col, visited, pathLen, str) ||
hasPathCore(matrix, rows, cols, row+1, col, visited, pathLen, str) ||
hasPathCore(matrix, rows, cols, row, col-1, visited, pathLen, str) ||
hasPathCore(matrix, rows, cols, row, col+1, visited, pathLen, str);
if (!hasC) {
visited[row * cols + col] = 0;
pathLen--;
}
}
return hasC;
}
public static void main(String[] args) {
Main12 m = new Main12();
char[] matrix = {'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A', 'A'};
char[] str = {'A','A','A','A','A','A','A','A','A','A','A','A'};
System.out.println(m.hasPath(matrix, 3, 4, str));
}
}
13. 机器人的运动范围
题目描述: 地上有一个m行和n列的方格。一个机器人从坐标0,0的格子开始移动,每一次只能向左,右,上,下四个方向移动一格,但是不能进入行坐标和列坐标的数位之和大于k的格子。 例如,当k为18时,机器人能够进入方格(35,37),因为3+5+3+7 = 18。但是,它不能进入方格(35,38),因为3+5+3+8 = 19。请问该机器人能够达到多少个格子?
实现方法: 递归回溯法,重点在13行代码
public class Main13 {
public int movingCount(int threshold, int rows, int cols) {
int[][] visited = new int[rows][cols];
return countCore(threshold, rows, cols, 0, 0, visited);
}
public int countCore(int threshold, int rows, int cols, int row, int col, int[][] visited) {
int count = 0;
if (row>=0 && row<rows && col>=0 && col<cols && visited[row][col]==0 && weiSum(row,col)<=threshold) {
visited[row][col] = 1;
count = 1 + countCore(threshold, rows, cols, row-1, col, visited)
+ countCore(threshold, rows, cols, row+1, col, visited)
+ countCore(threshold, rows, cols, row, col-1, visited)
+ countCore(threshold, rows, cols, row, col+1, visited);
}
return count;
}
public int weiSum(int x, int y) {
int sum = 0;
while (x > 0) {
sum += x % 10;
x = x / 10;
}
while (y > 0) {
sum += y % 10;
y = y / 10;
}
return sum;
}
public static void main(String[] args) {
Main13 m = new Main13();
System.out.println(m.movingCount(3, 3, 3));
}
}
14. 剪绳子
题目描述: 给你一根长度为n的绳子,请把绳子剪成整数长的m段(m、n都是整数,n>1并且m>1),每段绳子的长度记为k[0],k[1],…,k[m]。请问k[0]xk[1]x…xk[m]可能的最大乘积是多少?例如,当绳子的长度是8时,我们把它剪成长度分别为2、3、3的三段,此时得到的最大乘积是18。
实现方法: 1、时间复杂度为
O
(
n
2
)
O(n^2)
O(n2),空间复杂度为
O
(
n
)
O(n)
O(n)的动态规划。2、时间复杂度和空间复杂度都为
O
(
1
)
O(1)
O(1)的贪心算法。
import java.util.ArrayList;
public class Main14 {
public int cuttingRope(int n) {
if (n == 2)
return 1;
if (n == 3)
return 2;
ArrayList<Integer> array = new ArrayList();
array.add(0);
array.add(1);
array.add(2);
array.add(3);
int max = 0;
for (int i = 4; i <= n; i++) {
for (int j = 1; j <= i/2; j++) {
if (array.get(j) * array.get(i-j) > max) {
max = array.get(j) * array.get(i-j);
}
}
array.add(max);
}
return max;
}
public int tanxin(int n) {
if (n == 2)
return 1;
if (n == 3)
return 2;
int numOf3 = n / 3;
if (n - numOf3 * 3 == 1)
numOf3--;
int numOf2 = (n - numOf3 * 3) / 2;
return (int)(Math.pow(3, numOf3) * Math.pow(2, numOf2));
}
public static void main(String[] args) {
Main14 m = new Main14();
System.out.println(m.tanxin(10));
}
}
15. 二进制中1的个数
题目描述: 输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。
实现方法: 1、
c
=
1
c = 1
c=1, 让原数
&
c
\&c
&c,并不断将
c
c
c左移一位,直到
c
c
c大于
2
31
−
1
2^{31}-1
231−1 2、任何一个二进制数
&
\&
&(自己-1)都会讲该二进制数的最右边的1变为0,检查变了多少次该数才为0即可。
class Solution:
def NumberOf1_1(self, n):
x = 1
count = 0
while x < 2**32:
if n & x:
count += 1
x = x << 1
return count
def NumberOf1_2(self, n):
count = 0
while n >= -2**31 and n != 0:
count += 1
n = n & (n - 1)
return count
if __name__ == '__main__':
s = Solution()
print(s.NumberOf1_2(-1))
16. 数值的整数次方
题目描述: 给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。保证base和exponent不同时为0
实现方法: 注意指数为负数、底数为0的情况。
import sys
class Solution:
def Power(self, base, exponent):
if base == 0 and exponent < 0:
raise Exception('Invalid input!')
if base == 0:
return 0
newExponent = abs(exponent)
res = self.powerCore(base, newExponent)
if exponent < 0:
res = 1 / res
return res
def powerCore(self, base, exponent):
if exponent == 0:
return 1
if exponent == 1:
return base
res = self.powerCore(base, exponent >> 1)
res *= res
if exponent & 0x1 == 1:
res *= base
return res
if __name__ == '__main__':
s = Solution()
line = sys.stdin.readline().strip()
num = list(map(int, line.split()))
print(s.Power(num[0], num[1]))
17. 打印从1到最大的n位数
python不用考虑大数越界问题
import sys
class Solution:
def printNumbers(self, n):
tar = 10 ** n - 1
for i in range(1, tar+1):
print(i)
if __name__ == '__main__':
s = Solution()
n = int(sys.stdin.readline().strip())
s.printNumbers(n)
18.1 删除链表的节点
题目描述: 给定头节点和需要删除的节点,使用时间复杂度为
O
(
1
)
O(1)
O(1)的算法实现删除该节点的操作。
实现方法: 将下一个节点的值复制到该删除的节点,再删除下一个节点,若需要删除的节点为尾节点,则必须从头遍历,找到倒数第二个节点,再进行删除。
class ListNode:
def __init__(self, val):
self.val = val
self.next = None
def createNode(self, nodeP, val):
curNode = ListNode(val)
while nodeP.next != None:
nodeP = nodeP.next
nodeP.next = curNode
class Solution:
def deleteNode(self, nodeP, nodeN):
if nodeN.next == None:
p = nodeP
while p.next != nodeN:
p = p.next
p.next = None
del nodeN
return nodeP
elif nodeP.next == None:
return None
else:
nodeN.val = nodeN.next.val
nodeN.next = nodeN.next.next
return nodeP
if __name__ == '__main__':
s = Solution()
nodeHead = ListNode(1)
nodeHead.createNode(nodeHead, 2)
nodeHead.createNode(nodeHead, 3)
nodeHead.createNode(nodeHead, 4)
nodeP = s.deleteNode(nodeHead, nodeHead)
18.2 删除链表中重复的节点
题目描述: 给定头节点,删除链表中所有重复的节点,包括其本身如:
原链表:1 -> 2 -> 2 -> 3 -> 4
删除后的链表:1 -> 3 -> 4
class ListNode:
def __init__(self, val):
self.val = val
self.next = None
def createNode(self, nodeP, val):
curNode = ListNode(val)
while nodeP.next != None:
nodeP = nodeP.next
nodeP.next = curNode
class Solution:
def deleteSameNode(self, head):
if head == None or head.next == None:
return head
preNode = None
pNode = head
while pNode:
pNext = pNode.next
needDelete = False
if pNext and pNode.val == pNext.val:
needDelete = True
if not needDelete:
preNode = pNode
pNode = pNext
else:
toBeDeleted = pNode
value = pNode.val
while toBeDeleted and toBeDeleted.val == value:
pNode = toBeDeleted.next
del toBeDeleted
toBeDeleted = pNode
if preNode == None:
head = pNode
else:
preNode.next = pNode
return head
if __name__ == '__main__':
s = Solution()
nodeHead = ListNode(1)
nodeHead.createNode(nodeHead, 2)
nodeHead.createNode(nodeHead, 3)
nodeHead.createNode(nodeHead, 3)
nodeHead = s.deleteSameNode(nodeHead)
19. 正则表达式匹配
题目描述: 请实现一个函数用来匹配包括’.‘和’‘的正则表达式。模式中的字符’.‘表示任意一个字符,而’‘表示它前面的字符可以出现任意次(包含0次)。 在本题中,匹配是指字符串的所有字符匹配整个模式。例如,字符串"aaa"与模式"a.a"和"abaca"匹配,但是与"aa.a"和"ab*a"均不匹配
实现方法:
当模式中的第二个字符是
∗
*
∗时:1、如果字符串第一个字符跟模式第一个字符匹配,可以有3种匹配方式:(1)模式后移2字符,相当于
x
∗
x*
x∗被忽略;(2)字符串后移1字符,模式后移2字符,相当于
x
∗
x*
x∗匹配一位;(3)字符串后移1字符,模式不变,即继续匹配字符下一位,相当于
x
∗
x*
x∗匹配多位;2、如果字符串第一个字符跟模式第一个字符不匹配,则模式后移2个字符,继续匹配。
当模式中的第二个字符不是
∗
*
∗时:1、如果字符串第一个字符和模式中的第一个字符相匹配,那么字符串和模式都后移一个字符,然后匹配剩余的部分。2、如果字符串第一个字符和模式中的第一个字符相不匹配,直接返回False。注意:切片超出范围即为空字符串,如a=‘a’,则a[1:]=’’,并不会报错
import sys
class Solution:
def match(self, mystr, pattern):
if mystr is None or pattern is None:
return False
return self.matchCore(mystr, pattern)
def matchCore(self, mystr, pattern):
if len(mystr) == 0 and len(pattern) == 0:
return True
if len(mystr) > 0 and len(pattern) == 0:
return False
if len(pattern) > 1 and pattern[1] == '*':
if mystr and (pattern[0] == mystr[0] or pattern[0] == '.' ):
return self.matchCore(mystr[1:], pattern[2:]) \
or self.matchCore(mystr[1:], pattern) \
or self.matchCore(mystr, pattern[2:])
else:
return self.matchCore(mystr, pattern[2:])
if mystr and (pattern[0] == mystr[0] or pattern[0] == '.'):
return self.matchCore(mystr[1:], pattern[1:])
return False
if __name__ == '__main__':
s = Solution()
mystr = sys.stdin.readline().strip()
pattern = sys.stdin.readline().strip()
print(s.match(mystr, pattern))
20. 表示数值的字符串
题目描述: 请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100",“5e2”,"-123",“3.1416"和”-1E-16"都表示数值。 但是"12e",“1a3.14”,“1.2.3”,"±5"和"12e+4.3"都不是。
实现方法: 设置3个bool型变量,分别代表已经遇到“.”、“e”或“E”、“数字”。1、当前字符为“+”或“-”时:如果当前不在字符串首部,并且没有遇到“e”或“E”,则返回False。2、当前字符为“.”时,如果已经遇到“.”或“e”或“E”都返回False。3、当前字符为“e”或“E”时,如果没有遇到过数字或已经遇到过“e”或“E”,则返回False,详见代码:
import sys
class Solution:
def isNumeric(self, s):
if s is None or s == '':
return False
s = s.strip()
met_dot = met_e = met_digit = False
for i, ch in enumerate(s):
if ch in ['+', '-']:
if i > 0 and (s[i-1] not in ['e', 'E']):
return False
elif ch == '.':
if met_dot or met_e:
return False
met_dot = True
elif ch in ['e', 'E']:
if met_e or (not met_digit):
return False
met_e = True
met_digit = False
elif ch.isdigit():
met_digit = True
else:
return False
return met_digit
if __name__ == '__main__':
line = sys.stdin.readline().strip()
s = Solution()
print(s.isNumeric(line))
21. 调整数组顺序使奇数位于偶数前面
题目描述: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。
实现方法: 设2个相邻指针i、j,j = i + 1,i遇到偶数时停止,j遇到奇数时停止,然后之间的数字后移。
# 调整数组顺序使奇数位于偶数前面
import sys
class Solution:
def reOrderArray(self, array): # 相邻双指针牛客网可通过
if array == [] or len(array) == 1:
return array
i = 0
j = 0
while i < len(array) and j < len(array):
while i < len(array) and array[i] & 1 != 0: # 若为奇数
i += 1
j = i + 1
while j < len(array) and array[j] & 1 == 0: # 若为偶数
j += 1
if j < len(array):
tmp_index = j
tmp = array[j]
while j > i:
array[j] = array[j-1]
j -= 1
array[i] = tmp
j = tmp_index
return array
# def reOrderArray(self, array): # 头尾双指针法不稳定,但时间复杂度低Leetcode上该方法可以
# if array == []:
# return []
# begin = 0
# end = len(array) - 1
# while begin < end:
# while array[begin] & 0x1 != 0 and begin < end:
# begin += 1
# while array[end] & 0x1 == 0 and end > begin:
# end -= 1
# if begin < end:
# tmp = array[begin]
# array[begin] = array[end]
# array[end] = tmp
# begin += 1
# end -= 1
# return array
if __name__ == '__main__':
s = Solution()
line = sys.stdin.readline().strip()
array = list(map(int, line.split()))
print(s.reOrderArray(array))
22. 链表的倒数第k个节点
题目描述: 输入一个链表,输出该链表中倒数第k个结点。
实现方法: 设2个指针,第一个从head往后走k-1步,第二个就在head,随后两个指针分别向前各走一步,直到第一个指针走到了尾节点。第二个节点即为倒数第k个节点。注意判断k大于链表长度的情况。
class ListNode:
def __init__(self, val):
self.val = val
self.next = None
def creatNode(self, head, val):
p = head
while not p.next is None:
p = p.next
p.next = ListNode(val)
class Solution:
def FindKthToTail(self, head, k):
if head is None or k <= 0:
return None
p_i = head
count = 0
while p_i and count < k-1 :
p_i = p_i.next
count += 1
if p_i is None:
return None
p_j = head
while p_i.next:
p_i = p_i.next
p_j = p_j.next
return p_j
if __name__ == '__main__':
s = Solution()
head = ListNode(1)
head.creatNode(head, 2)
head.creatNode(head, 3)
print(s.FindKthToTail(head, 4))