剑指offer刷题

Liana ·
更新时间:2024-11-11
· 701 次阅读

1、二维数组中查找

题目描述:在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序。请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数。

思路:可以利用从左到右递增、从上到下递增的特点,开始从数组最右上角开始查找。如果array[rows][cols]比该整数小则row++,如果比该整数大则col--,找到返回True,如果直到数组越界了还没有找到的话就返回False。

# -*- coding:utf-8 -*- class Solution: # array 二维列表 def Find(self, target, array): # write code here rows= len(array) - 1 row = 0 col = len(array[0]) - 1 flag = False while row = 0: if array[row][col] == target: flag = True break elif array[row][col] > target: col -= 1 else: row += 1 return flag

2、替换空格

题目描述:请实现一个函数,将一个字符串中的每个空格替换成“%20”。例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy。

思路:C语言可以先统计空格个数m,然后new一个新指针指向一个大小为3*m+n长度新的内存空间,遍历原字符串复制字符到新字符串中,遇到空格则加‘%’,‘2’,‘0’三个字符。我直接用了python字符串的替换函数,哈哈哈哈哈哈

# -*- coding:utf-8 -*- class Solution: # s 源字符串 def replaceSpace(self, s): # write code here newStr = s.replace(' ', '%20') return newStr

3、从尾到头打印链表

题目描述:输入一个链表,按链表从尾到头的顺序返回一个ArrayList。

思路:1、利用头插法,新建一个链表,将原链表数据按照头插法的思路插入到新链表。

            2、利用栈的特点,递归。

# -*- 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 pTemp = listNode p = [] while pTemp != None: p.insert(0, pTemp.val) pTemp = pTemp.next return p # -*- 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 ret = [] def reverse(Node): if Node: reverse(Node.next) ret.append(Node.val) reverse(listNode) return ret

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): # write code here if len(pre)==0: return None if len(pre)==1: return TreeNode(pre[0]) root = TreeNode(pre[0]) root_left = tin[:tin.index(pre[0])] root_right = tin[tin.index(pre[0])+1:] root.left = self.reConstructBinaryTree(pre[1:tin.index(pre[0])+1], root_left) root.right = self.reConstructBinaryTree(pre[tin.index(pre[0])+1:], root_right) return root

5、用两个栈实现队列

题目描述:用两个栈来实现一个队列,完成队列的Push和Pop操作。 队列中的元素为int类型。

思路:队列先入先出,定义两个栈Push栈和Pop栈。当执行Push操作时,就直接往Push栈里append数据。但执行Pop操作时,先判断Pop栈是否为空,如果不为空直接放回最后一个元素,否则判断Push栈是否为空,不为空的话把Push栈里的数据全部append到Pop栈里面,最后输出Pop栈的最后一个元素。

# -*- coding:utf-8 -*- class Solution: def __init__(self): self.stack1 = [] self.stack2 = [] def push(self, node): self.stack1.append(node) # write code here def pop(self): # return xx if self.stack2 == []: while self.stack1: self.stack2.append(self.stack1.pop()) return self.stack2.pop()

6、旋转数组的最小数字

题目描述:把一个数组最开始的若干个元素搬到数组的末尾,我们称之为数组的旋转。输入一个非递减排序的数组的一个旋转,输出旋转数组的最小元素。例如数组{3,4,5,1,2}为{1,2,3,4,5}的一个旋转,该数组的最小值为1。
NOTE:给出的所有元素都大于0,若数组大小为0,请返回0。

思路:最暴力的解法就是遍历数组找到数组最小的元素,时间复杂度为O(n)。这里我使用二分法的思想,最小的元素应该满足比它的前后元素都小。

# -*- coding:utf-8 -*- class Solution: def minNumberInRotateArray(self, rotateArray): # write code here if len(rotateArray) == 0: return 0 left = 0 right = len(rotateArray) - 1 while left < right: if rotateArray[left] < rotateArray[right]: return rotateArray[left] mid = left + (right - left) // 2 if rotateArray[left] < rotateArray[mid]: left = mid + 1 elif rotateArray[mid] < rotateArray[right]: right = mid else: left += 1 return rotateArray[left]

7、斐波那契数列

题目描述:大家都知道斐波那契数列,现在要求输入一个整数n,请你输出斐波那契数列的第n项(从0开始,第0项为0,第1项是1)。 

n<=39

思路:通式为a(n) = a(n - 1) + a(n - 2)  n>=2, 可以用for循环也可以递归

# -*- coding:utf-8 -*- class Solution: def Fibonacci(self, n): # write code here if n <= 1: return n else: i = 2 first = 0 second = 1 while i <=n: result = first + second first = second second = result i = i + 1 return result

8、跳台阶

题目描述:一只青蛙一次可以跳上1级台阶,也可以跳上2级。求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果)。

思路:通式为a(n) = a(n - 1) + a(n - 2), n>=2 其中a(1) = 1, a(2) = 2。

# -*- coding:utf-8 -*- class Solution: def jumpFloor(self, number): # write code here if number == 0: return 0 if number == 1: return 1 if number == 2: return 2 exp_1 = 1 exp_2 = 2 for i in range(2, number): result = exp_1 + exp_2 exp_1 = exp_2 exp_2 = result return result

9、变态跳台阶

题目描述:一只青蛙一次可以跳上1级台阶,也可以跳上2级……它也可以跳上n级。求该青蛙跳上一个n级的台阶总共有多少种跳法。

思路:通式为a(n) = 2 * a(n - 1), 推导过程为a(n) = a(1) + a(2) + ..... + a(n - 1) (1) , a(n - 1) = a(1) + a(2) + ..... + a(n - 2)(2), 则(2)代入(1)可得。

