面试过程中,大概率会碰到的数据结构和算法题

版权声明:本文为博主原创文章,转载时请注明! https://blog.csdn.net/u013018618/article/details/80086992

数据结构和算法模拟器:LeetCode

闲扯

本人4月份的求职过程中,经历了20多场面试,碰到了形形色色的面试官,也遇到了各种各样的面试内容,这里记录一下遇到的常见数据结构和算法题,仅供参考,娱乐使用,不保证算法正确。偷笑

常见的数据结构和算法题

主要包括:排序(冒泡、快排、选择排序、插入排序、希尔排序、归并排序等)、链表(单链表、双链表、单链表反转)、二叉树、红黑树、二分法、图、约瑟夫环、栈和队列、包含数字和字母的字符串排序、找出序列中出现次数最多的元素的方法、判断一个整数是否是2的整数次幂、最长递增子序列等。这里以python语言实现为例。

排序算法复杂度

排序法
最差时间分析
平均时间复杂度
稳定度
空间复杂度
冒泡排序
O(n^2)
O(n^2)
稳定
O(1)
快速排序
O(n^2)
O(n*log2n)
不稳定
O(log2n)~O(n)
选择排序
O(n^2)
O(n^2)
稳定
O(1)
二叉树排序
O(n^2)
O(n*log2n)
不一顶
O(n)
插入排序
O(n^2)
O(n^2)
稳定
O(1)
堆排序
O(n*log2n)
O(n*log2n)
不稳定
O(1)
希尔排序
O
O
不稳定
O(1)

排序

1.冒泡排序

描述:每次循环,如果前面的数大于后面的数,就进行交换。

def bubble_sort(lists):
count = len(lists)
for i in range(count):
for j in range(i + 1, count):
if lists[i] > lists[j]:
lists[i], lists[j] = lists[j], lists[i]
return lists

2.快速排序

描述:递归调用,比列表第一个元素小的所有元素列表递归调用;第一个元素;比列表第一个元素大的所有元素列表递归调用

def quick_sort(L):
if len(L) <= 1: return L
return qsort([lt for lt in L[1:] if lt < L[0]]) \
             + L[0:1] + \
         qsort([ge for ge in L[1:] if ge >= L[0]])

3.归并排序

        归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
        归并过程为:比较a[i]和a[j]的大小,若a[i]≤a[j],则将第一个有序表中的元素a[i]复制到r[k]中,并令i和k分别加上1;否则将第二个有序表中的元素a[j]复制到r[k]中,并令j和k分别加上1,如此循环下去,直到其中一个有序表取完,然后再将另一个有序表中剩余的元素复制到r中从下标k到下标t的单元。归并排序的算法我们通常用递归实现,先把待排序区间[s,t]以中点二分,接着把左边子区间排序,再把右边子区间排序,最后把左区间和右区间用一次归并操作合并成有序的区间[s,t]。

def merge(left, right):
i, j = 0, 0
result = []
while i < len(left) and j < len(right):
if left[i] <= right[j]:
result.append(left[i])
i += 1
else:
result.append(right[j])
j += 1
result += left[i:]
result += right[j:]

        return result

def merge_sort(lists):
# 归并排序
if len(lists) <= 1:
    return lists
num = len(lists) / 2
left = merge_sort(lists[:num])
right = merge_sort(lists[num:])
return merge(left, right)

4.选择排序

        对于一组关键字{K1,K2,…,Kn}, 首先从K1,K2,…,Kn中选择最小值,假如它是 Kz,则将Kz与 K1对换;然后从K2,K3,… ,Kn中选择最小值 Kz,再将Kz与K2对换。如此进行选择和调换n-2趟,第(n-1)趟,从Kn-1、Kn中选择最小值 Kz将Kz与Kn-1对换,最后剩下的就是该序列中的最大值,一个由小到大的有序序列就这样形成。

def selection_sort(L):
length = len(L)
for i in range(length):
min = i
for j in range(i + 1, length):
if L[j] < L[min]:
min = j
L[i], L[min] = L[min], L[i]
return L

5.插入排序

        设有一组关键字{ K 1 , K 2 ,…, K n };排序开始就认为 K 1 是一个有序序列;让 K 2 插入上述表长为 1 的有序序列,使之成为一个表长为 2 的有序序列;然后让 K 3 插入上述表长为 2 的有序序列,使之成为一个表长为 3 的有序序列;依次类推,最后让 K n 插入上述表长为 n-1 的有序序列,得一个表长为 n 的有序序列。

