在包含M * N个混洗元素的列表中查找N个元素的M个算术序列

时间:2015-06-28 09:30:28

标签: python algorithm list sequence

问题: 每个具有N个项(具有不同d1,d2,... dm的项)的M个算术进展被作为输入传递,其中术语是混洗的。程序必须按顺序打印M个算术进程中的术语,并且起始项最小。

输入格式: 第一行包含M的值 第二行包含由空格分隔的术语(术语数量将为M * N)

边界条件: 2 <= M <= 5 N> = 3

输出格式: 进度中的术语(每个用空格分隔)按顺序排列,其中进度具有最小的起始术语。

示例输入/输出1:

输入:

2
1 4 8 12 7 16

输出:

1 4 7 8 12 16

说明:

There are two progressions. Hence 6/2 = 3 terms in each progression.
So the first A.M has 1 4 7 and the second has 8 12 16
As 1 < 8, 1 4 7 is printed followed by 8 12 16

示例输入/输出2:

输入:

3
2 6 8 10 15 22 12 11 4

输出:

2 4 6 8 15 22 10 11 12

说明:

There are three progressions. Hence 9/3 = 3 terms in each progression.
So the first A.M has 2 4 6 and the second has 8 15 22. The third has 10 11 12.

注意:我们不能将8 10 12作为第二个进展,因为其余数字11 15 22不适用于算术级数。

示例输入/输出3:

输入:

4
20 24 28 32 41 46 51 50 60 90 10 170 70 36 40 250

输出:

10 90 170 250 20 24 28 32 36 41 46 51 40 50 60 70

示例输入/输出4:

输入:

3
180 66 100 44 120 55 60 400 200 300 33 240

输出:

33 44 55 66 60 120 180 240 100 200 300 400

我的代码(到目前为止):

from __future__ import division
from itertools import permutations

m=int(raw_input())
values=map(int,raw_input().split())
terms=len(values)/m
permutation=list(permutations(values,terms))
lst=[]
for i in range(m):
    for perm in permutation:
        mean=sum(perm)/len(perm)
        temp=list(sorted(perm))
        if temp in lst:
            continue
        if len(perm)%2==0:
            med=(temp[int((len(temp)/2)-1)]+temp[int(len(temp)/2)])/2
            if med==mean:
                lst+=[temp]
        else:
            med=temp[int(len(temp)/2)]
            if med==mean:
                lst+=[temp]
lst=sorted(lst,key=lambda x:x[0])
print lst

我能够列出给定输入中的所有可能的算术序列,但不知道如何从那里开始。

4 个答案:

答案 0 :(得分:1)

def explore(n, terms, seqs):

    if not terms:  # if all terms have been processed, you found a solution
        return {tuple(sum(sorted(seqs), []))}

    result = set()

    for ix, seq in enumerate(seqs):

        new_seqs = list(seqs)
        new_seqs[ix] = seq + [terms[0]]

        if len(seq) == 0:  # if you are adding to an empty sequence
            if ix == 0 or len(seqs[ix - 1]) > 0:  # be sure previous is not empty
                result.update(explore(n, terms[1:], new_seqs))
            break  # don't bother checking following seqs, they are empty

        elif len(seq) == 1:  # you can always add to 1-element seq
            result.update(explore(n, terms[1:], new_seqs))

        elif len(seq) < n and seq[-1] * 2 == seq[-2] + terms[0]:  # is arithmetic?
            result.update(explore(n, terms[1:], new_seqs))

    return result

m = int(raw_input())
terms = sorted(map(int, raw_input().split()))
seqs = [[] for _ in range(m)]

result = explore(len(terms) / m, terms, seqs)

for solution in result:
    print(" ".join(map(str, solution)))

这是一个(不完整的)解决方案,应该对您有所帮助。这个想法是你创建了将术语划分为序列seqs(最初为空)并尝试将术语按升序排列到其中一个序列中,以便

  1. 每个seq是一个算术序列
  2. seqs的第一个元素按升序排列
  3. 所有空seqs都在非空seqs之后

答案 1 :(得分:1)

你可以使用itertools.combinations和Counter dict按降序对列表进行排序:

from itertools import combinations
from collections import Counter
def arith_seq(l, m):
    l.sort(reverse=True)
    terms = len(l) // m
    combs = filter(lambda x: all((x[i + 1] - x[i] == x[1] - x[0]
                                       for i in range(len(x) - 1))), combinations(l, terms))
    out = []
    cn = Counter(l)
    for ele in combs:
        if all(cn[c] > 0 for c in ele):
            out.append(ele[::-1])
            for c in ele:
                cn[c] -= 1
    out.sort()
    return out

输出:

In [15]: ms = [2, 3, 4, 3, 3]
In [16]: for l, m in zip(lsts, ms):
            print(arith_seq(l, m))
   ....:     
[(1, 4, 7), (8, 12, 16)]
[(2, 4, 6), (8, 15, 22), (10, 11, 12)]
[(10, 90, 170, 250), (20, 24, 28, 32), (36, 41, 46, 51), (40, 50, 60, 70)]
[(33, 44, 55, 66), (60, 120, 180, 240), (100, 200, 300, 400)]
[(100, 150, 200, 250), (100, 300, 500, 700), (100, 900, 1700, 2500)]

答案 2 :(得分:0)

我的算法时间复杂度小于O(180 mn)

首先,按升序对序列进行排序。然后

explore(n, m, terms, seqs)
    if m == 0 you find a solution seqs and sort seqs by its first terms. return;
    enumerate 2 elements a, b from the first m+1 elements of terms:
        if there exist a arithmetic sequence S whose first two terms are a, b and length is n:
           explore(n, m - 1, terms - S, seqs + [S])

此算法基于以下效果:排序序列的前m+1个元素必须包含一个算术序列的前两个项。

答案 3 :(得分:0)

#include <iostream>
using namespace std;
void FormingArray(int a, int b, int n, int arr[])
{    
    for (int i = 0; i < n; i++)
    {
        arr[i] = a + (i * b);
    }
}
void PrintingArray(int n, int arr[])
{
    cout<<"The array is: \n";
    for (int i = 0; i < n; i++)
    {
        cout <<"No."<<(i+1)<<" "<< arr[i] << endl;
    }
}
int SubArray(int arr[] , int n) //Sigma Series
{
    int sum = 0;
    for (int i = 0; i < n; i++)
    {
        sum += arr[i];
    }
    return sum;
    
}
int firstNegItem(int arr[],int n) //First Negative Item
{
    int i = 0;
        while(arr[i]>0)
        {
            i++;
            if (arr[i]<0)
            break;
        }
    return(arr[i+1]);
}
int firstPosItem(int arr[],int n) //First Positive Item
{
        int i = 0;
        while(arr[i]<0)
        {
            i++;
            if (arr[i]>0)
            break;
        }
    return(arr[i+1]);
}
void credit() { cout<<"This program is made by Ali Alsaeid \nThanks for choosing this program <3 \n"; }
int main()
{
    int a; //The First Item
    int b; //Array's Base
    int n; //Number of Items
    int* arr = new int(n); //Sizing Array
    cout << "Enter a (First Item), b (Array's Base), n (Number of Items) \n";
    //Input
    cin >> a >> b >> n;
    FormingArray(a,b,n,arr);
    //Output
    PrintingArray(n,arr); 
    cout << "Submission Array is " << SubArray(arr, n) << endl; //Sigma series
    if (b<0 && a>0)
        cout<<"The first negative item is: "<<firstNegItem(arr,n)<<endl;
    else if (b>0 && a<0)
        cout<<"The first positive item is: "<<firstPosItem(arr,n)<<endl;
    credit();
    return 0;
}