# -*- coding:utf-8 -*- class Solution: def jumpFloorII(self, number): # write code here if number == 0: return 0 if number == 1: return 1 if number == 2: return 2 exp_1 = 1 exp_2 = 2 for i in range(2, number): result = 2 * exp_2 exp_2 = result return result

10、矩形覆盖

题目描述:

我们可以用2*1的小矩形横着或者竖着去覆盖更大的矩形。请问用n个2*1的小矩形无重叠地覆盖一个2*n的大矩形,总共有多少种方法? 

比如n=3时,2*3的矩形块有3种覆盖方法:

思路:通式为a(n) = a(n - 1) + a(n - 2), a(n - 1)为矩形竖着覆盖的情况, a(n - 2)为横着覆盖。

# -*- coding:utf-8 -*- class Solution: def rectCover(self, number): # write code here # f(n) = f(n - 1) + f(n - 2) if number <= 2: return number a = 1 b = 2 for i in range(2, number): result = a + b a = b b = result return result

11、二进制中1的个数

题目描述:输入一个整数,输出该数二进制表示中1的个数。其中负数用补码表示。

思路:正整数的补码是其二进制表示,与原码相同。负整数的补码,将其原码除符号位外的所有位取反(0变1,1变0,符号位为1不变)后加1。第一个思路可以将整数分别与32位中的每一位做与操作,如果不为0,个数加一。第二个思路如果一个整数不为0,那么这个整数至少有一位是1。如果我们把这个整数减1,那么原来处在整数最右边的1就会变为0,原来在1后面的所有的0都会变成1(如果最右边的1后面还有0的话)。其余所有位将不会受到影响。举个例子:一个二进制数1100,从右边数起第三位是处于最右边的一个1。减去1后,第三位变成0,它后面的两位0变成了1,而前面的1保持不变,因此得到的结果是1011.我们发现减1的结果是把最右边的一个1开始的所有位都取反了。这个时候如果我们再把原来的整数和减去1之后的结果做与运算,从原来整数最右边一个1那一位开始所有位都会变成0。如1100&1011=1000.也就是说,把一个整数减去1,再和原整数做与运算,会把该整数最右边一个1变成0.那么一个整数的二进制有多少个1,就可以进行多少次这样的操作。

# -*- coding:utf-8 -*- class Solution: def NumberOf1(self, n): # write code here # first solution count = 0 for i in range(32): mask = 1 << i if n & mask != 0: count += 1 return count ''' # second solution count = 0 while n != 0: count = count + 1 n = n&(n - 1) return count '''

12、数值的整数次方

题目描述:

给定一个double类型的浮点数base和int类型的整数exponent。求base的exponent次方。 保证base和exponent不同时为0

思路:分exponent>0, exponent<0两种情况来做就行了。第二种情况用快速幂来做,也就是位运算

# -*- coding:utf-8 -*- class Solution: def Power(self, base, exponent): # write code here if base == 0: return 0 if exponent == 0: return 1 flag = False if exponent < 0: flag = True exponent = -exponent Ret = 0 for i in range(exponent): if Ret == 0: Ret = base else: Ret *= base if flag: return 1.0 / Ret else: return Ret # -*- coding:utf-8 -*- class Solution: def Power(self, base, exponent): # write code here if base == 0: return 0 if exponent == 0: return 1 flag = False ans = 1 if exponent 0: if exponent & 1 == 1: ans *= base exponent >>= 1 base *= base return 1.0 / ans if flag else ans

13、调整数组顺序使奇数位于偶数前面

题目描述:输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变。

思路:第一种可以用两个list分别保存数组种的奇数和偶数,然后将两个list合并就好了。第二张可以借用冒泡排序的思想。

# -*- coding:utf-8 -*- class Solution: def reOrderArray(self, array): # write code here # first solution ''' if array == None: return [] if len(array) == 1: return array oddArray = [] evenArray = [] for i in array: if i % 2 != 0: oddArray.append(i) else: evenArray.append(i) oddArray.extend(evenArray) return oddArray ''' # second solution num = len(array) if num <= 1: return array for i in range(num): for j in range(num - 1): if array[j] % 2 == 0 and array[j + 1] % 2 == 1: array[j], array[j+1] = array[j+1], array[j] return array

14、链表中倒数第K个节点

问题描述:输入一个链表,输出该链表中倒数第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 secondNode = head firstNode = head for i in range(k): if firstNode == None: return None firstNode = firstNode.next while firstNode: firstNode = firstNode.next secondNode = secondNode.next return secondNode

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 pHead == None: return None if pHead.next == None: return pHead first = pHead second = pHead.next third = second.next first.next = None while third != None: second.next = first first = second second = third third = third.next second.next = first return second

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 if pHead1 == None: return pHead2 if pHead2 == None: return pHead1 newHead = pHead1 if pHead1.val < pHead2.val else pHead2 tHead1 = pHead1 tHead2 = pHead2 tHead = newHead if newHead == tHead1: tHead1 = tHead1.next else: tHead2 = tHead2.next while tHead1 and tHead2: if tHead1.val < tHead2.val: tHead.next = tHead1 tHead = tHead1 tHead1 = tHead1.next else: tHead.next = tHead2 tHead = tHead2 tHead2 = tHead2.next if tHead1 != None: tHead.next = tHead1 else: tHead.next = tHead2 return newHead

17、树的子结构

题目描述:输入两棵二叉树A,B,判断B是不是A的子结构。(ps:我们约定空树不是任意一个树的子结构)

思路:子树的意思是包含了一个结点,就得包含这个结点下的所有节点,一棵大小为n的二叉树有n个子树,就是分别以每个结点为根的子树。子结构的意思是包含了一个结点,可以只取左子树或者右子树,或者都不取。

# -*- coding:utf-8 -*- # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def HasSubtree(self, pRoot1, pRoot2): # write code here if pRoot1 == None or pRoot2 == None: return False def judgeSubTree(pRoot1, pRoot2): if pRoot2 == None: return True if pRoot1 == None: return False if pRoot1.val == pRoot2.val: if pRoot2.left == None: leftEqual = True else: leftEqual = judgeSubTree(pRoot1.left, pRoot2.left) if pRoot2.right == None: rightEqual = True else: rightEqual = judgeSubTree(pRoot1.right, pRoot2.right) return leftEqual and rightEqual return False if pRoot1.val == pRoot2.val: ret = judgeSubTree(pRoot1, pRoot2) if ret: return True leftRet = self.HasSubtree(pRoot1.left, pRoot2) rightRet = self.HasSubtree(pRoot1.right, pRoot2) return leftRet or rightRet public boolean HasSubtree(TreeNode root1,TreeNode root2) { if(root1==null||root2==null) return false; boolean result=false; if(root1.val==root2.val){ result = HasSubtreeHelper(root1,root2); } if(!result) result = HasSubtree(root1.left,root2); if(!result) result = HasSubtree(root1.right,root2); return result; } public boolean HasSubtreeHelper(TreeNode r1,TreeNode r2){ if(r2==null) return true; if(r1==null) return false; if(r1.val!=r2.val) return false; return HasSubtreeHelper(r1.left,r2.left)&&HasSubtreeHelper(r1.right,r2.right); }

18、二叉树的镜像

题目描述:操作给定的二叉树,将其变换为源二叉树的镜像。

思路:递归交换位置即可。

# -*- coding:utf-8 -*- # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: # 返回镜像树的根节点 # 递归 def Mirror(self, root): # write code here if root == None: return None root.left, root.right = root.right, root.left self.Mirror(root.left) self.Mirror(root.right) # 非递归,层次遍历 ''' if root == None: return None ret = [root] while ret: temp = ret[0] if temp.right: ret.append(temp.right) if temp.left: ret.append(temp.left) temp.left, temp.right = temp.right, temp.left del ret[0] 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。

思路:定义四个变量代表范围,top、bottom、left、right

向右走存入整行的值,当存入后,该行再也不会被遍历,代表上边界的 top 加一,同时判断是否和代表下边界的 bottom 交错  向下走存入整列的值,当存入后,该列再也不会被遍历,代表右边界的 right 减一,同时判断是否和代表左边界的 left 交错  向左走存入整行的值,当存入后,该行再也不会被遍历,代表下边界的 bottom 减一,同时判断是否和代表上边界的 top 交错  向上走存入整列的值,当存入后,该列再也不会被遍历,代表左边界的 left 加一,同时判断是否和代表右边界的 right 交错 # -*- coding:utf-8 -*- class Solution: # matrix类型为二维列表,需要返回列表 def printMatrix(self, matrix): # write code here ''' row = len(matrix) col = len(matrix[0]) l = [] start = 0 while row > 2*start and col > 2*start: endx = row - 1 - start endy = col - 1 - start for i in range(start, endy+1): l.append(matrix[start][i]) if start < endx: for i in range(start+1, endx+1):#角上的重复算了一次 l.append(matrix[i][endy]) if start < endx and start < endy: for i in range(endy-1, start-1, -1): l.append(matrix[endx][i]) if start < endx-1 and start bottom: break for i in range(top, bottom + 1): ret.append(matrix[i][right]) right -= 1 if right < left: break for i in range(right, left - 1, -1): ret.append(matrix[bottom][i]) bottom -= 1 if bottom right: break return ret # write code here ''' rows=len(matrix) cols=len(matrix[0]) result=[] if rows==0 and cols==0: return result left,right,top,bottom = 0,cols-1,0,rows-1 while left<=right and top<=bottom: for i in range(left,right+1): result.append(matrix[top][i]) for i in range(top+1,bottom+1): result.append(matrix[i][right]) if top!=bottom: for i in range(right-1,left-1,-1): result.append(matrix[bottom][i]) if left!=right: for i in range(bottom-1,top,-1): result.append(matrix[i][left]) left+=1 right-=1 top+=1 bottom-=1 return result '''

20、包含min函数的栈

问题描述:

定义栈的数据结构,请在该类型中实现一个能够得到栈中所含最小元素的min函数(时间复杂度应为O(1)。注意:保证测试中不会当栈为空的时候,对栈调用pop()或者min()或者top()方法。

思路:使用一个辅助最小栈来保留当前长度栈中的最小值。

# -*- coding:utf-8 -*- class Solution: def __init__(self): self.stack = [] self.minValue = [] def push(self, node): # write code here self.stack.append(node) if self.minValue: if self.minValue[-1] > node: self.minValue.append(node) else: self.minValue.append(self.minValue[-1]) else: self.minValue.append(node) def pop(self): # write code here if self.stack == []: return None self.minValue.pop() return self.stack.pop() def top(self): # write code here if self.stack == []: return None return self.stack[-1] def min(self): # write code here if self.minValue == []: return None return self.minValue[-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 if pushV and len(pushV) != len(popV): return None stack = [] index = 0 for item in pushV: stack.append(item) while stack and stack[-1] == popV[index]: stack.pop() index += 1 if stack == []: return True else: return False

22、从上往下打印二叉树

题目描述:从上往下打印出二叉树的每个节点,同层节点从左至右打印。

思路:树的层次遍历。

# -*- 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 root == None: return [] tempList = [root] ret = [] while tempList: temp = tempList[0] ret.append(temp.val) if temp.left: tempList.append(temp.left) if temp.right: tempList.append(temp.right) del tempList[0] return ret

23、二叉搜索树的后序遍历序列

题目描述:输入一个非空整数数组,判断该数组是不是某二叉搜索树的后序遍历的结果。如果是则输出Yes,否则输出No。假设输入的数组的任意两个数字都互不相同。

思路:二叉搜索树:它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值。若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值。利用二叉搜索树根节点比左子树节点值大比右子树节点值小,后序遍历最后一个为根节点的特点来做。

# -*- coding:utf-8 -*- class Solution: def VerifySquenceOfBST(self, sequence): # write code here if sequence == []: return False seqLen = len(sequence) - 1 count = 0 while seqLen: while sequence[count] sequence[seqLen]: count += 1 if count val: index = i if index != None and sequence[i] 0: leftRet = self.VerifySquenceOfBST(sequence[:index]) if index > len(sequence) - 1: rightRet = self.VerifySquenceOfBST(sequence[index:len(sequence) - 1]) return leftRet and rightRet ''' ''' if not sequence: return False #找到根节点 root = sequence[-1] i = 0 #找到左子树和右子树的分界点 while i root: break i += 1 for j in range(i,len(sequence)-1): if sequence[j] 0: left = self.VerifySquenceOfBST(sequence[:i]) if i < len(sequence) - 1: right = self.VerifySquenceOfBST(sequence[i:len(sequence) - 1]) return left and right '''

24、二叉树中和为某一值的路径

题目描述:输入一颗二叉树的根节点和一个整数,打印出二叉树中结点值的和为输入整数的所有路径。路径定义为从树的根结点开始往下一直到叶结点所经过的结点形成一条路径。

思路:深度优先遍历,保存所有到根节点的路径。输出满足要求的路径。

# -*- coding:utf-8 -*- # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None import copy class Solution: # 返回二维列表,内部每个列表表示找到的路径 def FindPath(self, root, expectNumber): # write code here if root == None: return [] ret = [] supportArrayList = [[root.val]] support = [root] while support: tempNode = support[0] tempArrayList = supportArrayList[0] if tempNode.left == None and tempNode.right == None: if sum(tempArrayList) == expectNumber: ret.insert(0, tempArrayList) if tempNode.left: newArrayList = copy.copy(tempArrayList) newArrayList.append(tempNode.left.val) support.append(tempNode.left) supportArrayList.append(newArrayList) if tempNode.right: newArrayList = copy.copy(tempArrayList) newArrayList.append(tempNode.right.val) support.append(tempNode.right) supportArrayList.append(newArrayList) del support[0] del supportArrayList[0] return ret

25、复杂链表的复制

题目描述:输入一个复杂链表(每个节点中有节点值,以及两个指针,一个指向下一个节点,另一个特殊指针random指向一个随机节点),请对此链表进行深拷贝,并返回拷贝后的头结点。(注意,输出结果中请不要返回参数中的节点引用,否则判题程序会直接返回空)

思路:python中的copy模块有个deepcopy函数,可以直接AC 哈哈哈哈哈哈哈。我这思路是先将链表复制,然后根据原链表的next指针和random指针来指新链表的指针,最后将原链表断开。

# -*- coding:utf-8 -*- # class RandomListNode: # def __init__(self, x): # self.label = x # self.next = None # self.random = None import copy class Solution: # 返回 RandomListNode def Clone(self, pHead): # write code here # 复制每个节点,如复制A节点A1,将A1插到A的后面 if pHead is None: return None copyNode = pHead while copyNode: tempNode = RandomListNode(copyNode.label) nextNode = copyNode.next copyNode.next = tempNode tempNode.next = nextNode copyNode = nextNode # 重新遍历链表,复制老结点的随机指针给新结点,如A1.random = A.random.next copyNode = pHead while copyNode: copyNode.next.random = None if copyNode.random == None else copyNode.random.next copyNode = copyNode.next.next # 拆分链表,将链表拆分为原链表和复制后的链表 cloneHead = pHead.next copyNode = pHead n = pHead while copyNode: tempNode = copyNode.next copyNode.next = tempNode.next tempNode.next = None if tempNode.next == None else tempNode.next.next copyNode = copyNode.next return cloneHead

26、二叉搜索树与双向链表***

题目描述:输入一棵二叉搜索树,将该二叉搜索树转换成一个排序的双向链表。要求不能创建任何新的结点,只能调整树中结点指针的指向。

思路:首先要找到双向链表头节点,如果二叉搜索树有左子树的话,那么它的最左的叶子节点就是头节点。如果只有右子树的话,那么二叉搜索树的根节点就是双向链表的头节点。也可以使用中序递归遍历存入列表,最后将列表中的节点中指针进行调换,返回list1[0]。

# -*- coding:utf-8 -*- # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def Convert(self, pRootOfTree): # write code here if pRootOfTree == None: return None def findLeftRight(left): while left.right: left = left.right return left leftNode = self.Convert(pRootOfTree.left) rightNode = self.Convert(pRootOfTree.right) retNode = leftNode if leftNode: leftNode = findLeftRight(leftNode) else: retNode = pRootOfTree pRootOfTree.left = leftNode pRootOfTree.right = rightNode if leftNode != None: leftNode.right = pRootOfTree if rightNode != None: rightNode.left = pRootOfTree return retNode # -*- coding:utf-8 -*- # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def zhongxu(self,root): if not root: return [] return self.zhongxu(root.left)+[root]+self.zhongxu(root.right) def Convert(self, pRootOfTree): # write code here list1=self.zhongxu(pRootOfTree) if len(list1)==0: return None if len(list1)==1: return pRootOfTree for i in range(len(list1)-1): list1[i].right=list1[i+1] list1[i+1].left=list1[i] return list1[0]

27、字符串的排列***

题目描述:输入一个字符串,按字典序打印出该字符串中字符的所有排列。例如输入字符串abc,则打印出由字符a,b,c所能排列出来的所有字符串abc,acb,bac,bca,cab和cba。

思路:递归打印就好了

# -*- coding:utf-8 -*- class Solution: def Permutation(self, ss): # write code here l = [] if len(ss) <= 1: return ss n = len(ss) i = 0 while i < n: #temp = ss[i] + self.Permutation(ss[:i]+ss[i+1:]) for j in self.Permutation(ss[:i]+ss[i+1:]): temp = ss[i] + str(j) if temp not in l: l.append(temp) i += 1 return l

28、数组中出现次数超过一半的数字

题目描述:数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}。由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2。如果不存在则输出0。