def insertion_sort(L):
for i in range(1, len(L)):
tmp = L[i]
j = i
while j > 0 and L[j - 1] > tmp:
L[j] = L[j - 1]
j -= 1
L[j] = tmp
return L

6.希尔排序

        希尔排序(Shell Sort)是插入排序的一种。也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本。希尔排序是非稳定排序算法。希尔排序是把记录按下标的一定增量分组,对每组使用直接插入排序算法排序;随着增量逐渐减少,每组包含的关键词越来越多,当增量减至1时,整个文件恰被分成一组,算法便终止。

def shell_sort(lists):
# 希尔排序
count = len(lists)
step = 2
group = count / step
while group > 0:
for i in range(0, group):
j = i + group
while j < count:
k = j - group
key = lists[j]
while k >= 0:
if lists[k] > key:
lists[k + group] = lists[k]
lists[k] = key
k -= group
j += group
group /= step
return lists


链表

1.单链表实现

        python实现链表依赖于类生成的实例,每个节点都是一个对象,组合在一起形成一个完整链表。对于node类只需关注两点:data 和 pnext。对于linked_list需要关心的:head,默认是node; length,列表的长度。

class Node:
def __init__(self, data):
"""
node的初始化
:param data: 节点的数据
"""
self.data = data
self.pnext = None
def __repr__(self):
return str(self.data)

class LinkedList:
def __init__(self):
"""
Linked list 的初始化
"""
self.length = 0
self.head = None

def is_empty(self):
"""
判断该链表是否为空
:return: boolean
"""
return self.length == 0

def append(self, this_node):
"""
在链表末添加node/值,如果是node对象直接添加,否则先转换为node对象
:param this_node: 数据或者node对象
:return: None
"""
if isinstance(this_node, Node):
pass
else:
this_node = Node(data=this_node)
if self.is_empty():
# 链表为空的情况将头指针指向当前node
self.head = this_node
else:
node = self.head
while node.pnext:
node = node.pnext
node.pnext = this_node
self.length += 1

def insert(self, value, index):
"""
链表的插入操作
:param value: 要插入的值
:param index: 位置
:return: None
"""
if type(index) is int:
if index > self.length:
# 索引值超出范围直接提示并且退出
print("Index value is out of range.")
return
else:
# 获得当前node对象和head
this_node = Node(data=value)
current_node = self.head
if index == 0:
# 索引值为0是将
self.head = this_node
this_node.pnext = current_node
return
while index - 1:
current_node = current_node.pnext
index -= 1
# 这两条语句顺序很关键
# 将当前节点与后一个节点拆开,this_node指向后一个节点,前一个节点指向this_node
this_node.pnext = current_node.pnext
current_node.pnext = this_node
self.length += 1
return
else:
print("Index value is not int.")
return

def delete(self, index):
"""
删除链表中某个位置的节点
:param index: 位置索引
:return: None
"""
if type(index) is int:
if index > self.length:
# 索引值超出范围直接提示并且退出
print("Index is out of range.")
return
else:
if index == 0:
self.head = self.head.pnext
else:
current_node = self.head
while index - 1:
current_node = current_node.pnext
index -= 1
current_node.pnext = current_node.pnext.pnext
self.length -= 1
return
else:
print("Index value is not int.")
return

def update(self, value, index):
"""
为链表中某个位置的节点修改值
:param value: 要修改的值
:param index: 位置索引
:return: None
"""
if type(index) is int:
if index > self.length:
# 索引值超出范围直接提示并且退出
print("Index is out of range.")
return
else:
this_node = Node(data=value)
if index == 0:
this_node.pnext = self.head.pnext
self.head = this_node
else:
current_node = self.head
while index - 1:
current_node = current_node.pnext
index -= 1
this_node.pnext = current_node.pnext.pnext
current_node.pnext = this_node
return
else:
print("Index value is not int.")
return

def get_value(self, index):
"""
获取链表中某个位置节点的值
:param index: 位置索引
:return: 该节点值, int or not
"""
if type(index) is int:
if index > self.length:
# 索引值超出范围直接提示并且退出
print("Index is out of range.")
return
else:
if index == 0:
return self.head.data
else:
current_node = self.head
while index - 1:
current_node = current_node.pnext
index -= 1
return current_node.pnext.data
else:
print("Index value is not int.")
return

