引出:
网上可能有类似的问题,二进制串也是一种,比如统计“1100110011110001010”连续出现多次的元素个数:
连续出现两次或两次以上的元素的个数
"1"为3次,“0”为3次
我一般喜欢用自己的思路去想出解决问题的方法,所以也没细查。数据结构与算法这种问题,我建议程序员如果想打牢基础的话最好自己动手去敲代码实现,做的多了,逻辑清晰了,问题自然就处理了
思路:
看似简单,就输入子串嘛:“1001110”,“1”为1,“0”为1,肉眼看似容易,但要做的就是在程序中加一些语句和判断让计算机去识别。第一个冒出来的想法就是循环遍历,逐个比较,这个方法貌似可行,但想了并试着做了很久都没有清晰的思路,因为元素的下标都是固定的,很难有灵活的操作,看似简单的问题常规方法不可行。于是就想到排序算法中的插入排序,类似的做法就是将元素拆分,将元素分为两部分,对拆分的一端去操作。
步骤详解:
在这个例子中,要使得程序实现,在这为了简单,我们仅仅考虑某一种元素,指定一个key(比如'1')出现多次的情况,首先还是遍历,我们可以用pop()方法(转str为list),首先判断pop(0)是否为'1',然后再做其他判断操作,首先在之外有一个大循环控制,while alist,即当我一个个循环取出时,取完为止,可写出这两行代码
while alist:
if alist.pop(0) == '1':
还拿“1001110”为例,当满足第一个元素为'1'时,可以初始化num=0,为统计连续出现元素的个数,既有num+=1,
当第二个元素不满足为'1'时,将num重置为0,于是:
num = 0
while alist:
if alist.pop(0) == '1':
num += 1
else:
num = 0
理所当然,在判断为某个元素的值时,连续出现两次以上给个统计,用count计数。
拿“110”为例,pop(0)多次循环过后,第一次取到'1',此时alist=[1,0],第二次是'1',此时alist=[0],第三次为0,alist=[],故当下一个元素不为我当前的元素时,即满足num>=2并且alist[0] != ‘1’,count+=1
这里有一些特殊情况,拿“111”为例,第一次取到'1',alist=[1,1],第二次取到‘1’,alist=[1],第三次取到‘1’,alist=[],此时alist没有元素,alist[0]为false,但他满足连续的定义,故在满足num>=2并且len(alist)==0,count+=1
故当满足 alist[0] != ‘1’,len(alist)==0其中的一种,并且num >= 2,统计一次个数。当然,统计过后,num需要置为0
num = 0
count = 0
while alist:
if alist.pop(0) == '1':
num += 1
if (len(alist) == 0 or alist[0] != '1') and num >= 2:
count += 1
num = 0
else:
num = 0
基本的框架形成,封装成函数
def count_(alist,a_key):
count = 0
num = 0
while alist:
if alist.pop(0) == a_key:
num += 1
if (len(alist) == 0 or alist[0] != a_key) and num >= 2:
count += 1
num = 0
else:
num = 0
return count
注意,在重复调用函数时,所处理的对象会改变,如果想统计其他元素连续多次出现的次数,需要重新给定一个对象,如
def count_(alist,a_key):
count = 0
num = 0
while alist:
if alist.pop(0) == a_key:
num += 1
if (len(alist) == 0 or alist[0] != a_key) and num >= 2:
count += 1
num = 0
else:
num = 0
return count
s = '101010010010011011'
print(count_(list(s),'1'))
s = '101010010010011011'
print(count_(list(s),'0'))
得到的结果为
扩展:
从键盘输入任意整数n,表示有多少行接下来的输入;比如输入n=4,再继续输入4行0和1用空格表示的字串如1 1 1 0、1 1 0 0、0 1 1 0、1 0 1 0,可以看做为一个矩阵;其中横纵连续的0表示海洋,连续的1表示大陆,判别出这片土地(矩阵)有多少个大陆多少个海洋
这个问题就相当于我们之前的扩展,如上述的输入
棕色部分表示大陆,蓝色部分表示海洋,可见有6个大陆,2个海洋。
无非就是循环遍历每一行和每一列,统计相邻多元素的总和
首先定义一个对象,返回的是用户输入的结果,转换成我们想要的形式,最后返回一个用户输入的二维列表和转置的二维列表
n = int(input())
all_ = []
for i in range(n):
all_.append([int(i) for i in input().split(' ')])
all_T = list(map(list,zip(*all_)))
print(all_,all_T)
如
可以把这段代码封装成一个函数,方便调用
def get_object():
n = int(input())
all_ = []
for i in range(n):
all_.append([int(i) for i in input().split(' ')])
all_T = list(map(list,zip(*all_)))
return all_,all_T
接下来定义一个在二维列表中统计的函数,传入的是二维列表与转置的二维列表(横纵遍历)以及key,返回的是在二维列表中,key连续出现的次数
def count_all(all_,all_T,a_key):
count = 0
for item in all_:
count += count_(item,a_key)
for item in all_T:
count += count_(item,a_key)
return count
对于count_()这个函数来说,每次执行的时候,列表会发生改变,故在统计1和0之前,先拷贝一份原对象
import copy
all_1,all_T_1 = get_object()
all_0,all_T_0 = copy.deepcopy(all_1),copy.deepcopy(all_T_1)
调用统计函数count_all
print('大陆数量:',count_all(all_1,all_T_1,1))
print('海洋数量:',count_all(all_0,all_T_0,0))
全部python3代码
import copy
def get_object():
n = int(input())
all_ = []
for i in range(n):
all_.append([int(i) for i in input().split(' ')])
all_T = list(map(list,zip(*all_)))
return all_,all_T
def count_(alist,a_key):
count = 0
num = 0
while alist:
if alist.pop(0) == a_key:
num += 1
if (len(alist) == 0 or alist[0] != a_key) and num >= 2:
count += 1
num = 0
else:
num = 0
return count
def count_all(all_,all_T,a_key):
count = 0
for item in all_:
count += count_(item,a_key)
for item in all_T:
count += count_(item,a_key)
return count
all_1,all_T_1 = get_object()
all_0,all_T_0 = copy.deepcopy(all_1),copy.deepcopy(all_T_1)
print('大陆数量:',count_all(all_1,all_T_1,1))
print('海洋数量:',count_all(all_0,all_T_0,0))
输入测试,得到结果: