Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

更改面试题5 替换空格算法 #17

Open
wants to merge 22 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
002c2e2
更改面试题5 替换空格算法
Einstellung May 4, 2019
34c193c
更新面试题4指向的URL
Einstellung May 4, 2019
a72bd74
Update README.md
Einstellung May 4, 2019
2743c34
增加递归调用实现
Einstellung May 5, 2019
0d1d4e0
Merge branch 'master' of github.com:Einstellung/AlgorithmsByPython
Einstellung May 5, 2019
a65850e
修改面试题5指向链接
Einstellung May 5, 2019
7df60c9
添加新题更改一下排序
Einstellung May 6, 2019
7a518a9
更改二叉树下一个节点代码
Einstellung May 6, 2019
4c8aef5
添加第八题代码索引
Einstellung May 6, 2019
5ef63c6
更改两个队列实现栈,代码更简洁
Einstellung May 6, 2019
15659b2
Merge branch 'master' of github.com:Einstellung/AlgorithmsByPython
Einstellung May 6, 2019
d3eeb41
更改两个队列实现栈指向链接
Einstellung May 7, 2019
7f6ac1b
菲波那切数列代码调整
Einstellung May 7, 2019
4128e5f
Update README.md
Einstellung May 7, 2019
0ca4d3a
Merge branch 'master' of github.com:Einstellung/AlgorithmsByPython
Einstellung May 7, 2019
734b0d1
Update README.md
Einstellung May 7, 2019
50edaf6
添加矩形覆盖问题指向链接
Einstellung May 9, 2019
101fdd2
更改代码,快排算法变得更简洁
Einstellung May 12, 2019
244bc06
Merge branch 'master' of github.com:Einstellung/AlgorithmsByPython
Einstellung May 12, 2019
caa155e
更改快排指向链接
Einstellung May 12, 2019
4d25c56
更改旋转数组最小数字,代码更简洁
Einstellung May 14, 2019
954f541
更改第11题指向链接
Einstellung May 15, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 25 additions & 33 deletions QuickSort.py
Original file line number Diff line number Diff line change
@@ -1,46 +1,38 @@
# coding: utf-8

def quickSort(alist):
quickSortHelper(alist, 0, len(alist)-1)

quickSortHelper(alist, 0, len(alist) - 1)
def quickSortHelper(alist, first, last):
if first < last:
splitPoint = partition(alist, first, last)

quickSortHelper(alist, first, splitPoint-1)
quickSortHelper(alist, splitPoint+1, last)



def partition(alist, first, last):
pivotvlue = alist[first]

leftmark = first+1
base = alist[first]



leftmark = first
rightmark = last
done = False

while not done:
while leftmark <= rightmark and alist[leftmark] <= pivotvlue: # bugfix: 先比较index, 不然数组会越界

while leftmark < rightmark: # 要求左指针必须小于等于右指针,之所以没有等号是因为,在最后一次指针移动的时候就会取等,
# 不满足小于条件的时候其实已经取等了
if alist[leftmark] <= base:
leftmark += 1
while rightmark >= leftmark and alist[rightmark] >= pivotvlue:
if alist[rightmark] >= base:
rightmark -= 1

if leftmark > rightmark:
done = True
else:

else: # 当左右指针都停止的时候,交换左右指针所对应的值
alist[leftmark], alist[rightmark] = alist[rightmark], alist[leftmark]

# 当左指针和右指针重合的时候,交换右指针对应的值和base对应的值
alist[rightmark], alist[first] = alist[first], alist[rightmark]
return rightmark


return rightmark # rightmark是作为递归排序的标记,所以返回。最后输出alist就是直接排序排好的


alist = [54,26,93,17,77,31,44,55,20]
alist2 = [1]
quickSort(alist2)
print(alist2)


if __name__ == "__main__":
test_data = [3,2,111,3,-1,0,0,1,0,2,4]

res_stable = sorted(test_data)
quickSort(test_data)
print(test_data)
print(res_stable)
assert all(map(lambda x: x[0] == x[1], zip(res_stable, test_data)))
quickSort(alist)
print(alist)
22 changes: 12 additions & 10 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@