def get_length(self):
"""
获取链表长度
:return: int
"""
current_node = self.head
if current_node:
i = 1
while current_node.pnext:
current_node = current_node.pnext
i += 1
return i
else:
return 0

def clear(self):
"""
清空链表
:return: None
"""
self.head = None
self.length = 0
print("Clear the linked list finished.")

def print_linked_list(self):
"""
对整个链表的打印
:return: None
"""
if self.is_empty():
print("Linked list's length is 0")
else:
node = self.head
print("Head -->", node.data, end=' ')
while node.pnext:
node = node.pnext
print("-->", node.data, end=' ')
print("--> None. Linked node finished")

if __name__ == '__main__':
node1 = Node(data='node1')
node2 = Node(data='node2')
linked_list = LinkedList()
linked_list.append(node1)
linked_list.append(node2)
linked_list.print_linked_list()
linked_list.insert("sdf", 1)
linked_list.print_linked_list()
# linked_list.delete(0)
linked_list.update(value="update_test", index=2)
linked_list.print_linked_list()
print(linked_list.get_value(index=2))
print(linked_list.get_length())

2.循环链表实现

#链表的节点
class Node(object):
def __init__(self , item ):
self.item = item #节点数值

self.prev = None #用于指向前一个元素
self.next = None #用于指向后一个元素

#双向循环链表
class DoubleCircleLinkList(object):
def __init__(self):
self.__head = None #初始化的时候头节点设为空

#判断链表是否为空,head为None 的话则链表是空的
def is_empty(self):
return self.__head is None

#头部添加元素的方法
def add(self,item):
node = Node(item) #新建一个节点node 里面的值是item
# 如果链表是空的,则node的next和prev都指向自己(因为是双向循环),head指向node
if self.is_empty():
self.__head = node
node.next = node
node.prev = node
# 否则链表不空
else:
node.next = self.__head #node的next设为现在的head
node.prev = self.__head.prev #node的prev 设为现在head的prev
self.__head.prev.next = node #现在head的前一个元素的next设为node
self.__head.prev = node #现在head的前驱 改为node
self.__head = node #更改头部指针

#尾部添加元素方法
def append(self , item):
#如果当前链表是空的 那就调用头部插入方法
if self.is_empty():
self.add(item)
#否则链表不为空
else :
node = Node(item) #新建一个节点node
#因为是双向循环链表,所以head的prev其实就是链表的尾部
node.next = self.__head #node的下一个设为头
node.prev = self.__head.prev #node的前驱设为现在头部的前驱
self.__head.prev.next = node #头部前驱的后继设为node
self.__head.prev = node #头部自己的前驱改为node

#获得链表长度 节点个数
def length(self):
#如果链表是空的 就返回0
if self.is_empty():
return 0
#如果不是空的
else:
cur = self.__head #临时变量cur表示当前位置 初始化设为头head
count = 1 #设一个计数器count,cur每指向一个节点,count就自增1 目前cur指向头,所以count初始化为1
#如果cur.next不是head,说明cur目前不是最后一个元素,那么count就1,再让cur后移一位
while cur.next is not self.__head:
count += 1
cur = cur.next
#跳出循环说明所有元素都被累加了一次 返回count就是一共有多少个元素
return count

#遍历链表的功能
def travel(self):
#如果当前自己是空的,那就不遍历
if self.is_empty():
return
#链表不空
else :
cur = self.__head #临时变量cur表示当前位置,初始化为链表的头部
#只要cur的后继不是头说明cur不是最后一个节点,我们就输出当前值,并让cur后移一个节点
while cur.next is not self.__head:
print( cur.item,end=" " )
cur = cur.next
#当cur的后继是head的时候跳出循环了,最后一个节点还没有打印值 在这里打印出来
print( cur.item )

#置顶位置插入节点
def insert(self, pos , item ):
#如果位置<=0 则调用头部插入方法
if pos <= 0:
self.add(item)
#如果位置是最后一个或者更大 就调用尾部插入方法
elif pos > self.length() - 1 :
self.append(item)
#否则插入位置就是链表中间
else :
index = 0 #设置计数器,用于标记我们后移了多少步
cur = self.__head #cur标记当前所在位置
#让index每次自增1 ,cur后移,当index=pos-1的时候说明cur在要插入位置的前一个元素,这时候停下
while index < pos - 1 :
index += 1
cur = cur.next
#跳出循环,cur在要插入位置的前一个元素,将node插入到cur的后面
node = Node(item) #新建一个节点
node.next = cur.next #node的后继设为cur的后继
node.prev = cur #node的前驱设为cur
cur.next.prev = node #cur后继的前驱改为node
cur.next = node #cur后继改为node

