#python
#python
Вопрос:
ВОПРОС: Завершите функцию scramble(str1, str2), которая возвращает true, если часть символов str1 может быть изменена в соответствии с str2, в противном случае возвращает false .
Примечания:
Будут использоваться только строчные буквы (a-z). Знаки препинания или цифры не будут включены. Необходимо учитывать производительность
MY CODE:
s1 = 'rkqodlw'
s2 = 'world'
def scramble(s1, s2):
unscrambled_word = []
n = 0
x = 0
s1_list = list(s1)
s2_list = list(s2)
s1_letter = s1_list[n]
s2_letter = s2_list[x]
for letters in range(len(s2_list)):
while n > len(s1_list):
if s1_letter == s2_letter:
n = n 1
x = x 1
else:
n = n 1
return 'True' if x == len(s2_list) else 'False'
Я пытаюсь заставить свой код анализировать каждую из двух строк. Если слово первой строки не совпадает со словом второй строки, тогда n будет 1 и перейдет ко второй букве. Если он совпадает, то и n, и x будут 1. Моя мысль о моем коде заключается в том, что если x == длина второй строки до окончания гигантского цикла, то она вернет True. В противном случае False. Проблема в цикле. Кажется, что цикл проходит только по первым двум буквам обеих строк, а затем останавливается. Я довольно новый программист, любой ввод приветствуется! Спасибо!
Комментарии:
1. Каков ваш ожидаемый доход? Вы пытаетесь вернуть
True
, если s1 является зашифрованной версией s2, возможно, с дополнительными буквами? Если это так, наборы кажутся элегантным решением.2. Я тоже думал о наборах, однако наборы не будут работать. Если первое слово равно
moon
, а второе слово равноmoney
, это приведет к True, что неверно. Когда вы пытаетесь увидеть, находится ли word1 в word23. Ваша общая идея кажется правильной. Однако у вас что-то не так в вашем цикле while, вы проверяете,
n
превышает ли оно длину вашего списка, и, посколькуn
начинается с 0, ваш цикл while никогда не будет выполнен.4. Вам нужно отсортировать оба слова. Затем сравните по позиции. Если он не соответствует, то сбой
5. Я даже не уверен, что такое наборы, как я уже сказал, я все еще довольно новичок. Но я думаю, что мне не нужно расшифровывать слова, если я могу заставить программу проверить, что в первой строке достаточно слов, которые соответствуют словам во второй строке, чтобы создать второе строковое слово. Надеюсь, это поможет.
Ответ №1:
Вам просто нужно убедиться, что все буквы в str2 присутствуют в str1 в достаточном количестве
def scramble(str1,str2):
d1 = {}
for c in str1:
if not c in d1:
d1[c] = 0
d1[c] = 1
for c in str2:
if not c in d1 or d1[c] < 1:
return False
d1[c] -= 1
return True
Идея состоит в том, чтобы просмотреть все символы в str2, и если, например, str2 содержит три буквы «a», убедитесь, что str1 содержит как минимум три буквы «a». Для этого требуется подсчитать, сколько раз каждый символ встречается в str1. Это наиболее естественно сделать со словарем. Словарь сопоставляет вещи, называемые ключами, с другими вещами, называемыми значениями. В этом случае мы сопоставляем ключи, которые являются одиночными символами, со значениями, которые являются числовыми числами.
Первый шаг — создать пустой словарь d1={}
. Далее нужно перейти посимвольно в str1, который является первым циклом for . Для каждого из этих символов мы спрашиваем, был ли этот символ когда-либо ранее помещен в d1. Если этого не произошло, то мы создаем новое сопоставление внутри d1 для этого символа с начальным значением, равным нулю. Каждый раз, когда в этом цикле через str1 встречается символ, значение count, сопоставленное с этим символом в d1, увеличивается на 1. После завершения первого цикла for (который проходит через str1) словарь содержит количество каждой буквы в str1.
Следующая идея — перебрать каждый символ в str2. Если это символ, отсутствующий в d1, то это означает, что символ отсутствовал в str1, поэтому в str1 отсутствует символ, который нужно было бы скремблировать в str2. На этом этапе вы можете остановить обработку и просто вернуть False .
В противном случае, если вы сталкиваетесь только с символами, которые существуют в качестве ключей в d1, вы вычитаете единицу из отображенного значения счетчика d1 каждый раз, когда вы сталкиваетесь с этим символом во время выполнения цикла через str2. Если вычитание когда-либо приведет к тому, что значение d1 count опустится ниже нуля, то это означает, что str2 имеет большее число этого конкретного символа, чем str1, поэтому str1 снова не может скремблироваться в str2. Поэтому вы можете вернуть False в этот момент и остановить обработку.
Наконец, если мы пройдем весь 2-й цикл (через str2), не встретив ни одного из случаев возврата False, упомянутых выше, это означает, что str1 содержит по крайней мере столько же символов, сколько и str2, и поэтому может скремблироваться в str2, используя некоторые из его букв. Затем вы возвращаете True.
Комментарии:
1. я немного смущен тем, что компьютер делает в некоторых ваших коде. Не могли бы вы еще немного разбить его и объяснить, что делает ваш код? Извините, я большой новичок, лол.
2. @Jace Я добавлю больше объяснений
3. большой палец вверх для деталей. С точки зрения производительности я не вижу ничего, что могло бы превзойти ваш ответ
4. @BingWang Мне действительно понравилось, как вы используете коллекции. Ваши были элегантными.
Ответ №2:
from collections import defaultdict
s1 = 'rkqodlw'
s2 = 'world'
def scramble(s, t):
d=defaultdict(int)
for c in s:
d[c] =1
for c in t:
d[c]-=1
return min(d.values())>=0
scramble(s1,s2)
в качестве альтернативы используйте счетчик
from collections import Counter
s1 = 'rkqodlw'
s2 = 'world'
def scramble(s, t):
c=Counter(s)
c.subtract(Counter(t))
return min(c.values())>=0
scramble(s1,s2)
Ответ №3:
Альтернатива:
s1 = 'rkqodlw'
s2 = 'world'
def scramble(s1, s2):
s1_list = list(s1)
for char in s2:
if char in s1_list:
s1_list.pop(s1_list.index(char))
else:
return False
return True
print(scramble(s1,s2))
Вот как это работает: вы выполняете цикл для каждой буквы в s2, и если эта буква также находится в версии списка s1, вы удаляете ее из этой версии списка. Таким образом, если 'rabbit'
, например, s2 был, а s1 был 'braintrain'
, вы встретили бы первый 'r'
, 'a'
, и первый 'b'
, удалите его из 'braintrain'
, чтобы получить 'intrain'
, а следующий 'b'
затем провалит тест и False
будет возвращен. Если бы было достаточно 'b'
s, скремблер вернулся True
бы. Финал True
возвращается, если тест никогда не завершается неудачно (то есть все буквы в s2 также находятся в s1), когда функция завершается.
Комментарии:
1. Вы можете использовать remove так же, как у вас уже есть char
2. Я бы не рекомендовал это. список pop равен O (N), а ваш ответ — O (N ^ 2) сложность. И Matt, и мой ответ выполняются с O (N)
Ответ №4:
Обновленная версия:
s1 = зашифрованное слово, которое может содержать s2
s2 = слово для поиска
Шаг 1. Найдите набор s2
Шаг 2. Перебирайте каждую букву набора s2. Давайте назовем каждую букву как s
Шаг 3. Для каждой буквы s узнайте, сколько раз она встречается в s1 и s2
Шаг 4: Если количество букв в s2 <= количество букв в s1, тогда ОК, иначе выйдите и верните False
Шаг 5: Если все буквы в наборе s2 соответствуют условию шага 4, то s2 находится в s1. Вы можете вернуть True
Код для этого:
def scramble_check(s1,s2):
return True if all(s2.count(s) <= s1.count(s) for s in set(s2)) else False
print (scramble_check('rkqodlw', 'world'))
print (scramble_check('moonshine', 'moon'))
print (scramble_check('strain', 'brain'))
print (scramble_check('aaaappppleeeset', 'apple'))
print (scramble_check('braintrain', 'rabbit'))
Вывод приведенного выше кода:
True
True
False
True
False
Джейс, чтобы ты понял, что одна строка кода, я расширил функцию. Вот более расширенная версия.
def scramble_check(s1,s2):
ss = set(s2) #create a set from word s2
for s in ss: #iterate through each letter in set ss
#compare count of occurrences of s in both s1 and s2
#if s2 count is more than s1, then the word cannot be made with s1
#so return False and exit the function
if s2.count(s) > s1.count(s): return False
#if we iterated through all of ss and each letter met the condition, then s2 can be created using s1. So return True
return True
Все это одна строка:
return True if all(s2.count(s) <= s1.count(s) for s in set(s2)) else
Комментарии:
1. да, это поможет — я всегда забываю, что функция str.count существует. Вероятно, вы можете просто напрямую вернуть все (…) вместо выполнения условия.