[队列](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Queue.py)

[快排](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/QuickSort.py)
[快速排序](https://github.com/Einstellung/AlgorithmsByPython/blob/master/QuickSort.py)

[基数排序](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/RadixSort.py)

Expand All @@ -67,19 +67,23 @@

[面试题2:实现Singleton模式](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/Singleton.py)

[面试题3:二维数组中的查找](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E4%BA%8C%E7%BB%B4%E6%95%B0%E7%BB%84%E6%9F%A5%E6%89%BE.py):对于在一个每一行从左到右依次递增,每一列从上到下依次递增的二维数组查找一个元素,可以选择从数组左上角开始查找array[i]\[j],如果目标元素大于array[i]\[j],i+=1,如果元素小于array[i]\[j],j-=1,依次循环直至找到这个数。
[面试题4:二维数组中的查找](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E4%BA%8C%E7%BB%B4%E6%95%B0%E7%BB%84%E6%9F%A5%E6%89%BE.py):对于在一个每一行从左到右依次递增,每一列从上到下依次递增的二维数组查找一个元素,可以选择从数组左上角开始查找array[i]\[j],如果目标元素大于array[i]\[j],i+=1,如果元素小于array[i]\[j],j-=1,依次循环直至找到这个数。

[面试题4:替换空格](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC.py):如果直接每次遇到空格添加'%20',那么空格后面的数字就需要频繁向后移动。遇到这种移动问题,我们可以尝试先给出最终需要的长度,然后从后向前扫描,同时给定两个指针来保证定位。**逆向思维**
[面试题5:替换空格](https://github.com/Einstellung/AlgorithmsByPython/blob/master/Target%20Offer/%E6%9B%BF%E6%8D%A2%E7%A9%BA%E6%A0%BC.py):如果直接每次遇到空格添加'%20',那么空格后面的数字就需要频繁向后移动。遇到这种移动问题,我们可以尝试先给出最终需要的长度,然后从后向前扫描,同时给定两个指针来保证定位。**逆向思维**

[面试题5:从头到尾打印链表](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E5%8F%8D%E5%90%91%E6%89%93%E5%8D%B0%E9%93%BE%E8%A1%A8.py):从头到尾遍历链表,并用一个栈存储每个结点的值,之后出栈输出值即可。
[面试题6:从头到尾打印链表](https://github.com/Einstellung/AlgorithmsByPython/blob/master/Target%20Offer/%E5%8F%8D%E5%90%91%E6%89%93%E5%8D%B0%E9%93%BE%E8%A1%A8.py):从头到尾遍历链表,并用一个栈存储每个结点的值,之后出栈输出值即可。

[面试题6:重建二叉树](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E9%87%8D%E5%BB%BA%E4%BA%8C%E5%8F%89%E6%A0%91.py):利用二叉树前序遍历和中序遍历的特性。前序遍历的第一个值一定为根节点,对应于中序遍历中间的一个点。在中序遍历序列中,这个点左侧的均为根的左子树,这个点右侧的均为根的右子树。这时可以利用递归,分别取前序遍历[1:i+1]和中序遍历的[:i]对应与左子树继续上一个过程,取前序遍历[i+1:]和中序遍历[i+1]对应于右子树继续上一个过程,最终得以重建二叉树。
[面试题7:重建二叉树](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E9%87%8D%E5%BB%BA%E4%BA%8C%E5%8F%89%E6%A0%91.py):利用二叉树前序遍历和中序遍历的特性。前序遍历的第一个值一定为根节点,对应于中序遍历中间的一个点。在中序遍历序列中,这个点左侧的均为根的左子树,这个点右侧的均为根的右子树。这时可以利用递归,分别取前序遍历[1:i+1]和中序遍历的[:i]对应与左子树继续上一个过程,取前序遍历[i+1:]和中序遍历[i+1]对应于右子树继续上一个过程,最终得以重建二叉树。

[面试题7:用两个栈实现队列](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E7%94%A8%E4%B8%A4%E4%B8%AA%E6%A0%88%E5%AE%9E%E7%8E%B0%E9%98%9F%E5%88%97.py):需要两个栈Stack1和Stack2,push的时候直接push进Stack1。pop需要判断Stack1和Stack2中元素的情况,Stack1空的话,直接从Stack2 pop,Stack1不空的话,把Stack1的元素push进入Stack2,然后pop Stack2的值。[推广:用两个队列实现栈](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E7%94%A8%E4%B8%A4%E4%B8%AA%E9%98%9F%E5%88%97%E5%AE%9E%E7%8E%B0%E6%A0%88.py)
[面试题8:二叉树的下一个结点](https://github.com/Einstellung/AlgorithmsByPython/blob/master/Target%20Offer/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E4%B8%8B%E4%B8%80%E4%B8%AA%E7%BB%93%E7%82%B9.py):三种情况:当前节点有右子树的话,当前节点的下一个结点是右子树中的最左子节点;当前节点无右子树但是是父节点的左子节点,下一个节点是当前结点的父节点;当前节点无右子树而且是父节点的右子节点,则一直向上遍历,直到找到最靠近的一个祖先节点pNode,pNode是其父节点的左子节点,那么输入节点的下一个结点就是pNode的父节点。

[面试题9:用两个栈实现队列](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E7%94%A8%E4%B8%A4%E4%B8%AA%E6%A0%88%E5%AE%9E%E7%8E%B0%E9%98%9F%E5%88%97.py):需要两个栈Stack1和Stack2,push的时候直接push进Stack1。pop需要判断Stack1和Stack2中元素的情况,Stack1空的话,直接从Stack2 pop,Stack1不空的话,把Stack1的元素push进入Stack2,然后pop Stack2的值。[推广:用两个队列实现栈](https://github.com/Einstellung/AlgorithmsByPython/blob/master/Target%20Offer/%E7%94%A8%E4%B8%A4%E4%B8%AA%E9%98%9F%E5%88%97%E5%AE%9E%E7%8E%B0%E6%A0%88.py)

[面试题10:斐波那契数列](https://github.com/Einstellung/AlgorithmsByPython/blob/master/Target%20Offer/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97.py):如何不使用递归实现斐波那契数列,需要把前面两个数字存入在一个数组中。斐波那契数列的变形有很多,如[青蛙跳台阶](https://github.com/Einstellung/AlgorithmsByPython/blob/master/Target%20Offer/%E9%9D%92%E8%9B%99%E8%B7%B3%E5%8F%B0%E9%98%B6.py),一次跳一个或者两个;铺瓷砖问题。[**变态青蛙跳**](https://github.com/Einstellung/AlgorithmsByPython/blob/master/Target%20Offer/%E5%8F%98%E6%80%81%E9%9D%92%E8%9B%99%E8%B7%B3%E5%8F%B0%E9%98%B6.py),每次至少跳一个,至多跳n个,一共有f(n)=2<sup>n-1</sup>种跳法。考察数学建模的能力。以及[矩形覆盖问题](https://blog.csdn.net/Einstellung/article/details/90020345)

[面试题11:旋转数组的最小数字](https://github.com/Einstellung/AlgorithmsByPython/blob/master/Target%20Offer/%E6%97%8B%E8%BD%AC%E6%95%B0%E7%BB%84%E7%9A%84%E6%9C%80%E5%B0%8F%E6%95%B0%E5%AD%97.py):二分查找的变形,注意到旋转数组的首元素肯定不小于旋转数组的尾元素,设置中间点。如果中间点大于首元素,说明最小数字在后面一半,如果中间点小于尾元素,说明最小数字在前一半。依次循环。同时,当一次循环中首元素小于尾元素,说明最小值就是首元素。但是当首元素等于尾元素等于中间值,只能在这个区域顺序查找。

[面试题8:旋转数组的最小数字](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E6%97%8B%E8%BD%AC%E6%95%B0%E7%BB%84%E7%9A%84%E6%9C%80%E5%B0%8F%E6%95%B0%E5%AD%97.py):二分查找的变形,注意到旋转数组的首元素肯定不小于旋转数组的尾元素,设置中间点。如果中间点大于首元素,说明最小数字在后面一半,如果中间点小于尾元素,说明最小数字在前一半。依次循环。同时,当一次循环中首元素小于尾元素,说明最小值就是首元素。但是当首元素等于尾元素等于中间值,只能在这个区域顺序查找。

[面试题9:斐波那契数列](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E6%96%90%E6%B3%A2%E9%82%A3%E5%A5%91%E6%95%B0%E5%88%97.py):如何不使用递归实现斐波那契数列,需要把前面两个数字存入在一个数组中。斐波那契数列的变形有很多,如青蛙跳台阶,一次跳一个或者两个;铺瓷砖问题。**变态青蛙跳**,每次至少跳一个,至多跳n个,一共有f(n)=2<sup>n-1</sup>种跳法。考察数学建模的能力。

[面试题10:二进制中1的个数](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E4%BA%8C%E8%BF%9B%E5%88%B6%E4%B8%AD1%E7%9A%84%E4%B8%AA%E6%95%B0.py):注意到每个**非零**整数n和n-1进行按位与运算,整数n的二进制数中最右边的1就会变成0,那么二进制数中的1的个数就会减少一个,因此可以利用一个循环,使得 n = n&(n-1) ,计算经过几次运算减少到0,就是有几个1。注意:书中给了另外两种方法,分别是原始n左移一位和右移一位的方法,因为Python不会出现整数溢出的情况,这里就不再考虑着两种方法。扩展:判断一个数值是不是2得整数次方,如果是的话,这个数的二进制数中有且只有一个1,那么这个数n会有 n&(n-1) == 0。或者求两个整数m和n需要改变m二进制中的多少位才能得到n,可以先做 m^n 的异或运算,然后求这个数中有多少个1。

Expand Down Expand Up @@ -183,8 +187,6 @@

[面试题57:删除链表中重复的结点](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E5%88%A0%E9%99%A4%E9%93%BE%E8%A1%A8%E4%B8%AD%E9%87%8D%E5%A4%8D%E7%9A%84%E7%BB%93%E7%82%B9.py):我们需要设置一个指针preNode,preNode最开始为None,然后设置两个指针,pNode指向当前节点,pNext指向pNode下一个结点,⓵如果pNext不为空而且pNext的值等于pNode的值,那么就说明出现了重复数字的结点,就需要删除,然后从pNode开始遍历,如果结点值等于前面那个重复值,继续遍历。当遍历到None或者不同值结点的时候,这时候需要判断preNode结点,如果preNode结点为None,就说明我们刚才的重复结点是从整个链表的头结点开始重复的,就直接把pHead设置为当前结点,pNode也设置为当前结点。反之,如果preNode不为None,直接把preNode的下一个指针指向当前节点,pNode指向preNode即可;⓶如果pNext为空或者pNext的值不等于pNode的值,说明当前的这个pNode和后面的值不重复,直接令preNode = pNode,pNode指向下一个结点即可。

[面试题58:二叉树的下一个结点](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E4%BA%8C%E5%8F%89%E6%A0%91%E7%9A%84%E4%B8%8B%E4%B8%80%E4%B8%AA%E7%BB%93%E7%82%B9.py):三种情况:当前节点有右子树的话,当前节点的下一个结点是右子树中的最左子节点;当前节点无右子树但是是父节点的左子节点,下一个节点是当前结点的父节点;当前节点无右子树而且是父节点的右子节点,则一直向上遍历,直到找到最靠近的一个祖先节点pNode,pNode是其父节点的左子节点,那么输入节点的下一个结点就是pNode的父节点。

[面试题59:对称的二叉树](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E5%AF%B9%E7%A7%B0%E7%9A%84%E4%BA%8C%E5%8F%89%E6%A0%91.py):分为递归和非递归的两种方式,思想是一样的。主要就是把叶子节点的None节点也加入到遍历当中。按照前序遍历二叉树,存入一个序列中。然后按照和前序遍历对应的先父节点,然后右子节点,最后左子节点遍历二叉树,存入一个序列。如果前后两个序列相等,那么说明二叉树是对称的。

[面试题60:把二叉树打印成多行](https://github.com/Jack-Lee-Hiter/AlgorithmsByPython/blob/master/Target%20Offer/%E6%8A%8A%E4%BA%8C%E5%8F%89%E6%A0%91%E6%89%93%E5%8D%B0%E6%88%90%E5%A4%9A%E8%A1%8C.py):引入两个队列。首先把当前层的节点存入到一个队列queue1中,然后遍历当前队列queue1,在遍历的过程中,如果节点有左子树或右子树,依次存入另一个队列queue2。然后遍历队列queue2,如此往复。
Expand Down
35 changes: 17 additions & 18 deletions Target Offer/二叉树的下一个结点.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,24 @@ def __init__(self, x):
self.val = x
self.left = None
self.right = None
self.next = None
self.father = None #指向父节点的指针
class Solution:
def GetNext(self, pNode):
if pNode == None:
return
pNext = None
if pNode.right != None:
pRight = pNode.right
while pRight.left != None:
pRight = pRight.left
pNext= pRight
elif pNode.next != None:
pCurrent = pNode
pParent = pCurrent.next
while pParent != None and pCurrent == pParent.right:
pCurrent = pParent
pParent = pCurrent.next
pNext = pParent
return pNext
def GetNext(self, nNode):
if not nNode:
return None

if nNode.right: #如果有右子树
while nNode.left:
nNode = nNode.left
return nNode

else: # 如果没有右子树
while nNode.father: # 不停地去找父节点的左子节点是该节点的情况
if nNode == nNode.father.left:
return nNode.father
nNode = nNode.father

return None #都不满足情况,最后返回为空,是中序遍历的结尾

class Solution2:
def GetNext(self, pNode):
Expand Down
9 changes: 9 additions & 0 deletions Target Offer/反向打印链表.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,15 @@ def printListFromTailToHead(self, listNode):
head = head.next
return l

# 添加使用递归调用的方法,堆栈和递归是一样的
def recursive(self, listNode):
if listNode.val != None:
if listNode.next != None:
self.recursive(listNode.next)

print(listNode.val)


node1 = ListNode(10)
node2 = ListNode(11)
node3 = ListNode(13)
Expand Down
20 changes: 20 additions & 0 deletions Target Offer/变态青蛙跳台阶.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
'''
和青蛙跳台阶问题类似,再做出一定程度扩展。

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

这个问题写起来就很简单了,由数学归纳我们可以知道,一共有2^(n-1)种方案,所以就可以直接写代码
'''

class Solution:
def jumpFloor2(self, number):
if number == 0:
return 0

ans = 1
if number == 1:
return 1
else:
for i in range(1, number):
ans = 2*ans
return ans
22 changes: 3 additions & 19 deletions Target Offer/斐波那契数列.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,13 @@

# -*- coding:utf-8 -*-
class Solution:
def Fibonacci(self, n):
def fibonacci(self, n):
tempArray = [0, 1]

if n >= 2:
for i in range(2, n+1):
tempArray[i%2] = tempArray[0] + tempArray[1]
return tempArray[n%2]
# 青蛙跳台阶, 每次可以跳1级或2级
def jumpFloor(self, number):
# write code here
tempArray = [1, 2]
if number >= 3:
for i in range(3, number + 1):
tempArray[(i + 1) % 2] = tempArray[0] + tempArray[1]
return tempArray[(number + 1) % 2]

def jumpFloorII(self, number):
ans = 1
if number >= 2:
for i in range(number-1):
ans = ans * 2
return ans

test = Solution()
print(test.Fibonacci(100))
print(test.jumpFloor(3))
print(test.jumpFloorII(2))
print(test.fibonacci(100))
Loading