#删除节点操作
def remove(self,item):
#如果链表为空 直接不操作
if self.is_empty():
return
#链表不为空
else:
cur = self.__head #临时变量标记位置,从头开始
#如果头结点就是 要删除的元素
if cur.item == item:
#如果只有一个节点 链表就空了 head设为None
if self.length() == 1:
self.__head = None
#如果多个元素
else:
self.__head = cur.next #头指针指向cur的下一个
cur.next.prev= cur.prev #cur后继的前驱改为cur的前驱
cur.prev.next = cur.next #cur前驱的后继改为cur的后继
#否则 头节点不是要删除的节点 我们要向下遍历
else:
cur = cur.next #把cur后移一个节点
#循环让cur后移一直到链表尾元素位置,期间如果找得到就删除节点,找不到就跳出循环,
while cur is not self.__head:
#找到了元素cur就是要删除的
if cur.item == item:
cur.prev.next = cur.next #cur的前驱的后继改为cur的后继
cur.next.prev = cur.prev #cur的后继的前驱改为cur的前驱
cur = cur.next

#搜索节点是否存在
def search(self , item):
#如果链表是空的一定不存在
if self.is_empty():
return False
#否则链表不空
else:
cur = self.__head #设置临时cur从头开始
# cur不断后移,一直到尾节点为止
while cur.next is not self.__head:
#如果期间找到了就返回一个True 结束运行
if cur.item == item:
return True
cur = cur.next
# 从循环跳出来cur就指向了尾元素 看一下为元素是不是要找的 是就返回True
if cur.item ==item:
return True
#所有元素都不是 就返回False 没找到
return False

if __name__ == "__main__":
dlcl = DoubleCircleLinkList()
print(dlcl.search(7))
dlcl.travel()
dlcl.remove(1)
print(dlcl.length())
print(dlcl.is_empty())
dlcl.append(55)
print(dlcl.search(55))
dlcl.travel()
dlcl.remove(55)
dlcl.travel()
print(dlcl.length())
dlcl.add(3)
print(dlcl.is_empty())
dlcl.travel()
dlcl.add(4)
dlcl.add(5)
dlcl.append(6)
dlcl.insert(-10,1)
dlcl.travel()
print(dlcl.length())
dlcl.remove(6)
dlcl.travel()
print(dlcl.search(7) )
dlcl.append(55)
dlcl.travel()

3.单链表反转

        

        循环反转单链表:循环的方法中,使用pre指向前一个结点,cur指向当前结点,每次把cur->next指向pre即可。

             class ListNode:

def __init__(self,val):
self.val=val;
self.next=None;

def nonrecurse(head): #循环的方法反转链表
if head is None or head.next is None:
return head;
pre=None;
cur=head;
h=head;
while cur:
h=cur;
tmp=cur.next;
cur.next=pre;
pre=cur;
cur=tmp;
return h;

head=ListNode(1); #测试代码
p1=ListNode(2); #建立链表1->2->3->4->None;
p2=ListNode(3);
p3=ListNode(4);
head.next=p1;
p1.next=p2;
p2.next=p3;
p=nonrecurse(head); #输出链表 4->3->2->1->None
while p:
print p.val;
p=p.next;

递归实现单链表反转
class ListNode:
def __init__(self,x):
self.val=x;
self.next=None;

def recurse(head,newhead): #递归,head为原链表的头结点,newhead为反转后链表的头结点
if head is None:
return ;
if head.next is None:
newhead=head;
else :
newhead=recurse(head.next,newhead);
head.next.next=head;
head.next=None;
return newhead;
head=ListNode(1); #测试代码
p1=ListNode(2); # 建立链表1->2->3->4->None
p2=ListNode(3);
p3=ListNode(4);
head.next=p1;
p1.next=p2;
p2.next=p3;
newhead=None;
p=recurse(head,newhead); #输出链表4->3->2->1->None
while p:
print p.val;
p=p.next;


二叉树

        实现功能:树的构造;递归实现先序遍历、中序遍历、后序遍历;堆栈实现先序遍历、中序遍历、后序遍历;队列实现层次遍历

