পুনরাবৃত্ত স্ট্রিংয়ের সময়-জটিলতা আসলে ও (এন ^ 2), বা ও (এন) সংযোজন করে?


89

আমি সিটিসিআইয়ের বাইরে থাকা একটি সমস্যা নিয়ে কাজ করছি।

অধ্যায় 1 এর তৃতীয় সমস্যাটি আপনি যেমন একটি স্ট্রিং গ্রহণ করেছেন

'Mr John Smith '

এবং আপনাকে মধ্যস্থতাকারীর স্থানগুলি এর সাথে প্রতিস্থাপন করতে বলে %20:

'Mr%20John%20Smith'

পাইথন এটিকে ও (এন) বলে ডেকে এই সমাধানটি লেখক দিয়েছেন:

def urlify(string, length):
    '''function replaces single spaces with %20 and removes trailing spaces'''
    counter = 0
    output = ''
    for char in string:
        counter += 1
        if counter > length:
            return output
        elif char == ' ':
            output = output + '%20'
        elif char != ' ':
            output = output + char
    return output

আমার প্রশ্ন:

আমি বুঝতে পারি যে বাম থেকে ডানে আসল স্ট্রিংয়ের মাধ্যমে স্ক্যান করার ক্ষেত্রে এটি ও (এন)। কিন্তু পাইথনের স্ট্রিংগুলি কি পরিবর্তনযোগ্য নয়? যদি আমার কাছে স্ট্রিং থাকে এবং আমি +অপারেটরের সাথে এটিতে আরও একটি স্ট্রিং যুক্ত করি , এটি প্রয়োজনীয় স্থান বরাদ্দ করে না, মূলটির উপর অনুলিপি করে, এবং তারপরে অ্যাডিং স্ট্রিংয়ের অনুলিপি করে?

আমার যদি nদৈর্ঘ্যের প্রতিটি দৈর্ঘ্যের স্ট্রিংয়ের সংকলন থাকে তবে তা লাগে:

1 + 2 + 3 + 4 + 5 + ... + n = n(n+1)/2

বা ও (এন ^ 2) সময় , হ্যাঁ? বা পাইথন কীভাবে অ্যাডেন্ডিং পরিচালনা করে?

বিকল্পভাবে, আপনি আমাকে কীভাবে মাছ ধরতে শেখাতে ইচ্ছুক হন: আমি কীভাবে নিজের জন্য এটি সন্ধান করব? আমি একটি সরকারী উত্স গুগল আমার প্রচেষ্টা ব্যর্থ হয়েছে। আমি https://wiki.python.org/moin/TimeComplexity খুঁজে পেয়েছি তবে স্ট্রিংগুলিতে এর কিছুই নেই।


17
কারও কাছে লেখককে বলা উচিতurllib.urlencode
wim

11
@ উইম এর অর্থ অ্যারে এবং স্ট্রিংগুলি সম্পর্কে অনুশীলন সমস্যা হতে হবে
ব্যবহারকারী5622964

4
বইটির উদ্দেশ্য সাক্ষাত্কারের প্রশ্নগুলি শেখানো, যা আপনাকে সাধারণত ইন্টারভিউয়ের চিন্তার প্রক্রিয়াটি দেখার জন্য চাকাটি পুনরায় আবিষ্কার করতে বলে।
জেমস ওয়েয়ারজবা

4
যেহেতু এটা পাইথন, আমি একটি কাজ মনে rtrimএবং replaceআরও পছন্দসই এবং ন্যয় হবে O(n)। স্ট্রিংগুলির অনুলিপি করা স্বল্প দক্ষ উপায় বলে মনে হচ্ছে না।
ওয়ানডে ক্রিকেটার 21

4
@ আরএনআর আপনি কীভাবে একটি অনুলিপি স্থির সময় নিতে পারেন তা ব্যাখ্যা করতে পারেন?
জেমস ওয়েয়ারজবা 21

উত্তর:


84

