एक हे (एन) एल्गोरिथ्म [बंद] के साथ एक पूर्णांक एरे को घुमाएं


10

एक फ़ंक्शन लिखें जो किसी दिए गए नंबर k द्वारा पूर्णांक सरणी को घुमाता है। k तत्व अंत से आरम्भ की ओर बढ़ना चाहिए, और अन्य सभी तत्वों को स्थान बनाने के लिए दाईं ओर जाना चाहिए।

रोटेशन को जगह में किया जाना चाहिए।

एल्गोरिथ्म को O (n) से अधिक नहीं चलना चाहिए, जहां n सरणी का आकार है।

ऑपरेशन करने के लिए भी एक निरंतर मेमोरी का उपयोग किया जाना चाहिए।

उदाहरण के लिए,

यदि सरणी गिरफ्तार तत्वों के साथ आरंभीकृत है = {1, 2, 3, 4, 5, 6, 7, 8, 9}

घुमाएँ (गिरफ्तारी, 3) तत्वों का परिणाम होगा {7, 8, 9, 1, 2, 3, 4, 5, 6}

घुमाने (गिरफ्तारी, 6) का परिणाम {4, 5, 6, 7, 8, 9, 1, 2, 3} होगा


1
यहाँ निरंतर स्मृति से क्या अभिप्राय है? निश्चित रूप से इसे कम से कम हे (एन) मेमोरी की आवश्यकता होती है ताकि स्टोर किए जाने वाले सरणी को स्टोर करने के लिए न्यूनतम (ओ) मेमोरी उपयोग असंभव हो।
तदर्थ गार्फ हंटर

2
मैं इस प्रश्न को ऑफ-टॉपिक के रूप में बंद करने के लिए मतदान कर रहा हूं क्योंकि बिना वस्तुनिष्ठ प्राथमिक मानदंड के प्रश्न ऑफ-टॉपिक हैं, क्योंकि वे निर्विवाद रूप से यह तय करना असंभव बनाते हैं कि किस प्रविष्टि को जीतना चाहिए। कोई कारण नहीं है कि यह एक लोकप्रियता प्रतियोगिता होनी चाहिए।
जेम्स

बंद करने के लिए वोट दिया गया। से लोकप्रियता-प्रतियोगिता विकी ( यहाँ ), "क्या महत्वपूर्ण भागों में करने का फैसला करने के लिए खिलाड़ियों को स्वतंत्रता देता है और इस स्वतंत्रता का उपयोग करने के लिए उन्हें incentivizes।" मुझे नहीं लगता कि इस तरह की एक सरल चुनौती के लिए रचनात्मकता को प्रोत्साहित करने के रूप में किसी भी एल्गोरिथ्म के लिए चुनौती को छोड़ना कम से कम इस हद तक नहीं है कि यह एक पॉपकॉन के रूप में काम करता है। यह एक कोड-गोल्फ चुनौती के रूप में अधिक अनुकूल होगा ।
mbomb007

जवाबों:


18

सी (104)

void reverse(int* a, int* b)
{
    while (--b > a) {
        *b ^= *a;
        *a ^= *b;
        *b ^= *a;
        ++a;
    }
}

void rotate(int *arr, int s_arr, int by)
{
    reverse(arr, arr+s_arr);
    reverse(arr, arr+by);
    reverse(arr+by, arr+s_arr);
}

न्यूनतम किया गया:

v(int*a,int*b){while(--b>a){*b^=*a;*a^=*b;*b^=*a++;}}r(int*a,int s,int y){v(a,a+s);v(a,a+y);v(a+y,a+s);}

4
आपको लूप की स्थिति के रूप में a <-- b
लिखना

एक समय हुआ करता था जब C प्रोग्राम ने लोकप्रियता प्रतियोगिता जीती थी ...
Anubian Noob

आप सबसे अच्छे हो! कैसे सुरुचिपूर्ण और अनुकूलित .. क्या आप इसे बिट सरणी के साथ कर सकते हैं?

9

एपीएल (4)

¯A⌽B
  • A घूमने के स्थानों की संख्या है
  • B, घुमाए जाने वाले सरणी का नाम है

मुझे यकीन नहीं है कि अगर एपीएल वास्तव में इसकी आवश्यकता है, लेकिन कार्यान्वयन में मैंने देखा है (आंतरिक) यह समय के लिए आनुपातिक A, और निरंतर स्मृति लेगा ।


+1 अगर यह गोल्फ था:
ग्लेन टीटेलबाम

हालांकि यह जगह में ऐसा नहीं करता है।
मारिनस

@marinus: यह निश्चित रूप से मेरे द्वारा देखे गए कार्यान्वयन में है।
जेरी कॉफिन

यह कैसा फंक्शन है? {⍵⌽⍨-⍺}या हो सकता है {⌽⍺⌽⌽⍵}। NARS2000 में इसे सुरुचिपूर्ण ढंग से लिखा जा सकता है ⌽⍢⌽
Adám

5

यहां कॉलिन के विचार का एक लंबा घुमावदार सी संस्करण है।

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int gcd(int a, int b) {
  int t;
  if (a < b) {
    t = b; b = a; a = t;
  }
  while (b != 0) {
    t = a%b;
    a = b;
    b = t;
  }
  return a;
}

double arr[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
int s_arr = sizeof(arr)/sizeof(double);

/* We assume 1 <= by < s_arr */
void rotate(double *arr, int s_arr, int by) {
  int i, j, f;
  int g = gcd(s_arr,by);
  int n = s_arr/g;
  double t_in, t_out;

  for (i=0; i<g; i++) {
    f = i;
    t_in = arr[f + s_arr - by];
    for (j=0; j<n; j++) {
      t_out = arr[f];
      arr[f] = t_in;
      f = (f + by) % s_arr;
      t_in = t_out;
    }
  }
}

void print_arr(double *arr, int s_arr) {
  int i;
  for (i=0; i<s_arr; i++) printf("%g ",arr[i]);
  puts("");
}

int main() {
  double *temp_arr = malloc(sizeof(arr));
  int i;

  for (i=1; i<s_arr; i++) {
    memcpy(temp_arr, arr, sizeof(arr));
    rotate(temp_arr, s_arr, i);
    print_arr(temp_arr, s_arr);
  }
}

यह एक निरंतर मेमोरी समाधान की तरह नहीं दिखता है, क्या यह है?
माइक्रोबियन

हाँ यह एक निरंतर स्मृति समाधान है। "मैलोकेड" सामान सरणी की एक अस्थायी प्रतिलिपि है, ताकि मैं इसमें मूल डेटा को बार-बार कॉपी कर सकूं, ताकि मैं अलग-अलग रोटेशन मात्रा के लिए परीक्षण कर सकूं।
स्टीफन मोंटगोमरी-स्मिथ

वास्तविक घुमाव क्या है फ़ंक्शन "घुमाएँ" है। यह 5 पूर्णांक और दो डबल्स का उपयोग करता है। यह एक फ़ंक्शन "gcd" भी कहता है जो एक पूर्णांक का उपयोग करता है, और अधिकांश O (लॉग (n)) ऑपरेशन में उपयोग करता है।
स्टीफन मॉन्टगोमरी-स्मिथ

समझ गया। मैंने आपका उत्तर छोड़ दिया।
माइक्रोबियन

@ स्टीफनमोंटगोमरी-स्मिथ - यह O(log(n))ऑपरेशन कैसा है । by1 होने पर देखो , आपका `जे 'लूप s_arr / g या N है - यह O (N) ऑपरेशन है
Glenn Teitelbaum

3

सी

यह सुनिश्चित नहीं है कि मानदंड क्या है, लेकिन चूंकि मैंने एल्गोरिथ्म के साथ मज़े किए, यहाँ मेरी प्रविष्टि है:

void rotate(int* b, int size, int shift)
{
    int *done;
    int *p;
    int i;
    int saved;
    int c;

    p = b;
    done = p;
    saved = *p;
    for (i = 0; i < size; ++i) {
        c = saved;
        p += shift;
        if (p >= b+size) p -= size;
        saved = *p;
        *p = c;
        if (p == done) {
            p += 1;
            done = p;
            saved = *p;
        }
    }
}

मैं इसे एक अच्छे उपाय के लिए भी गोल्फ दूँगा; 126 बाइट्स, कम किए जा सकते हैं:

void r(int*b,int s,int n){int*d,*p,i,t,c;d=p=b;t=*p;for(i=0;i<s;++i){c=t;p+=n;if(p>=b+s)p-=s;t=*p;*p=c;if(p==d){d=++p;t=*p;}}}

3

मुझे यहाँ बहुत सारे C ++ सॉल्यूशन दिखाई नहीं देते हैं, इसलिए मुझे लगा कि मैं इसकी कोशिश करूंगा क्योंकि यह वर्णों की गिनती नहीं करता है।

यह सच है "इन-प्लेस" रोटेशन, इसलिए 0 अतिरिक्त स्थान (तकनीकी रूप से स्वैप और 3 इन्टस को छोड़कर) का उपयोग करता है और चूंकि लूप बिल्कुल एन है, ओ (एन) जटिलता को भी पूरा करता है।

template <class T, size_t N>
void rot(std::array<T,N>& x, int shift)
{
        size_t base=0;
        size_t cur=0; 
        for (int i = 0; i < N; ++i)
        {
                cur=(cur+shift)%N; // figure out where we are going
                if (cur==base)     // exact multiple so we have to hit the mods when we wrap
                {
                        cur++;
                        base++;
                }
                std::swap(x.at(base), x.at(cur)); // use x[base] as holding area
        }
}

नोट: मैंने जानबूझकर उपयोग नहीं किया std::rotateक्योंकि इस तरह का उद्देश्य पराजित करता है
ग्लेन टीइटेलबाम

2

यदि आप बारी-बारी से एन द्वारा घूर्णन के प्रत्येक संभावित चक्र का प्रदर्शन करते हैं (इनमें से जीसीडी (एन, लेन (गिरफ्तार)) हैं), तो आपको केवल एक सरणी तत्व और कुछ राज्य चर की एक ही अस्थायी प्रतिलिपि की आवश्यकता है। इस तरह, पायथन में:

from fractions import gcd

def rotate(arr, n):
    total = len(arr)
    cycles = gcd(n, total)
    for start in range(0, cycles):
        cycle = [i % total for i in range(start, abs(n * total) / cycles, n)]
        stash = arr[cycle[-1]]
        for j in reversed(range(1, len(cycle))):
            arr[cycle[j]] = arr[cycle[j - 1]]
        arr[cycle[0]] = stash

1
मुझे लगता है कि आपके पास सही विचार है, लेकिन आपका cycleचर निरंतर-स्थिर आकार है। जाते ही आपको यह व्यूह बनाना होगा।
कीथ रान्डेल

2

सी (137 अक्षर)

#include <stdio.h>

void rotate(int * array, int n, int k) {
    int todo = (1<<n+1)-1;
    int i = 0, j;
    int tmp = array[0];

    while (todo) {
        if (todo & 1<<i) {
            j = (i-k+n)%n;
            array[i] = todo & 1<<j ? array[j] : tmp;
            todo -= 1<<i;
            i = j;
        } else tmp = array[++i];
    }
}

int main() {
    int a[] = {1,2,3,4,5,6,7,8,9};
    rotate(a, 9, 4);
    for (int i=0; i<9;i++) printf("%d ", a[i]);
    printf("\n");
}

rotate137 पात्रों के लिए उपयुक्त कार्य :

void r(int*a,int n,int k){int m=(1<<n+1)-1,i=0,j,t=a[0];while(m)if(m&1<<i){j=(i-k+n)%n;a[i]=(m&1<<j)?a[j]:t;m-=1<<i;i=j;}else t=a[++i];}

2

फैक्टर में रोटेटेबल सरणियों के लिए एक अंतर्निहित प्रकार होता है <circular>, इसलिए यह वास्तव में एक ओ (1) ऑपरेशन है:

: rotate ( circ n -- )
    neg swap change-circular-start ;

IN: 1 9 [a,b] <circular> dup 6 rotate >array .
{ 4 5 6 7 8 9 1 2 3 }
IN: 1 9 [a,b] <circular> dup 3 rotate >array .
{ 7 8 9 1 2 3 4 5 6 }

बेन वोइगट के प्रभावशाली सी समाधान के बराबर एक कम धोखा कारक

: rotate ( n s -- ) 
    reverse! swap cut-slice [ reverse! ] bi@ 2drop ;

IN: 7 V{ 0 1 2 3 4 5 6 7 8 9 } [ rotate ] keep .
V{ 3 4 5 6 7 8 9 0 1 2 }

2

जावास्क्रिप्ट 45

वैसे भी गोल्फ के लिए गया क्योंकि मुझे गोल्फ पसंद है। यह अधिकतम O (N) पर है जब तक कि tयह सरणी का आकार = है।

function r(o,t){for(;t--;)o.unshift(o.pop())}

tO (N) में किसी भी अनुपात को संभालने के लिए निम्नलिखित का उपयोग किया जा सकता है (58 अक्षरों में वजन):

function r(o,t){for(i=t%o.length;i--;)o.unshift(o.pop())}

वापस नहीं आता है, जगह में सरणी संपादित करता है।


1
+1 के लिएr(o,t) => rot
कॉनर ओ'ब्रायन

1

REBEL - 22

/_(( \d+)+)( \d+)/$3$1

इनपुट: k को अंक के _रूप में उपयोग करते हुए एक पूर्णांक के रूप में व्यक्त किया जाता है , इसके बाद एक स्थान होता है, फिर पूर्णांक का एक स्थान-सीमांकित सरणी।

आउटपुट: एक स्थान, फिर सरणी घुमाई गई।

उदाहरण:

___ 1 2 3 4 5/_(( \d+)+)( \d+)/$3$1

अंतिम स्थिति:

 3 4 5 1 2

स्पष्टीकरण:

प्रत्येक पुनरावृत्ति पर, यह एक _और एक सरणी [array] + tailको प्रतिस्थापित करता है tail + [array]

उदाहरण:

___ 1 2 3 4 5
__ 5 1 2 3 4
_ 4 5 1 2 3
 3 4 5 1 2

मुझे नहीं लगता कि यह O (n) है। एक सरणी की प्रतिलिपि बनाना है O(n), और आप उस nसमय करते हैं।
बेन वोइगट

1

जावा

public static void rotate(int[] arr, int by) {
    int n = arr.length;
    int i = 0;
    int j = 0;
    while (i < n) {
        int k = j;
        int value = arr[k];
        do {
            k = (k + by) % n;
            int tmp = arr[k];
            arr[k] = value;
            value = tmp;
            i++;
        } while (k != j);
        j++;
    }
}

यहां डेमो करें

न्यूनतम जावास्क्रिप्ट, 114 :

function rotate(e,r){n=e.length;i=0;j=0;while(i<n){k=j;v=e[k];do{k=(k+r)%n;t=e[k];e[k]=v;v=t;i++}while(k!=j);j++}}

1

हास्केल

यह वास्तव में θ (n) है, क्योंकि विभाजन k (k) है और जॉइन θ (nk) है। हालांकि स्मृति के बारे में निश्चित नहीं है।

rotate 0 xs = xs
rotate n xs | n >= length xs = rotate (n`mod`(length xs)) xs
            | otherwise = rotate' n xs

rotate' n xs = let (xh,xt) = splitAt n xs in xt++xh

1

अजगर ३

from fractions import gcd
def rotatelist(arr, m):
    n = len(arr)
    m = (-m) % n # Delete this line to change rotation direction
    for i0 in range(gcd(m, n)):
        temp = arr[i0]
        i, j = i0, (i0 + m) % n
        while j != i0:
            arr[i] = arr[j]
            i, j = j, (j + m) % n
        arr[i] = temp

निरंतर स्मृति
O (n) समय जटिलता


0

अजगर

def rotate(a, n): a[:n], a[n:] = a[-n:], a[:-n] 

क्या यह निरंतर मेमोरी का उपयोग करेगा?
सिटुप्य

हम्म ... यकीन नहीं होता।
मैडिसन

यह एक निरंतर मेमोरी ऑपरेशन नहीं है।
माइक्रोबियन

ओह। गुड कॉल ...
मैडिसन

0

अजगर

   import copy
    def rotate(a, r):
        c=copy.copy(a);b=[]
        for i in range(len(a)-r):   b.append(a[r+i]);c.pop();return b+c

सरणी की प्रतिलिपि बनाना निरंतर स्थान नहीं है। @ मैडिसनमाय का उत्तर अनिवार्य रूप से इस कोड के समान होता है जिसमें कई कम वर्ण होते हैं।
ब्लैंकनथ

0

vb.net O (n) (लगातार मेमोरी नहीं)

Function Rotate(Of T)(a() As T, r As Integer ) As T()     
  Dim p = a.Length-r
  Return a.Skip(p).Concat(a.Take(p)).ToArray
End Function

0

माणिक

def rotate(arr, n)
  arr.tap{ (n % arr.size).times { arr.unshift(arr.pop) } }  
end

0

सी (118)

संभवतः कुछ विशिष्टताओं के साथ थोड़ा बहुत उदार था। के लिए आनुपातिक का उपयोग करता है shift % length। यदि एक नकारात्मक बदलाव मूल्य पारित किया जाता है, तो भी विपरीत दिशा में घूमने में सक्षम।

r(int *a,int l,int s){s=s%l<0?s%l+l:s%l;int *t=malloc(4*s);memcpy(t,a+l-s,4*s);memcpy(a+s,a,4*(l-s));memcpy(a,t,4*s);}

0

अजगर 2, 57

def rotate(l,n):
 return l[len(l)-n:len(l)]+l[0:len(l)-n]

अगर केवल l[-n:len(l)-n]इस तरह से काम किया तो मुझे इसकी उम्मीद होगी। यह []किसी कारण से वापस लौटता है ।


0
def r(a,n): return a[n:]+a[:n]

क्या कोई जाँच कर सकता है कि क्या यह वास्तव में आवश्यकताओं को पूरा करता है? मुझे लगता है कि यह करता है, लेकिन मैंने सीएस (अभी तक) का अध्ययन नहीं किया है।


0

सी ++, 136

template<int N>void rotate(int(&a)[N],int k){auto r=[](int*b,int*e){for(int t;--e>b;t=*b,*b++=*e,*e=t);};r(a,a+k);r(a+k,a+N);r(a,a+N);}

0

जावा

पहले k तत्वों के साथ अंतिम k तत्वों को स्वैप करें, और फिर शेष तत्वों को k से घुमाएं। जब आपके पास अंत में कम से कम k तत्व बचे हों, तो उन्हें शेष तत्वों की k% संख्या से घुमाएं। मुझे नहीं लगता कि ऊपर किसी ने भी यह तरीका अपनाया। हर तत्व के लिए ठीक एक स्वैप ऑपरेशन करता है, सब कुछ जगह पर करता है।

public void rotate(int[] nums, int k) {
    k = k % nums.length; // If k > n, reformulate
    rotate(nums, 0, k);
}

private void rotate(int[] nums, int start, int k) {
    if (k > 0) {
        if (nums.length - start > k) { 
            for (int i = 0; i < k; i++) {
                int end = nums.length - k + i;
                int temp = nums[start + i];
                nums[start + i] = nums[end];
                nums[end] = temp;
            }
            rotate(nums, start + k, k); 
        } else {
            rotate(nums, start, k % (nums.length - start)); 
        }
    }
}

0

पर्ल 5 , 42 बाइट्स

sub r{$a=pop;map{unshift@$a,pop@$a}1..pop}

इसे ऑनलाइन आज़माएं!

सबरूटीन पहले पैरामीटर के रूप में घूमने के लिए दूरी और दूसरे के रूप में सरणी के लिए एक संदर्भ लेता है। रोटेशन की दूरी के आधार पर रन टाइम स्थिर है। ऐरे आकार रन टाइम को प्रभावित नहीं करता है। एरे को एक तत्व को दाईं ओर से हटाकर और बाईं ओर रखकर संशोधित किया जाता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.