class Node(object):
"""节点类"""
def __init__(self, elem=-1, lchild=None, rchild=None):
self.elem = elem
self.lchild = lchild
self.rchild = rchild

class Tree(object):
"""树类"""
def __init__(self):
self.root = Node()
self.myQueue = []

def add(self, elem):
"""为树添加节点"""
node = Node(elem)
if self.root.elem == -1: # 如果树是空的,则对根节点赋值
self.root = node
self.myQueue.append(self.root)
else:
treeNode = self.myQueue[0] # 此结点的子树还没有齐。
if treeNode.lchild == None:
treeNode.lchild = node
self.myQueue.append(treeNode.lchild)
else:
treeNode.rchild = node
self.myQueue.append(treeNode.rchild)
self.myQueue.pop(0) # 如果该结点存在右子树,将此结点丢弃。

def front_digui(self, root):
"""利用递归实现树的先序遍历"""
if root == None:
return
print root.elem,
self.front_digui(root.lchild)
self.front_digui(root.rchild)

def middle_digui(self, root):
"""利用递归实现树的中序遍历"""
if root == None:
return
self.middle_digui(root.lchild)
print root.elem,
self.middle_digui(root.rchild)

def later_digui(self, root):
"""利用递归实现树的后序遍历"""
if root == None:
return
self.later_digui(root.lchild)
self.later_digui(root.rchild)
print root.elem,

def front_stack(self, root):
"""利用堆栈实现树的先序遍历"""
if root == None:
return
myStack = []
node = root
while node or myStack:
while node: #从根节点开始,一直找它的左子树
print node.elem,
myStack.append(node)
node = node.lchild
node = myStack.pop() #while结束表示当前节点node为空,即前一个节点没有左子树了
node = node.rchild #开始查看它的右子树

def middle_stack(self, root):
"""利用堆栈实现树的中序遍历"""
if root == None:
return
myStack = []
node = root
while node or myStack:
while node: #从根节点开始,一直找它的左子树
myStack.append(node)
node = node.lchild
node = myStack.pop() #while结束表示当前节点node为空,即前一个节点没有左子树了
print node.elem,
node = node.rchild #开始查看它的右子树

def later_stack(self, root):
"""利用堆栈实现树的后序遍历"""
if root == None:
return
myStack1 = []
myStack2 = []
node = root
myStack1.append(node)
while myStack1: #这个while循环的功能是找出后序遍历的逆序,存在myStack2里面
node = myStack1.pop()
if node.lchild:
myStack1.append(node.lchild)
if node.rchild:
myStack1.append(node.rchild)
myStack2.append(node)
while myStack2: #将myStack2中的元素出栈,即为后序遍历次序
print myStack2.pop().elem,

def level_queue(self, root):
"""利用队列实现树的层次遍历"""
if root == None:
return
myQueue = []
node = root
myQueue.append(node)
while myQueue:
node = myQueue.pop(0)
print node.elem,
if node.lchild != None:
myQueue.append(node.lchild)
if node.rchild != None:
myQueue.append(node.rchild)

if __name__ == '__main__':
"""主函数"""
elems = range(10) #生成十个数据作为树节点
tree = Tree() #新建一个树对象
for elem in elems:
tree.add(elem) #逐个添加树的节点

print '队列实现层次遍历:'
tree.level_queue(tree.root)

print '\n\n递归实现先序遍历:'
tree.front_digui(tree.root)
print '\n递归实现中序遍历:'
tree.middle_digui(tree.root)
print '\n递归实现后序遍历:'
tree.later_digui(tree.root)

print '\n\n堆栈实现先序遍历:'
tree.front_stack(tree.root)
print '\n堆栈实现中序遍历:'
tree.middle_stack(tree.root)
print '\n堆栈实现后序遍历:'
tree.later_stack(tree.root)

二分查找

注意边界条件

二分查找的时间复杂度是O(log(n)),最坏情况下的时间复杂度是O(n)。
伪代码:
1.low = 0; high = len(list1]-1 #设置初识查找区间
2.测试查找区间[low, high]是否存在,若不存在,则查找失败;否则
3.取中间mid=(low + high)/2;比较k与list1[mid],有以下三种情况:
3.1 若k<r[mid],则high=mid-1;查找在左半区进行,转2;
3.2 若k>r[mid],则low=mid+1;查找在右半边区进行,转2;
3.3 若k=r[mid],则查找成功,返回记录在表中位置mid;