পাইথনে, পাইথনের মানক প্রয়োগকরণ, একটি বাস্তবায়ন বিশদ রয়েছে যা এটি সাধারণত ও (এন) করে, কোডটিতে বাইটকোড মূল্যায়ন লুপ কল করে +বা +=দুটি স্ট্রিং অপারেশন সহ কল করে । পাইথন যদি সনাক্ত করে যে বাম আর্গুমেন্টের অন্য কোনও রেফারেন্স নেই, তবে এটি reallocস্ট্রিংটির স্থানে আকার পরিবর্তন করে একটি অনুলিপিটি এড়ানোর চেষ্টা করার আহ্বান জানায় । এটি এমন কোনও বিষয় নয় যা আপনার কখনও নির্ভর করা উচিত, কারণ এটি একটি বাস্তবায়ন বিশদ এবং কারণ যদি reallocপ্রায়শই স্ট্রিংটি সরানোর প্রয়োজন হয়, পারফরম্যান্স যাইহোক O (n ^ 2) এ অবনমিত হয়।

অদ্ভুত বাস্তবায়নের বিশদ ছাড়াই অনুলিপিটির সাথে জড়িত চতুর্ভুজ পরিমাণের কারণে অ্যালগরিদম হ'ল (n ^ 2)। এর মতো কোডটি কেবলমাত্র সি ++ এর মতো পরিবর্তিত স্ট্রিংগুলির সাথে কোনও ভাষায় বোঝায় এবং এমনকি আপনি সি ++ ব্যবহার করতে চান +=


4
আমি আপনার সংযুক্ত কোডটি দেখছি ... দেখে মনে হচ্ছে যে এই কোডটির একটি বড় অংশ সাফ করছে / স্ট্রিংয়ের পয়েন্টার / রেফারেন্সগুলি মুছে ফেলা হচ্ছে, সঠিক? এবং তারপরে শেষের দিকে এটি সংক্ষিপ্ত _PyString_Resize(&v, new_len)স্ট্রিংয়ের জন্য মেমরি বরাদ্দ করতে সম্পাদন করে এবং তারপরে memcpy(PyString_AS_STRING(v) + v_len, PyString_AS_STRING(w), w_len);অনুলিপিটি কী করে। যদি স্থানটিতে পুনরায় আকার দেওয়া ব্যর্থ হয়, তবে এটি ঘটে PyString_Concat(&v, w);(মূল স্ট্রিং ঠিকানার শেষে সংগতিপূর্ণ মেমরিটি নিখরচায় না হলে আমি এর অর্থ গ্রহণ করি)। এটি কীভাবে গতিবেগ দেখায়?
ব্যবহারকারী5622964

আমি আমার পূর্ববর্তী মন্তব্যে স্থান ছাড়িয়েছি, তবে আমার প্রশ্নটি রয়েছে যে আমি সেই কোডটি সঠিকভাবে বুঝতে পারছি কিনা এবং সেই টুকরোগুলির মেমরির ব্যবহার / রানটাইম কীভাবে ব্যাখ্যা করব।
ব্যবহারকারী5622964

4
@ user5622964: ওহো, অদ্ভুত বাস্তবায়ন বিশদটি ভুলভাবে ছড়িয়ে দিয়েছে। কোনও কার্যকর পুনরায় আকার দেওয়ার নীতি নেই; এটি কেবল কল করে reallocএবং সেরাটির জন্য আশা করে।
ব্যবহারকারীর 2357112 মনিকা

কিভাবে memcpy(PyString_AS_STRING(v) + v_len, PyString_AS_STRING(w), w_len);কাজ করে? সিপিপ্লসপ্লাস / রেফারেন্স/cstring/memcpy অনুসারে এর সংজ্ঞা void * memcpy ( void * destination, const void * source, size_t num );এবং বিবরণ রয়েছে: "Copies the values of num bytes from the location pointed to by source directly to the memory block pointed to by destination."এই ক্ষেত্রে সংখ্যাটি অ্যাডেন্ডিং স্ট্রিংয়ের আকার এবং উত্সটি দ্বিতীয় স্ট্রিংয়ের ঠিকানা, আমি ধরে নিই? তবে তবে কেন গন্তব্য (প্রথম স্ট্রিং) + লেন (প্রথম স্ট্রিং)? ডাবল স্মৃতি?
ব্যবহারকারী5622964

