题目描述
算法思路(第一步)–贪心
刚刚开始拿到这个题目,我的第一想法是,当前要输入的密码,我只要找距离最近的那个字符,转过去,然后press button即可
于是开开心心的开始了代码
代码实现
这里我还是只把核心部分发出来,写的可能有点冗长,如果有哪里可以写的更简洁,希望大家在底下评论区告诉我
我定义了一个Ring类,Ring可以进行两种操作(顺/逆时针),以及找到最近的并旋转
class Ring:
__slots__ = ("ring", "lenth")
def __init__(self, ring: str):
self.lenth = len(ring)
self.ring = ring
def get_current(self):
return self.ring[0]
def clockwise(self):
print("Started an clockwise rotate")
temp_str = []
for i in range(0, self.lenth):
temp_str.append(self.ring[(i-1)%self.lenth])
self.ring = temp_str
print("current ring is : ")
print(self.ring)
def anti_clockwise(self):
print("Started an anti-clockwise rotate")
temp_str = []
for i in range(0, self.lenth):
temp_str.append(self.ring[(i+1)%self.lenth])
self.ring = temp_str
print("current ring is : ")
print(self.ring)
def find_nearest_and_rotate(self,character)->int:
i=0
j=0
for i in range(0,self.lenth):
if (self.ring[i]==character):
break
for j in range(self.lenth-1,-1,-1):
if (self.ring[j]==character):
break
rotate_time=0
#clock wise is faster
if (i<=self.lenth-j):
rotate_time=i
for rotate in range(0,rotate_time):
self.anti_clockwise()
#anti clock wise is faster
else:
rotate_time=self.lenth-j
for rotate in range(0,rotate_time):
self.clockwise()
return rotate_time
class Solution:
def __init__(self):
print("init")
def findRotateSteps(self,ring:str,key:str)->int:
step=0
my_ring=Ring(ring)
key_lenth=len(key)
for i in range(0,key_lenth):
if (my_ring.get_current() == key[i]):
step=step+1
print("PRESSED")
else:
step=step+my_ring.find_nearest_and_rotate(key[i])+1
print("Rotate finished and PRESSED")
return step
为什么错了?
开始的第一个测试用例执行的很不错:
不过这个测试用例就错了:
不过哪里错了呢?
贪心算法就是每一次操作,都在找当前字符我所需操作数最少的操作方式,也就是比较逆时针还是顺时针去找时间短。
但是,这里就发现一个问题,如果逆时针和顺时针所需操作数一样呢?
这里就是输入到“i”之后找“o”,发现左右两边是一样的,那,我们该怎么找呢?
算法思路(第二步)–贪心+选择
如果当前的两个方向转都是一样的话,那么我们就需要去找那种方式转完后,后续的寻找中,哪个旋转次数最少
代码实现
在第一步的代码上进行修改
class Ring:
__slots__ = ("ring", "lenth")
def __init__(self, ring):
self.lenth = len(ring)
self.ring = []
for i in range(0,len(ring)):
self.ring.append(ring[i])
def get_ring(self):
return self.ring
def clockwise(self):
print("Started an clockwise rotate")
temp_str = []
for i in range(0, self.lenth):
temp_str.append(self.ring[(i-1)%self.lenth])
self.ring = temp_str
print("current ring is : ")
print(self.ring)
def anti_clockwise(self):
print("Started an anti-clockwise rotate")
temp_str = []
for i in range(0, self.lenth):
temp_str.append(self.ring[(i+1)%self.lenth])
self.ring = temp_str
print("current ring is : ")
print(self.ring)
def find_rotate_steps(self,ring,key):
step = 0
my_ring = Ring(ring)
key_lenth = len(key)
for i in range(0, key_lenth):
if (my_ring.get_ring()[0] == key[i]):
step = step + 1
print("PRESSED")
else:
step = step + my_ring.find_nearest_and_rotate(key[i], i, key_lenth,key) + 1
print("Rotate finished and PRESSED")
return step
def find_nearest_and_rotate(self,character,indexOfChar,key_lenth,key)->int:
i=0
j=0
for i in range(0,self.lenth):
if (self.ring[i]==character):
break
for j in range(self.lenth-1,-1,-1):
if (self.ring[j]==character):
break
rotate_time=0
#anti clock wise is faster
if (i<self.lenth-j):
rotate_time=i
for rotate in range(0,rotate_time):
self.anti_clockwise()
#clock wise is faster
else:
if (i>self.lenth-j):
rotate_time=self.lenth-j
for rotate in range(0,rotate_time):
self.clockwise()
else:
print("Now, two rotation is the same, begin to compare which is best")
rotate_time=i
remaining_key=[]
for index in range(indexOfChar+1,key_lenth):
remaining_key.append(key[index])
clockwise_temp_Ring=Ring(self.ring)
for rotate in range(0,rotate_time):
clockwise_temp_Ring.clockwise()
anticlockwise_temp_Ring=Ring(self.ring)
for rotate in range(0,rotate_time):
anticlockwise_temp_Ring.anti_clockwise()
if (clockwise_temp_Ring.find_rotate_steps(''.join(clockwise_temp_Ring.get_ring()),''.join(remaining_key)) <
anticlockwise_temp_Ring.find_rotate_steps(''.join(anticlockwise_temp_Ring.get_ring()),''.join(remaining_key))):
print("Clockwise is better")
for rotate in range(0, rotate_time):
self.clockwise()
else:
print("anti clock wise is better")
for rotate in range(0, rotate_time):
self.anti_clockwise()
return rotate_time
class Solution:
def __init__(self):
print("init")
def findRotateSteps(self,ring:str,key:str)->int:
my_ring=Ring(ring)
return my_ring.find_rotate_steps(ring,key)
运行结果
依然是没有All Clear,原因是,这样的算法,一旦遇到稍微长一些的字符串,就相当于给电脑抛了个炸弹,所以,贪婪算法是肯定不行的。
未完待续。。。(等博主考完GRE)