思路: 两两不相同的数字相互抵消,剩下了的数字嘉定是超过一半的次数的数字,最后遍历一遍数组验证一下就可以了

# -*- coding:utf-8 -*- class Solution: def MoreThanHalfNum_Solution(self, numbers): # write code here ''' First Solution tempDict = {} numLen = len(numbers) for num in numbers: if num in tempDict: tempDict[num] += 1 else: tempDict[num] = 1 if tempDict[num] > (numLen >> 1): return num return 0 ''' first = 0 preCount = 0 numLen = len(numbers) for num in numbers: if preCount == 0: first = num preCount += 1 else: if first == num: preCount += 1 else: preCount -= 1 if preCount == 0: return 0 else: Count = 0 for num in numbers: if num == first: Count += 1 if Count > (numLen >> 1): return first return 0

29、最小K个数***

题目描述:输入n个整数,找出其中最小的K个数。例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,。

思路:用大根堆这个数据结构。

# -*- coding:utf-8 -*- class Solution: def GetLeastNumbers_Solution(self, tinput, k): # write code here def createMaxHeap(num): maxHeap.append(num) currentIndex = len(maxHeap) - 1 while currentIndex != 0: parentIndex = (currentIndex - 1) >> 1 if maxHeap[parentIndex] < maxHeap[currentIndex]: maxHeap[parentIndex], maxHeap[currentIndex] = maxHeap[currentIndex], maxHeap[parentIndex] currentIndex = parentIndex else: break def adjustMaxHeap(num): if num < maxHeap[0]: maxHeap[0] = num maxHeapLen = len(maxHeap) index = 0 while index < maxHeapLen: leftIndex = index * 2 + 1 rightIndex = index * 2 + 2 largeIndex = 0 if rightIndex < maxHeapLen: if maxHeap[rightIndex] < maxHeap[leftIndex]: largeIndex = leftIndex else: largeIndex = rightIndex elif leftIndex < maxHeapLen: largeIndex = leftIndex else: break if maxHeap[index] < maxHeap[largeIndex]: maxHeap[index], maxHeap[largeIndex] = maxHeap[largeIndex], maxHeap[index] index = largeIndex maxHeap = [] inputLen = len(tinput) if inputLen < k or k <= 0: return [] for i in range(inputLen): if i < k: createMaxHeap(tinput[i]) else: adjustMaxHeap(tinput[i]) maxHeap.sort() return maxHeap

30、连续子数组的最大和

问题描述:HZ偶尔会拿些专业问题来忽悠那些非计算机专业的同学。今天测试组开完会后,他又发话了:在古老的一维模式识别中,常常需要计算连续子向量的最大和,当向量全为正数的时候,问题很好解决。但是,如果向量中包含负数,是否应该包含某个负数,并期望旁边的正数会弥补它呢?例如:{6,-3,-2,7,-15,1,2,2},连续子向量的最大和为8(从第0个开始,到第3个为止)。给一个数组,返回它的最大连续子序列的和,你会不会被他忽悠住?(子向量的长度至少是1)

思路:动态规划问题,如果array[0] + .....+ array[n] >= array[n]则可以继续加下去,不然直接从array[n]从头开始加

# -*- coding:utf-8 -*- class Solution: def FindGreatestSumOfSubArray(self, array): # write code here maxSum = None tempNum = 0 for i in array: if maxSum == None: maxSum = i if tempNum + i maxSum: maxSum = tempNum return maxSum

31、整数中出现1的次数***

题目描述:求出1~13的整数中1出现的次数,并算出100~1300的整数中1出现的次数?为此他特别数了一下1~13中包含1的数字有1、10、11、12、13因此共出现6次,但是对于后面问题他就没辙了。ACMer希望你们帮帮他,并把问题更加普遍化,可以很快的求出任意非负整数区间中1出现的次数(从1 到 n 中1出现的次数)。

思路:设定整数点(如1、10、100等等)作为位置点i(对应n的各位、十位、百位等等),分别对每个数位上有多少包含1的点进行分析。根据设定的整数位置,对n进行分割,分为两部分,高位n/i,低位n%i 。

当i表示百位,且百位对应的数>=2,如n=31456,i=100,则a=314,b=56,此时百位为1的次数有a/10+1=32(最高两位0~31),每一次都包含100个连续的点,即共有(a%10+1)*100个点的百位为1 。

当i表示百位,且百位对应的数为1,如n=31156,i=100,则a=311,b=56,此时百位对应的就是1,则共有a%10(最高两位0-30)次是包含100个连续点,当最高两位为31(即a=311),本次只对应局部点00~56,共b+1次,所有点加起来共有(a%10*100)+(b+1),这些点百位对应为1 。

当i表示百位,且百位对应的数为0,如n=31056,i=100,则a=310,b=56,此时百位为1的次数有a/10=31(最高两位0~30) 

综合以上三种情况,当百位对应0或>=2时,有(a+8)/10次包含所有100个点,还有当百位为1(a%10==1),需要增加局部点b+1 。之所以补8,是因为当百位为0,则a/10==(a+8)/10,当百位>=2,补8会产生进位位,效果等同于(a/10+1)

# -*- coding:utf-8 -*- class Solution: def NumberOf1Between1AndN_Solution(self, n): # write code here ''' index = 1 count = 0 sumNum = 0 highNum = 1 midNum = 1 lowNum = 1 while highNum != 0: highNum = n // (index * 10) midNum = (n // index) % 10 lowNum = n % index index = index * 10 if midNum == 0: num = highNum * pow(10, count) elif midNum > 1: num = (highNum + 1) * pow(10, count) else: num = highNum * pow(10, count) + lowNum + 1 sumNum += num count += 1 return sumNum ''' count = 0 i = 1 while i <= n: first = n / i second = n % i count += (first + 8) / 10 * i + (first % 10 == 1)*(second + 1) i *= 10 return count

32、把数组排成最小的数

题目描述:输入一个正整数数组,把数组里所有数字拼接起来排成一个数,打印能拼接出的所有数字中最小的一个。例如输入数组{3,32,321},则打印出这三个数字能排成的最小数字为321323。

思路:我这里用的是冒泡排序的思想,两两数字拼接,如果前面的拼成的数字比后面拼成的数字要大,则两两互换位置。简单意思就是局部最小促成全局最小。

# -*- coding:utf-8 -*- class Solution: def PrintMinNumber(self, numbers): # write code here Len = len(numbers) for i in range(Len): for j in range(i + 1, Len): if int((str(numbers[j])+str(numbers[i])) < (str(numbers[i])+str(numbers[j]))): numbers[j], numbers[i] = numbers[i], numbers[j] return ''.join([str(num) for num in numbers])

33、丑数

题目描述:把只包含质因子2、3和5的数称作丑数(Ugly Number)。例如6、8都是丑数,但14不是,因为它包含质因子7。 习惯上我们把1当做是第一个丑数。求按从小到大的顺序的第N个丑数。

思路:所有的丑数都是2, 3 ,5这三个数的乘积所得来的。定义一个丑数列表,三个指针分别代表2, 3, 5三个数在丑数列表最小值所在的下标,每次三个指针都乘上2, 3, 5三个数,最小的数放入丑数列表中,然后当前指针指向的下标加一。最后的终止条件是丑数列表大小为N。

# -*- coding:utf-8 -*- class Solution: def GetUglyNumber_Solution(self, index): # write code here if index < 1: return 0 uglyList = [1] twoPointer = 0 threePointer = 0 fivePointer = 0 for i in range(index - 1): uglyValue = min(2*uglyList[twoPointer], 3*uglyList[threePointer], 5*uglyList[fivePointer]) uglyList.append(uglyValue) if uglyValue == uglyList[twoPointer]*2: twoPointer += 1 if uglyValue == uglyList[threePointer]*3: threePointer += 1 if uglyValue == uglyList[fivePointer]*5: fivePointer += 1 return uglyList[-1]

34、第一个只出现一次的字符