7
@ user5622964: এটি পয়েন্টার গাণিতিক। আপনি যদি সিপিথন উত্স কোডটি অদ্ভুত প্রয়োগের বিশদটি নীচে বুঝতে চান তবে আপনাকে সি জানা দরকার super সুপার-কনডেন্স করা সংস্করণটি হ'ল PyString_AS_STRING(v)প্রথম স্ট্রিংয়ের ডেটার v_lenঠিকানা এবং যুক্তটি স্ট্রিংয়ের ঠিক পরে পেয়ে যায় তথ্য শেষ হয়।
ব্যবহারকারী 2357112

41

লেখক এমন একটি অপ্টিমাইজেশনের উপর নির্ভর করে যা এখানে উপস্থিত হয় তবে স্পষ্টভাবে নির্ভরযোগ্য নয়। strA = strB + strCসাধারণত O(n), ফাংশন করা হয় O(n^2)। তবে এটি সম্পূর্ণ প্রক্রিয়াটি নিশ্চিত করা খুব সহজ O(n), একটি অ্যারে ব্যবহার করুন:

output = []
    # ... loop thing
    output.append('%20')
    # ...
    output.append(char)
# ...
return ''.join(output)

সংক্ষেপে, appendক্রিয়াকলাপটি সূক্ষ্মভাবে তৈরি করা হয় O(1) (যদিও আপনি এটিটিকেO(1) সঠিক আকারে প্রাক বরাদ্দ করে শক্তিশালী করতে পারেন ), লুপ তৈরি করে O(n)

এবং এরপরে joinএটিও রয়েছে O(n)তবে এটি ঠিক আছে কারণ এটি লুপের বাইরে।


এই উত্তরটি ভাল কারণ এটি কীভাবে স্ট্রিংগুলি সংহত করতে হয় তা বলে।
ব্যবহারকারীর 877329

রানটাইমের গণনা প্রসঙ্গে যথাযথ উত্তর।
ihaider

25

পাইথনের গতিতে আমি এই টুকরো টুকরোটি পেয়েছি > সেরা অ্যালগরিদম এবং দ্রুততম সরঞ্জামগুলি ব্যবহার করুন :

স্ট্রিং কনটেনটেশন সর্বোত্তমভাবে সম্পন্ন হয় ''.join(seq)যা একটি O(n)প্রক্রিয়া। বিপরীতে, '+'বা '+='অপারেটরগুলি ব্যবহারের ফলে একটি O(n^2)প্রক্রিয়া হতে পারে কারণ প্রতিটি মধ্যবর্তী পদক্ষেপের জন্য নতুন স্ট্রিংগুলি নির্মিত হতে পারে। সিপিথন ২.৪ দোভাষী এই সমস্যাটি কিছুটা কমিয়ে দিয়েছেন; তবে, ''.join(seq)সেরা অনুশীলন রয়ে গেছে


3

ভবিষ্যতে দর্শক জন্য: যেহেতু এটি একটি CTCI প্রশ্ন শেখার কোনো রেফারেন্স urllib বিশেষভাবে যেমন ওপি এবং বই প্রতি প্যাকেজ এখানে প্রয়োজন নেই,, এই প্রশ্নের অ্যারে এবং স্ট্রিং সম্পর্কে।

@ Njzk2 এর সিউডো থেকে অনুপ্রাণিত আরও একটি সম্পূর্ণ সমাধান এখানে দেওয়া হয়েছে:

text = 'Mr John Smith'#13 
special_str = '%20'
def URLify(text, text_len, special_str):
    url = [] 
    for i in range(text_len): # O(n)
        if text[i] == ' ': # n-s
            url.append(special_str) # append() is O(1)
        else:
            url.append(text[i]) # O(1)

    print(url)
    return ''.join(url) #O(n)


print(URLify(text, 13, '%20'))
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.