इसे सॉर्ट करने और तत्वों को अधिकतम करने के लिए सरणी से प्रविष्टियाँ निकालें


13

यह चुनौती एक प्रवेश परीक्षा से लेकर बंद संख्या वाले साइबर सुरक्षा पाठ्यक्रम तक है। वैसे भी इसका साइबर सुरक्षा से कोई लेना-देना नहीं है, यह सिर्फ छात्रों को तार्किक और कोडिंग कौशल का परीक्षण करने के लिए है।

कार्य

एक ऐसा प्रोग्राम लिखें जो किसी सरणी से प्रविष्टियाँ निकालता है ताकि शेष मान कड़ाई से घटते क्रम में क्रमबद्ध हो जाएँ और उनका योग सभी अन्य संभावित घटते क्रमों के बीच अधिकतम हो जाए।

इनपुट और आउटपुट

इनपुट पूर्णांक मानों की एक सरणी होगी जो सभी की तुलना में कड़ाई से अधिक 0और सभी भिन्न होती है । आप यह चुनने के लिए स्वतंत्र हैं कि फ़ाइल, कमांड लाइन या स्टडिन से इनपुट पढ़ना है या नहीं।

आउटपुट एक हो जाएगा उतरते-क्रमबद्ध इनपुट एक है जिसका योग किसी अन्य संभव उतरते-छाँटे गए subarray से अधिक है की subarray।

नोट: [5, 4, 3, 2] का एक अवगुण है [5, 4, 1, 3, 2], भले ही 4और 3आसन्न न हो। सिर्फ इसलिए कि 1पॉप किया गया था।

Bruteforce समाधान

पाठ्यक्रम का सबसे सरल समाधान दिए गए सरणी के सभी संभावित संयोजनों के बीच पुनरावृत्ति होगा और सबसे बड़ी राशि के साथ एक क्रमबद्ध खोज करेगा, जो कि पायथन में होगा :

import itertools

def best_sum_desc_subarray(ary):
    best_sum_so_far = 0
    best_subarray_so_far = []
    for k in range(1, len(ary)):
        for comb in itertools.combinations(ary, k):
            if sum(comb) > best_sum_so_far and all(comb[j] > comb[j+1] for j in range(len(comb)-1)):
                best_subarray_so_far = list(comb)
                best_sum_so_far = sum(comb)
    return best_subarray_so_far

दुर्भाग्य से, जाँचने के बाद कि क्या सरणी को सॉर्ट किया गया है, और इसके तत्वों की राशि की गणना करना है और चूंकि यह ऑपरेशन से के लिए कई बार किया जाएगा , इसलिए असममित समय जटिलता होगी

चुनौती

आपका लक्ष्य उपरोक्त ब्रूटफोर्स से बेहतर समय जटिलता प्राप्त करना है। सबसे छोटी स्पर्शोन्मुख समय जटिलता के साथ समाधान चुनौती का विजेता है। यदि दो समाधानों में समान स्पर्शोन्मुख समय जटिलता है, तो विजेता सबसे छोटी स्पर्शोन्मुख स्थानिक जटिलता वाला होगा।

नोट: आप पढ़ने, लिखने और परमाणु की तुलना बड़ी संख्या पर भी कर सकते हैं ।

नोट: यदि दो या दो से अधिक समाधान हैं, तो उनमें से कोई भी वापस आ जाएगा।

परीक्षण के मामलों

Input:  [200, 100, 400]
Output: [400]

Input:  [4, 3, 2, 1, 5]
Output: [4, 3, 2, 1]

Input:  [50, 40, 30, 20, 10]
Output: [50, 40, 30, 20, 10]

Input:  [389, 207, 155, 300, 299, 170, 158, 65]
Output: [389, 300, 299, 170, 158, 65]

Input:  [19, 20, 2, 18, 13, 14, 8, 9, 4, 6, 16, 1, 15, 12, 3, 7, 17, 5, 10, 11]
Output: [20, 18, 16, 15, 12, 7, 5]

Input:  [14, 12, 24, 21, 6, 10, 19, 1, 5, 8, 17, 7, 9, 15, 23, 20, 25, 11, 13, 4, 3, 22, 18, 2, 16]
Output: [24, 21, 19, 17, 15, 13, 4, 3, 2]

Input:  [25, 15, 3, 6, 24, 30, 23, 7, 1, 10, 16, 29, 12, 13, 22, 8, 17, 14, 20, 11, 9, 18, 28, 21, 26, 27, 4, 2, 19, 5]
Output: [25, 24, 23, 22, 17, 14, 11, 9, 4, 2]

सम्बंधित। (मैं अभी जाँच नहीं कर सकता कि क्या दो एल्गोरिदम वास्तव में बराबर हैं, लेकिन मुझे लगता है कि वे हो सकते हैं।)
मार्टिन एंडर

टिप्पणियाँ विस्तारित चर्चा के लिए नहीं हैं; इस वार्तालाप को बातचीत में स्थानांतरित कर दिया गया है ।
मार्टिन एंडर

जवाबों:


3

पर्ल

यह समय में O (n ^ 2) और अंतरिक्ष में O (n) होना चाहिए

STDIN को एक लाइन पर स्पेस द्वारा अलग किए गए नंबर दें

#!/usr/bin/perl -a
use strict;
use warnings;

# use Data::Dumper;
use constant {
    INFINITY => 9**9**9,
    DEBUG    => 0,
};

# Recover sequence from the 'how' linked list
sub how {
    my @z;
    for (my $h = shift->{how}; $h; $h = $h->[1]) {
        push @z, $h->[0];
    }
    pop @z;
    return join " ", reverse @z;
}

use constant MINIMUM => {
    how  => [-INFINITY, [INFINITY]],
    sum  => -INFINITY,
    next => undef,
};

# Candidates is a linked list of subsequences under consideration
# A given final element will only appear once in the list of candidates
# in combination with the best sum that can be achieved with that final element
# The list of candidates is reverse sorted by final element
my $candidates = {
    # 'how' will represent the sequence that adds up to the given sum as a
    # reversed lisp style list.
    # so e.g. "1, 5, 8" will be represented as [8, [5, [1, INFINITY]]]
    # So the final element will be at the front of 'how'
    how  => [INFINITY],
    # The highest sum that can be reached with any subsequence with the same
    # final element
    sum  => 0,
    # 'next' points to the next candidate
    next => MINIMUM,   # Dummy terminator to simplify program logic
};

for my $num (@F) {
    # Among the candidates on which an extension with $num is valid
    # find the highest sum
    my $max_sum = MINIMUM;
    my $c = \$candidates;
    while ($num < $$c->{how}[0]) {
        if ($$c->{sum} > $max_sum->{sum}) {
            $max_sum = $$c;
            $c = \$$c->{next};
        } else {
            # Remove pointless candidate
            $$c = $$c->{next};
        }
    }

    my $new_sum = $max_sum->{sum} + $num;
    if ($$c->{how}[0] != $num) {
        # Insert a new candidate with a never before seen end element
        # Due to the unique element rule this branch will always be taken
        $$c = { next => $$c };
    } elsif ($new_sum <= $$c->{sum}) {
        # An already known end element but the sum is no improvement
        next;
    }
    $$c->{sum} = $new_sum;
    $$c->{how} = [$num, $max_sum->{how}];
    # print(Dumper($candidates));
    if (DEBUG) {
        print "Adding $num\n";
        for (my $c = $candidates; $c; $c = $c->{next}) {
            printf "sum(%s) = %s\n", how($c), $c->{sum};
        }
        print "------\n";
    }
}

# Find the sequence with the highest sum among the candidates
my $max_sum = MINIMUM;
for (my $c = $candidates; $c; $c = $c->{next}) {
    $max_sum = $c if $c->{sum} > $max_sum->{sum};
}

# And finally print the result
print how($max_sum), "\n";

3

O(nlogn)O(n)

{-# LANGUAGE MultiParamTypeClasses #-}

import qualified Data.FingerTree as F

data S = S
  { sSum :: Int
  , sArr :: [Int]
  } deriving (Show)

instance Monoid S where
  mempty = S 0 []
  mappend _ s = s

instance F.Measured S S where
  measure = id

bestSubarrays :: [Int] -> F.FingerTree S S
bestSubarrays [] = F.empty
bestSubarrays (x:xs) = left F.>< sNew F.<| right'
  where
    (left, right) = F.split (\s -> sArr s > [x]) (bestSubarrays xs)
    sLeft = F.measure left
    sNew = S (x + sSum sLeft) (x : sArr sLeft)
    right' = F.dropUntil (\s -> sSum s > sSum sNew) right

bestSubarray :: [Int] -> [Int]
bestSubarray = sArr . F.measure . bestSubarrays

यह काम किस प्रकार करता है

bestSubarrays xsउस की उप-पंक्तियों का क्रम xs{सबसे बड़ी राशि, सबसे छोटे प्रथम तत्व} के कुशल सीमा रेखा पर है, जो बाईं ओर से दाईं ओर बढ़ती हुई राशि और पहले तत्व को बढ़ाते हुए क्रमबद्ध है।

हम से जाने के bestSubarrays xsलिएbestSubarrays (x:xs)

  1. पहले से कम तत्वों के साथ एक बाईं ओर अनुक्रम विभाजित करें x, और पहले से अधिक तत्वों के साथ एक सही पक्ष x,
  2. xबाईं ओर दाईं ओर के सबसे उप-भाग से जुड़कर एक नई उपप्रजाति खोजें ,
  3. नई सबर्रे की तुलना में छोटी राशि के साथ दाईं ओर से उपप्रकारों का उपसर्ग छोड़ें,
  4. बाईं ओर, नई उप-रेखा और दाईं ओर के शेष भाग को समतल करें।

O(logn)


1

यह उत्तर टन हास्पेल के एक पर फैलता है।

पुनरावृत्ति का उपयोग करके समस्या को गतिशील प्रोग्रामिंग के साथ हल किया जा सकता है

T(i)=ai+max[{0}{T(j)|0j<iaiaj}]

जहां इनपुट अनुक्रम और सूचकांक साथ समाप्त होने वाले किसी भी घटते हुए उप-अनुक्रम का अधिकतम प्राप्त योग है । वास्तविक समाधान को फिर से उपयोग किया जा सकता है का उपयोग करके , जैसा कि निम्नलिखित जंग कोड में होता है।टी ( मैं ) मैं टी(ai)T(i)iT

fn solve(arr: &[usize]) -> Vec<usize> {
    let mut tbl = Vec::new();
    // Compute table with maximum sums of any valid sequence ending
    // with a given index i.
    for i in 0..arr.len() {
        let max = (0..i)
            .filter(|&j| arr[j] >= arr[i])
            .map(|j| tbl[j])
            .max()
            .unwrap_or(0);
        tbl.push(max + arr[i]);
    }
    // Reconstruct an optimal sequence.
    let mut sum = tbl.iter().max().unwrap_or(&0).clone();
    let mut limit = 0;
    let mut result = Vec::new();

    for i in (0..arr.len()).rev() {
        if tbl[i] == sum && arr[i] >= limit {
            limit = arr[i];
            sum -= arr[i];
            result.push(arr[i]);
        }
    }
    assert_eq!(sum, 0);
    result.reverse();
    result
}

fn read_input() -> Vec<usize> {
    use std::io::{Read, stdin};
    let mut s = String::new();
    stdin().read_to_string(&mut s).unwrap();
    s.split(|c: char| !c.is_numeric())
        .filter(|&s| !s.is_empty())
        .map(|s| s.parse().unwrap())
        .collect()
}

fn main() {
    println!("{:?}", solve(&read_input()));
}

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

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