题目描述:在一个字符串(0<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置, 如果没有则返回 -1(需要区分大小写).(从0开始计数)

思路:最简单粗暴的方法就是遍历一遍字符串,用count函数看字符出现的次数是否为1。

# -*- coding:utf-8 -*- class Solution: def FirstNotRepeatingChar(self, s): # write code here if not s: return -1 for i in range(len(s)): if s.count(s[i]) == 1: return i return -1

35、数组中的逆序对***

题目描述:在数组中的两个数字,如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对。输入一个数组,求出这个数组中的逆序对的总数P。并将P对1000000007取模的结果输出。 即输出P%1000000007

思路:归并排序在合并的时候统计逆序对。

# -*- coding:utf-8 -*- count = 0 class Solution: def InversePairs(self, data): # write code here ''' # only pass 50% data arrLen = len(data) count = 0 for i in range(1, arrLen): for j in range(i): if data[j] > data[i]: count += 1 return count % 1000000007 ''' global count def MergeSort(lists): global count if len(lists) <= 1: return lists num = int( len(lists)/2 ) left = MergeSort(lists[:num]) right = MergeSort(lists[num:]) r, l=0, 0 result=[] while l<len(left) and r<len(right): if left[l] < right[r]: result.append(left[l]) l += 1 else: result.append(right[r]) r += 1 count += len(left)-l result += left[l:] result += right[r:] return result MergeSort(data) return count%1000000007

36、两个链表的第一个公共节点

题目描述:输入两个链表,找出它们的第一个公共结点。(注意因为传入数据是链表,所以错误测试数据的提示是用其他方式显示的,保证传入数据是正确的)

思路:第一种思路是计算长链表和短链表相差的长度k,然后先长链表走k步,再长短链表一起走,最后两个链表走到的节点相同时就是第一个公共节点。第二种思路是把两个链表的值分别存在存在两个列表里面,因为公共节点后两个链表的节点是相同的,我们可以把两个列表的节点pop出来,如果两个节点的值不相同的话,那么他们的下一个节点就是第一个公共节点。

# -*- coding:utf-8 -*- # class ListNode: # def __init__(self, x): # self.val = x # self.next = None class Solution: def FindFirstCommonNode(self, pHead1, pHead2): # write code here ''' def findNode(longTemp, shortHead, longHead): k = 0 while longTemp: longTemp = longTemp.next k += 1 shortTemp = shortHead longTemp = longHead for i in range(k): longTemp = longTemp.next while shortTemp != longTemp: shortTemp = shortTemp.next longTemp = longTemp.next return shortTemp pTemp1 = pHead1 pTemp2 = pHead2 while pTemp1 and pTemp2: if pTemp1 == pTemp2: return pTemp2 pTemp1 = pTemp1.next pTemp2 = pTemp2.next if pTemp1: return findNode(pTemp1, pHead2, pHead1) if pTemp2: return findNode(pTemp2, pHead1, pHead2) ''' listA, listB = [], [] if not pHead2 and not pHead1: return None while pHead1: listA.append(pHead1) pHead1 = pHead1.next while pHead2: listB.append(pHead2) pHead2 = pHead2.next length = min(len(listB), len(listA)) temp=None for i in range(length): nodeA = listA.pop() nodeB = listB.pop() if nodeA == nodeB: temp = nodeA else: break return temp

37、数字在排序数组中出现的次数

题目描述:统计一个数字在排序数组中出现的次数。

思路:这个数组要是有序数组,才能用二分法来做。利用二分法,寻找第一个和最后一个出现的k。

# -*- coding:utf-8 -*- class Solution: def GetNumberOfK(self, data, k): # write code here if not data : return 0 def getfirst(data,k): length = len(data) index1 = 0 index2 = length - 1 while index1 index1 and data[mid - 1] != k) or mid == index1: return mid else: index2 = mid - 1 elif data[mid] > k: index2 = mid - 1 else: index1 = mid + 1 return -1 def getend(data,k): length = len(data) index1 = 0 index2 = length - 1 while index1 <= index2: mid = (index2 - index1) // 2 + index1 if data[mid] == k : if (mid k: index2 = mid - 1 else: index1 = mid + 1 return -1 first = getfirst(data,k) end = getend(data,k) if first > -1 and end >-1 : return end - first + 1 else: return 0

38、二叉树的深度

题目描述:输入一棵二叉树,求该树的深度。从根结点到叶结点依次经过的结点(含根、叶结点)形成树的一条路径,最长路径的长度为树的深度。

思路:用层次遍历和递归都可以。

# -*- coding:utf-8 -*- # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def TreeDepth(self, pRoot): # write code here ''' if not pRoot: return 0 left = self.TreeDepth(pRoot.left) right = self.TreeDepth(pRoot.right) return max(left, right) + 1 ''' if not pRoot: return 0 tempList = [pRoot] d, count = 0, 0 nowLen = len(tempList) while tempList: temp = tempList.pop(0) count += 1 if temp.left: tempList.append(temp.left) if temp.right: tempList.append(temp.right) if count == nowLen: d += 1 count = 0 nowLen = len(tempList) return d

39、平衡二叉树

题目描述:输入一棵二叉树,判断该二叉树是否是平衡二叉树。 在这里,我们只需要考虑其平衡性,不需要考虑其是不是排序二叉树。

思路:平衡二叉树的特点是左右子树的深度差不超过1,我们只要算左右子树的深度就好了

# -*- coding:utf-8 -*- # class TreeNode: # def __init__(self, x): # self.val = x # self.left = None # self.right = None class Solution: def IsBalanced_Solution(self, pRoot): # write code here def TreeDepth(pRoot): if not pRoot: return 0 left = TreeDepth(pRoot.left) right = TreeDepth(pRoot.right) return max(left, right) + 1 if not pRoot: return True p_left = TreeDepth(pRoot.left) p_right = TreeDepth(pRoot.right) ret = abs(p_left - p_right) return True if ret <= 1 else False

40、数组中只出现一次的数字

题目描述:一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

思路:首先:位运算中异或的性质:两个相同数字异或=0,一个数和0异或还是它本身。当只有一个数出现一次时,我们把数组中所有的数,依次异或运算,最后剩下的就是落单的数,因为成对儿出现的都抵消了。

依照这个思路,我们来看两个数(我们假设是AB)出现一次的数组。我们首先还是先异或,剩下的数字肯定是A、B异或的结果,这个结果的二进制中的1,表现的是A和B的不同的位。我们就取第一个1所在的位数,假设是第3位,接着把原数组分成两组,分组标准是第3位是否为1。如此,相同的数肯定在一个组,因为相同数字所有位都相同,而不同的数,肯定不在一组。然后把这两个组按照最开始的思路,依次异或,剩余的两个结果就是这两个只出现一次的数字。

|按位或,&按位与, ^ 按位异或

# -*- coding:utf-8 -*- class Solution: # 返回[a,b] 其中ab是出现一次的两个数字 def FindNumsAppearOnce(self, array): # write code here if len(array) > 1 count += 1 temp = 1 << count firstNum = None secondNum = None for num in array: if num&temp == 0: if firstNum == None: firstNum = num else: firstNum = firstNum ^ num else: if secondNum == None: secondNum = num else: secondNum = secondNum ^ num return firstNum, secondNum

41、和为S的连续正数序列

题目描述:小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,20,21,22。现在把问题交给你,你能不能也很快的找出所有和为S的连续正数序列? Good Luck!

输出描述:输出所有和为S的连续正数序列。序列内按照从小至大的顺序,序列间按照开始数字从小到大的顺序

思路:1、直接遍历1-n找出符合条件的序列。 2、双指针技术,就是相当于有一个窗口,窗口的左右两边就是两个指针 2、根据窗口内值之和来确定窗口的位置和宽度。 

# -*- coding:utf-8 -*- class Solution: def FindContinuousSequence(self, tsum): # write code here # first solution ''' if tsum < 3: return [] ret = [] for i in range(1, tsum): tempSum = 0 tempArrayList = [] while tempSum < tsum: tempSum += i tempArrayList.append(i) i += 1 if tempSum == tsum: ret.append(tempArrayList) return ret ''' # second solution if tsum < 3: return [] ret = [] leftPointer = 1 rightPointer = 2 tempSum = leftPointer + rightPointer while rightPointer < tsum: if tempSum tsum: tempSum -= leftPointer leftPointer += 1 else: tempArrayList = [] for i in range(leftPointer, rightPointer+1): tempArrayList.append(i) ret.append(tempArrayList) rightPointer += 1 tempSum += rightPointer return ret

42、和为S的两个数字

题目描述:输入一个递增排序的数组和一个数字S,在数组中查找两个数,使得他们的和正好是S,如果有多对数字的和等于S,输出两个数的乘积最小的。

思路:1、遍历数组。2、使用双指针,因为是递增数组,乘积最小的两个数肯定是最外围的两个数。

# -*- coding:utf-8 -*- class Solution: def FindNumbersWithSum(self, array, tsum): # write code here # first solution ''' a = None b = None muli = None for i in array: tempA = i tempB = tsum - tempA if tempB in array: if muli == None or muli > tempA * tempB: a = tempA b = tempB muli = a * b if a > b: a, b = b, a return [] if a == None else [a, b] ''' leftPointer = 0 rightPointer = len(array) - 1 ret = [] while leftPointer < rightPointer: tempSum = array[leftPointer] + array[rightPointer] if tempSum tsum: rightPointer -= 1 else: ret.append(array[leftPointer]) ret.append(array[rightPointer]) break return ret

43、左旋转字符串

题目描述:汇编语言中有一种移位指令叫做循环左移(ROL),现在有个简单的任务,就是用字符串模拟这个指令的运算结果。对于一个给定的字符序列S,请你把其循环左移K位后的序列输出。例如,字符序列S=”abcXYZdef”,要求输出循环左移3位后的结果,即“XYZdefabc”。是不是很简单?OK,搞定它!

思路:列表切片。

# -*- coding:utf-8 -*- class Solution: def LeftRotateString(self, s, n): # write code here return s[n:] + s[:n]

44、翻转单词顺序列

题目描述:牛客最近来了一个新员工Fish,每天早晨总是会拿着一本英文杂志,写些句子在本子上。同事Cat对Fish写的内容颇感兴趣,有一天他向Fish借来翻看,但却读不懂它的意思。例如,“student. a am I”。后来才意识到,这家伙原来把句子单词的顺序翻转了,正确的句子应该是“I am a student.”。Cat对一一的翻转这些单词顺序可不在行,你能帮助他么?

# -*- coding:utf-8 -*- class Solution: def ReverseSentence(self, s): # write code here if not s: return '' words = s.split(" ") words.reverse() return ' '.join(w for w in words) ''' return ' '.join(s.split(" ")[::-1]) '''

45、扑克牌顺子

题目描述: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。

思路:题意大概就是,给定五张牌,数值范围是0-13其中0可变为1-13中任意一个数字。你要判断的是这五张牌是否为连续的五个数字。

# -*- coding:utf-8 -*- class Solution: def IsContinuous(self, numbers): # write code here if len(numbers) != 5: return False maxNum = -1 minNum = float("inf") for i in numbers: if i != 0: if i > maxNum: maxNum = i if i 4: return False s = [num for num in range(minNum, maxNum + 1)] if len(s) + countZero < 5: return False count = 0 for i in numbers: if i != 0: if i in s: count += 1 return True if count + countZero == 5 else False

46、孩子们的游戏 ***

题目描述:

每年六一儿童节,牛客都会准备一些小礼物去看望孤儿院的小朋友,今年亦是如此。HF作为牛客的资深元老,自然也准备了一些小游戏。其中,有个游戏是这样的:首先,让小朋友们围成一个大圈。然后,他随机指定一个数m,让编号为0的小朋友开始报数。每次喊到m-1的那个小朋友要出列唱首歌,然后可以在礼品箱中任意的挑选礼物,并且不再回到圈中,从他的下一个小朋友开始,继续0...m-1报数....这样下去....直到剩下最后一个小朋友,可以不用表演,并且拿到牛客名贵的“名侦探柯南”典藏版(名额有限哦!!^_^)。请你试着想下,哪个小朋友会得到这份礼品呢?(注:小朋友的编号是从0到n-1) 如果没有小朋友,请返回-1

思路:
用数学归纳法推导出递推公式,设有n个人(编号0~(n-1)),从0开始报数,报到(m-1)的退出,剩下的人继续从0开始报数。令f[i]表示i个人时最后胜利者的编号,则有递推公式:
f[1]=0;
f[i]=(f[i-1]+m)%i; (i>1)

# -*- coding:utf-8 -*- class Solution: def LastRemaining_Solution(self, n, m): # write code here # write code here #通过推导公式可得 f(n) = (f(n-1)+m)%n if n < 1 or m < 1: return -1 #只有一个人的时候,说明要找的就是这一个人。那么就返回下标0 编号。 if n==1: return 0 value = 0 #时间复杂度 o(n) #从 2 开始 一直到 n 个小朋友 来循环,n 个数,所以为 n+1 for index in range(2,n+1): #现在数到的 m-1 这个值 的索引。对应上上面的公式。



剑指offer offer

需要 登录 后方可回复, 如果你还没有账号请 注册新账号