def binary_search(find, list1) :
low = 0
high = len(list1)
while low <= high :
mid = (low + high) / 2
if list1[mid] == find :
return mid
#左半边
elif list1[mid] > find :
high = mid -1
#右半边
else :
low = mid + 1
#未找到返回-1
return -1



#图的邻接链表表示法
graph = {'A': ['B','C','D','E','F'],
'B': ['C', 'E'],
'C': ['D'],
'D': ['E'],
'E': ['F'],
'F': ['C','G','H'],
'G':['F','H']
'H':['F','G']}

#从图中找出任意一条从起始顶点到终止顶点的路径
def find_path(graph, start, end, path=[]):
if start == end:
print "path", path
return True
if not graph.get(start):
path.pop()
return False
for v in graph[start]:
if v not in path:
path.append(v)
if find_path(graph,v,end,path):
return True
return False

path = []
if find_path(graph, 'A', 'C', path=path):
print(path)
else:
print(1)

#从图中找出从起始顶点到终止顶点的所有路径
import copy
def find_path_all(curr, end, path):
'''
:param curr: 当前顶点
:param end: 要到达的顶点
:param path: 当前顶点的一条父路径
:return:
'''
if curr == end:
path_tmp = copy.deepcopy(path)
path_all.append(path_tmp)
return
if not graph.get(curr):
return
for v in graph[curr]:
#一个顶点在当前递归路径中只能出现一次,否则会陷入死循环。
if v in path:
print("v %s in path %s" %(v, path))
continue
#构造下次递归的父路径
path.append(v)
find_path_all(v,end,path)
path.pop()

path_all = []
find_path_all('A', 'G',path=['A'])
print path_all

#遍历图中所有顶点,按照遍历顺序将顶点添加到列表中
vertex = []
def dfs(v):
if v not in graph:
return
for vv in graph[v]:
if vv not in vertex:
vertex.append(vv)
dfs(vv)

for v in graph:
if v not in vertex:
vertex.append(v)
dfs(v)
print(vertex)


约瑟夫环

        描述:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围。从编号为k的人开始报数,数到k的那个人被杀掉;他的下一个人又从1开始报数,数到k的那个人又被杀掉;依此规律重复下去,直到圆桌周围的人只剩最后一个。

        使用取模进行实现。

def josephus(n,k):
if k==1:
print('survive:',n)
return
p=0
people=list(range(1,n+1))
while True:
if len(people)==1:
break
p=(p+(k-1))%len(people)
print('kill:',people[p])
del people[p]
print('survive:',people[0])
if __name__=='__main__':
josephus(10,4)


栈和队列

栈的代码实现:
class Stack(object):
def __init__(self):
self.stack = []
def empty(self):
"""
判断栈是否为空
:return:
"""
return len(self.stack) == 0
def peek(self):
"""
查看栈顶的对象,但不移除
:return:
"""
if not self.empty():
return self.stack[-1]
return None
def pop(self):
"""
移除栈顶对象,并返回该对象的值
:return:
"""
if not self.empty():
return self.stack.pop()
return None
def push(self, obj):
"""
把对象压入栈顶
:return:
"""
self.stack.append(obj)
def search(self, obj):
"""
返回对象在栈中的位置,以1为基数
:param obj:
:return:
"""
if not self.empty():
return self.stack.index(obj) + 1
return -1
队列的代码实现:
class Queue(object):
def __init__(self):
self.queue = []
def empty(self):
"""
判断队列是否为空
:return:
"""
return len(self.queue) == 0
def add(self, obj):
"""
将指定元素加入队列的尾部
:param obj:
:return:
"""
self.queue.append(obj)
def peek(self):
"""
查看队首的对象,但不移除
:return:
"""
if not self.empty():
return self.queue[0]
return None
def poll(self):
"""
移除队首对象,并返回该对象的值
:return:
"""
if not self.empty():
return self.queue.pop(0)
return None
# 两个队列实现一个栈
class Stock:
def __init__(self):
self.queueA=[]
self.queueB=[]
def push(self, node):
self.queueA.append(node)
def pop(self):
if len(self.queueA)==0:
return None
while len(self.queueA)!=1:
self.queueB.append(self.queueA.pop(0))
print "queueA = %s, queueB = %s" % (self.queueA, self.queueB)
self.queueA,self.queueB=self.queueB,self.queueA #交换是为了下一次的pop
return self.queueB.pop()
if __name__=='__main__':
times=5
testList=list(range(times))
testStock=Stock()
for i in range(times):
testStock.push(testList[i])
print(testList)
for i in range(times):
print(testStock.pop())
# 两个栈实现一个队列
class Queue:
def __init__(self):
self.stockA=[]
self.stockB=[]
def push(self, node):
self.stockA.append(node)
def pop(self):
print "stockA = %s" % self.stockA
if self.stockB==[]:
if self.stockA==[]:
return None
else:
for i in range(len(self.stockA)):
self.stockB.append(self.stockA.pop())
print "stockB = %s" % self.stockB
return self.stockB.pop()
if __name__=='__main__':
times=5
testList=list(range(times))
testQueue=Queue()
for i in range(times):
testQueue.push(testList[i])
print(testList)
for i in range(times):
print(testQueue.pop())


