自由之路(困难)-力扣每日一题(环形密码门,输入正确密码所用操作最少次数)

题目描述

在这里插入图片描述

算法思路(第一步)–贪心

刚刚开始拿到这个题目,我的第一想法是,当前要输入的密码,我只要找距离最近的那个字符,转过去,然后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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值