others

1.字符串(包含数字和字母)进行排序

形式类似于:['100ab', '100abc', '90ab', '90abc']

import re
def emb_numbers(s):
pieces=re.compile(r'(\d+)').split(s)
pieces[1:2]=map(int,pieces[1:2]) # 将str('100','90')变为int(100,90)
return pieces
alist = ['100abc', '90abc', '100ab', '90ab']
print sorted(alist, key=str) # ['100ab', '100abc', '90ab', '90abc']
print sorted(alist, key=emb_numbers) # ['90ab', '90abc', '100ab', '100abc']

sorted的使用:

在Sorting Keys中:如果想用第二个关键字进行排序,排序后再用第一个关键字进行排序。
>>> L = [('d',2),('a',4),('b',3),('c',2)]
>>> print sorted(L, key=lambda x:(x[1],x[0])) # sorted(iterable, cmp=None, key=None, reverse=False)
>>>[('c', 2), ('d', 2), ('b', 3), ('a', 4)]

2.字符串大小写转换

str = "www.runoob.com"
print(str.upper()) # 把所有字符中的小写字母转换成大写字母
print(str.lower()) # 把所有字符中的大写字母转换成小写字母
print(str.capitalize()) # 把第一个字母转化为大写字母,其余小写
print(str.title()) # 把每个单词的第一个字母转化为大写,其余小写
执行以上代码输出结果为:
WWW.RUNOOB.COM
www.runoob.com
Www.runoob.com
Www.Runoob.Com

自定义实现、可以通过ASCII码来做,小写字母转换成ascii码后-32,得到的就是其对应的大写字母;同理,大写字母+32,得到的就是其对应的小写字母,例如:
#接收单个字符并做大小写转换,(没有做边界值判断)
def chg(c):
if ord(c) > = 97:
return chr(ord(c)-32)
else

return chr(ord(c)+32)

3.找出列表中出现次数最多的元素的方法

from collections import Counter
words = ['look', 'into', 'my', 'look', 'eyes', 'look', 'into', 'my', 'eyes']
Counter(words)

dict_num = {}
for item in words:
if item not in dict_num.keys():
dict_num[item] = words.count(item)

4.判断一个整数是否是2的整数次幂

将2的幂次方写成二进制形式后,很容易就会发现有一个特点:二进制中只有一个1,并且1后面跟了n个0; 因此问题可以转化为判断1后面是否跟了n个0就可以了。如果将这个数减去1后会发现,仅有的那个1会变为0,而原来的那n个0会变为1;因此将原来的数与去减去1后的数字进行与运算后会发现为零。
与运算:(number & number - 1) == 0

5.最长递增子序列

        平均时间复杂度nlogn

最长递增子序列(Longest Increasing Subsequence)是指n个数的序列的最长单调递增子序列。比如,A = [1,3,6,7,9,4,10,5,6]的LIS是1 3 6 7 9 10。
def lis(arr):
n = len(arr)
m = [0]*n
for x in range(n-2,-1,-1):
for y in range(n-1,x,-1):
if arr[x] < arr[y] and m[x] <= m[y]:
m[x] += 1
max_value = max(m)
result = []
for i in range(n):
if m[i] == max_value:
result.append(arr[i])
max_value -= 1
return result
nums = [8, 3, 4, 7, 2, 5]
print(lis(nums)) # [3, 4, 7]

其它请参考:https://github.com/kdn251/interviews/blob/master/README-zh-cn.md#%E7%AE%97%E6%B3%95

待补充......

猜你喜欢

转载自blog.csdn.net/u013018618/article/details/80086992
今日推荐